[gnome-contacts] Use cheese APIs rather than direct gstreamer to take avatar photo
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] Use cheese APIs rather than direct gstreamer to take avatar photo
- Date: Mon, 3 Sep 2012 11:25:17 +0000 (UTC)
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]