[gnome-contacts] Use cheese APIs rather than direct gstreamer to take avatar photo



commit a803054a057b4c481a30eaabd78eba9732da1421
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Sep 3 13:16:51 2012 +0200

    Use cheese APIs rather than direct gstreamer to take avatar photo
    
    This uses the currently private cheese_widget_get_camera public call,
    which is slated to be made public:
    https://bugzilla.gnome.org/show_bug.cgi?id=683259
    
    I did this after verifying that this is ok with David King.

 configure.ac                    |   47 ++++-------
 src/Makefile.am                 |   10 +-
 src/cheese-flash.h              |    4 +
 src/contacts-avatar-dialog.vala |  176 +++++++++++++++++----------------------
 src/main.vala                   |    8 +-
 vapi/custom.vapi                |   40 +++++++++-
 6 files changed, 146 insertions(+), 139 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5e08f12..20dc967 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,39 +51,26 @@ PKG_CHECK_MODULES(CONTACTS, [$pkg_modules])
 CONTACTS_PACKAGES="--pkg gtk+-3.0 --pkg gio-2.0 --pkg gio-unix-2.0 --pkg folks --pkg folks-telepathy --pkg folks-eds --pkg libnotify"
 AC_SUBST(CONTACTS_PACKAGES)
 
-gstreamers_modules="gdk-x11-3.0
-                    gstreamer-0.10
-                    gstreamer-interfaces-0.10
-		    cheese-gtk >= 3.3.5
-		    cheese
-                    "
+# Optional dependency for the user accounts panel
+AC_ARG_WITH([cheese],
+            AS_HELP_STRING([--with-cheese], [enable cheese webcam support]),,
+            with_cheese=auto)
 
-AC_MSG_CHECKING([whether to enable gstreamer/cheese support])
-AC_ARG_ENABLE([gst],
-    AS_HELP_STRING([--enable-gst], [Whether to enable gstreamer and cheese support @<:@default=auto@:>@]),
-    [], [enable_gst=auto])
-AC_MSG_RESULT([$enable_gst])
-if test "$enable_gst" != "no"; then
-    PKG_CHECK_MODULES(CONTACTS_GSTREAMER,
-                  [$gstreamers_modules],
-                  [have_gst=yes], [have_gst=no])
-    if test "$enable_gst" = "yes" -a "$have_gst" = "no"; then
-        AC_MSG_ERROR([GStreamer/Cheese support was requested but requirements were not met])
-    elif test "$have_gst" = "yes"; then
-        enable_gst=yes
-    else
-        enable_gst=no
-    fi
+if test x"$with_cheese" != x"no" ; then
+   PKG_CHECK_MODULES(CHEESE, gstreamer-0.10 gstreamer-interfaces-0.10 cheese-gtk >= 3.3.5 cheese, [have_cheese=yes], [have_cheese=no])
+   if test x${have_cheese} = xyes; then
+     AC_DEFINE(HAVE_CHEESE, 1, [Define to 1 to enable cheese webcam support])
+   fi
+   if test x${with_cheese} = xyes && test x${have_cheese} = xno; then
+     AC_MSG_ERROR([Cheese configured but not found])
+   fi
+else
+   have_cheese=no
 fi
+AM_CONDITIONAL(BUILD_CHEESE, test x${have_cheese} = xyes)
 
-if test "$enable_gst" = "yes"; then
-    AC_DEFINE([USE_GSTREAMER], 1,
-            [Define to enable gstreamer/cheese support])
-fi
-
-AM_CONDITIONAL(USE_GSTREAMER, test "$enable_gst" = "yes")
-CONTACTS_GSTREAMER_PACKAGES="--pkg gdk-x11-3.0 --pkg gstreamer-0.10 --pkg gstreamer-interfaces-0.10"
-AC_SUBST(CONTACTS_GSTREAMER_PACKAGES)
+CONTACTS_CHEESE_PACKAGES="--pkg gdk-x11-3.0 --pkg gstreamer-0.10 --pkg gstreamer-interfaces-0.10"
+AC_SUBST(CONTACTS_CHEESE_PACKAGES)
 
 #############
 # Resources #
diff --git a/src/Makefile.am b/src/Makefile.am
index b16ed08..2f6ed3e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,9 +15,9 @@ AM_VALAFLAGS = \
 	@CONTACTS_PACKAGES@ \
 	$(NULL)
 
-if USE_GSTREAMER
-AM_VALAFLAGS += -D HAVE_GSTREAMER @CONTACTS_GSTREAMER_PACKAGES@
-AM_CPPFLAGS += $(CONTACTS_GSTREAMER_CFLAGS)
+if BUILD_CHEESE
+AM_VALAFLAGS += -D HAVE_CHEESE @CONTACTS_CHEESE_PACKAGES@
+AM_CPPFLAGS += $(CHEESE_CFLAGS)
 endif
 
 bin_PROGRAMS = gnome-contacts
@@ -69,8 +69,8 @@ gnome_contacts_SOURCES = \
 
 gnome_contacts_LDADD = $(CONTACTS_LIBS) -lm
 
-if USE_GSTREAMER
-gnome_contacts_LDADD += $(CONTACTS_GSTREAMER_LIBS)
+if BUILD_CHEESE
+gnome_contacts_LDADD += $(CHEESE_LIBS)
 gnome_contacts_SOURCES += \
 	cheese-flash.c \
 	$(NULL)
diff --git a/src/cheese-flash.h b/src/cheese-flash.h
index 6248aea..62db42f 100644
--- a/src/cheese-flash.h
+++ b/src/cheese-flash.h
@@ -47,6 +47,10 @@ CheeseFlash *cheese_flash_new (void);
 void cheese_flash_fire (CheeseFlash *flash,
                         GdkRectangle *rect);
 
+#include <cheese/cheese-widget.h>
+
+GObject   *cheese_widget_get_camera (CheeseWidget *widget);
+
 G_END_DECLS
 
 #endif /* _CHEESE_FLASH_H_ */
diff --git a/src/contacts-avatar-dialog.vala b/src/contacts-avatar-dialog.vala
index 1b46aab..e3d23d5 100644
--- a/src/contacts-avatar-dialog.vala
+++ b/src/contacts-avatar-dialog.vala
@@ -16,10 +16,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#if HAVE_GSTREAMER
-using Gst;
-#endif
-
 using Gtk;
 using Folks;
 
@@ -34,12 +30,11 @@ public class Contacts.AvatarDialog : Dialog {
   private Grid view_grid;
   private ContactFrame main_frame;
 
-#if HAVE_GSTREAMER
-  private bool has_device = false;
-  private DrawingArea photobooth_area;
+#if HAVE_CHEESE
   private Cheese.Flash flash;
-  private Pipeline pipeline;
-  private Element sink;
+  private Cheese.CameraDeviceMonitor camera_monitor;
+  private Cheese.Widget cheese;
+  private int num_cameras;
 #endif
 
   private Gdk.Pixbuf? new_pixbuf;
@@ -243,7 +238,6 @@ public class Contacts.AvatarDialog : Dialog {
     chooser.present ();
   }
 
-
   public AvatarDialog (Contact contact) {
     thumbnail_factory = new Gnome.DesktopThumbnailFactory (Gnome.ThumbnailSize.NORMAL);
     this.contact = contact;
@@ -313,21 +307,29 @@ public class Contacts.AvatarDialog : Dialog {
     toolbar.add (the_add_button);
     the_add_button.clicked.connect (select_avatar_file_cb);
 
-#if HAVE_GSTREAMER
-    if (setup_gstreamer_pipeline ()) {
-      var webcam_button = new ToolButton (null, null);
-      webcam_button.set_icon_name ("camera-photo-symbolic");
-      webcam_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
-      webcam_button.is_important = true;
-      toolbar.add (webcam_button);
-      webcam_button.clicked.connect ( (button) => {
-        notebook.set_current_page (2);
-        var xoverlay = this.sink as XOverlay;
-        xoverlay.set_xwindow_id (Gdk.X11Window.get_xid (photobooth_area.get_window ()));
-        pipeline.set_state (State.PLAYING);
+#if HAVE_CHEESE
+    var webcam_button = new ToolButton (null, null);
+    webcam_button.set_icon_name ("camera-photo-symbolic");
+    webcam_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
+    webcam_button.is_important = true;
+    webcam_button.sensitive = false;
+    toolbar.add (webcam_button);
+
+    camera_monitor = new Cheese.CameraDeviceMonitor ();
+    camera_monitor.added.connect ( () => {
+	num_cameras++;
+	webcam_button.sensitive = num_cameras > 0;
+    });
+    camera_monitor.removed.connect ( () => {
+	num_cameras--;
+	webcam_button.sensitive = num_cameras > 0;
+    });
+    camera_monitor.coldplug ();
+
+    webcam_button.clicked.connect ( (button) => {
+	notebook.set_current_page (2);
+	cheese.show ();
       });
-      has_device = true;
-    }
 #endif
 
     frame_grid.show_all ();
@@ -361,70 +363,67 @@ public class Contacts.AvatarDialog : Dialog {
     cancel_button.is_important = true;
     toolbar.add (cancel_button);
     cancel_button.clicked.connect ( (button) => {
-      crop_area.destroy ();
-      notebook.set_current_page (0);
+	crop_area.destroy ();
+	notebook.set_current_page (0);
     });
 
     frame_grid.show_all ();
     notebook.append_page (frame_grid, null);
 
-#if HAVE_GSTREAMER
-    if (has_device) {
-      /* photobooth page */
-      frame_grid = new Grid ();
-      frame_grid.set_orientation (Orientation.VERTICAL);
-
-      photobooth_area = new DrawingArea ();
-      photobooth_area.set_vexpand (true);
-      photobooth_area.set_hexpand (true);
-      frame_grid.add (photobooth_area);
-
-      flash = new Cheese.Flash ();
-
-      toolbar = new Toolbar ();
-      toolbar.get_style_context ().add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
-      toolbar.set_icon_size (IconSize.MENU);
-      toolbar.set_vexpand (false);
-      frame_grid.attach (toolbar, 0, 1, 1, 1);
-
-      accept_button = new ToolButton (null, null);
-      accept_button.set_icon_name ("object-select-symbolic");
-      accept_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
-      accept_button.is_important = true;
-      toolbar.add (accept_button);
-      accept_button.clicked.connect ( (button) => {
-        int x, y;
-        var win = photobooth_area.get_window ();
-        var flash_win = Gdk.get_default_root_window ();
-        flash_win.get_origin (out x, out y);
-        Gdk.Rectangle rect = {};
-        rect.x = x;
-        rect.y = y;
-        rect.width = flash_win.get_width ();
-        rect.height = flash_win.get_height ();
+#if HAVE_CHEESE
+    /* photobooth page */
+    frame_grid = new Grid ();
+    frame_grid.set_orientation (Orientation.VERTICAL);
+
+    cheese = new Cheese.Widget ();
+    cheese.set_vexpand (true);
+    cheese.set_hexpand (true);
+    cheese.set_no_show_all (true);
+    frame_grid.add (cheese);
+
+    flash = new Cheese.Flash ();
+
+    toolbar = new Toolbar ();
+    toolbar.get_style_context ().add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
+    toolbar.set_icon_size (IconSize.MENU);
+    toolbar.set_vexpand (false);
+    frame_grid.attach (toolbar, 0, 1, 1, 1);
+
+    accept_button = new ToolButton (null, null);
+    accept_button.set_icon_name ("object-select-symbolic");
+    accept_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
+    accept_button.is_important = true;
+    toolbar.add (accept_button);
+
+    accept_button.clicked.connect ( (button) => {
+	var camera = cheese.get_camera () as Cheese.Camera;
+
+	var screen = button.get_screen ();
+        Gdk.Rectangle rect = { 0, 0, screen.get_width (), screen.get_height ()};
         flash.fire (rect);
-        if (pipeline != null)
-          pipeline.set_state (State.PAUSED);
-        var pix = Gdk.pixbuf_get_from_window (win, 0, 0,
-                                              photobooth_area.get_allocated_width (),
-                                              photobooth_area.get_allocated_height ());
-        set_crop_widget (pix);
+
+	camera.photo_taken.connect ( (pix) => {
+	    set_crop_widget (pix);
+	    cheese.hide ();
+	  });
+
+	if (!camera.take_photo_pixbuf ()) {
+	    warning ("Unable to take photo");
+	}
       });
 
-      cancel_button = new ToolButton (null, null);
-      cancel_button.set_icon_name ("edit-undo-symbolic");
-      cancel_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
-      cancel_button.is_important = true;
-      toolbar.add (cancel_button);
-      cancel_button.clicked.connect ( (button) => {
-        if (pipeline != null)
-          pipeline.set_state (State.READY);
+    cancel_button = new ToolButton (null, null);
+    cancel_button.set_icon_name ("edit-undo-symbolic");
+    cancel_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
+    cancel_button.is_important = true;
+    toolbar.add (cancel_button);
+    cancel_button.clicked.connect ( (button) => {
         notebook.set_current_page (0);
-      });
+	cheese.hide ();
+    });
 
-      frame_grid.show_all ();
-      notebook.append_page (frame_grid, null);
-    }
+    frame_grid.show_all ();
+    notebook.append_page (frame_grid, null);
 #endif
 
     notebook.set_current_page (0);
@@ -449,10 +448,6 @@ public class Contacts.AvatarDialog : Dialog {
 	  }
 	}
 
-#if HAVE_GSTREAMER
-      pipeline.set_state (State.NULL);
-#endif
-
 	this.destroy ();
       });
 
@@ -460,21 +455,4 @@ public class Contacts.AvatarDialog : Dialog {
 
     grid.show_all ();
   }
-#if HAVE_GSTREAMER
-  private bool setup_gstreamer_pipeline () {
-    pipeline = new Pipeline ("booth_pipeline");
-    var src = ElementFactory.make ("v4l2src", "video");
-    sink = ElementFactory.make ("xvimagesink", "sink");
-    pipeline.add_many (src, sink);
-    src.link (this.sink);
-
-    unowned ParamSpec pspec = (src as PropertyProbe).get_property ("device");
-    if (pspec != null) {
-      unowned ValueArray values = (src as PropertyProbe).probe_and_get_values (pspec);
-      return (values != null);
-    }
-
-    return false;
-  }
-#endif
 }
diff --git a/src/main.vala b/src/main.vala
index f429927..8411cc4 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -27,11 +27,11 @@ main (string[] args) {
 
   Notify.init (_("Contacts"));
 
-#if HAVE_GSTREAMER
-  Gst.init (ref args);
-#endif
-
+#if HAVE_CHEESE
+  Cheese.gtk_init (ref args);
+#else
   Gtk.init (ref args);
+#endif
 
   var app = new App ();
   app.run (args);
diff --git a/vapi/custom.vapi b/vapi/custom.vapi
index 467284c..9a9fefb 100644
--- a/vapi/custom.vapi
+++ b/vapi/custom.vapi
@@ -64,8 +64,46 @@ namespace Um {
 	}
 }
 
-[CCode (cprefix = "Cheese", lower_case_cprefix = "cheese_", cheader_filename = "cheese-flash.h")]
+[CCode (cprefix = "Cheese", lower_case_cprefix = "cheese_", cheader_filename = "cheese/cheese-gtk.h")]
 namespace Cheese {
+	public static void gtk_init ([CCode (array_length_pos = 0.9)] ref unowned string[] argv);
+	[CCode (cheader_filename = "cheese/cheese-camera-device.h")]
+	public class CameraDevice : GLib.Object {
+		[CCode (has_construct_function = false, type = "CheeseCameraDevice*")]
+		public CameraDevice (string uuid, string device_node, string name, uint v4l_api_version) throws GLib.Error;
+	}
+	[CCode (cheader_filename = "cheese/cheese-camera-device-monitor.h")]
+	public class CameraDeviceMonitor : GLib.Object {
+		[CCode (has_construct_function = false, type = "CheeseCameraDeviceMonitor*")]
+		public CameraDeviceMonitor ();
+		public void coldplug ();
+		public signal void added (CameraDevice device);
+		public signal void removed (string uuid);
+	}
+	[CCode (cheader_filename = "cheese/cheese-avatar-chooser.h")]
+	public class AvatarChooser : Gtk.Dialog {
+		[CCode (has_construct_function = false, type = "CheeseAvatarChooser*")]
+		public AvatarChooser ();
+		public Gdk.Pixbuf get_picture ();
+	}
+	public enum WidgetState {
+		NONE,
+		READY,
+		ERROR
+	}
+	[CCode (cheader_filename = "cheese/cheese-widget.h")]
+	public class Widget : Gtk.Widget {
+		[CCode (has_construct_function = false, type = "CheeseWidget*")]
+		public Widget ();
+		public WidgetState state { get; }
+        public unowned GLib.Object get_camera ();
+	}
+	[CCode (cheader_filename = "cheese/cheese-camera.h")]
+	public class Camera : GLib.Object {
+		public bool take_photo_pixbuf ();
+		public signal void photo_taken (Gdk.Pixbuf pixbuf);
+	}
+	[CCode (cheader_filename = "cheese-flash.h")]
 	public class Flash : Gtk.Window {
 		[CCode (has_construct_function = false, type = "CheeseFlash*")]
 		public Flash ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]