[cheese] First pass at some reorganization of caps handling



commit 09e9bf8d3298639dc7daf971f96a1139ae34b69f
Author: Filippo Argiolas <filippo argiolas gmail com>
Date:   Sat Dec 12 21:12:53 2009 +0100

    First pass at some reorganization of caps handling
    
    Gobjectify CheeseDevice.  Move video format stuff into CheeseDevice,
    trying to use gstreamer functions whenever possibile (i.e. caps
    manipulating stuff).  Remove framerate code. We just use the maximum
    framerate since some time now and gstreamer is quite good at picking the
    best rate, no need to do that here.

 libcheese/cheese-camera-device-monitor.c |   38 ++--
 libcheese/cheese-camera-device.c         |  393 ++++++++++++++++++++++++-
 libcheese/cheese-camera-device.h         |   50 ++--
 libcheese/cheese-camera.c                |  473 ++++++------------------------
 libcheese/cheese-camera.h                |    2 +-
 src/cheese-prefs-camera-combo.c          |    2 +
 tests/cheese-test-monitor.c              |    5 +-
 7 files changed, 523 insertions(+), 440 deletions(-)
---
diff --git a/libcheese/cheese-camera-device-monitor.c b/libcheese/cheese-camera-device-monitor.c
index 0babe99..0bb869a 100644
--- a/libcheese/cheese-camera-device-monitor.c
+++ b/libcheese/cheese-camera-device-monitor.c
@@ -2,6 +2,7 @@
  * Copyright © 2007,2008 Jaap Haitsma <jaap haitsma org>
  * Copyright © 2007-2009 daniel g. siegel <dgsiegel gnome org>
  * Copyright © 2008 Ryan Zeigler <zeiglerr gmail com>
+ * Copyright © 2009 Filippo Argiolas <filippo argiolas gmail com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -86,7 +87,7 @@ static void
 cheese_camera_device_monitor_added (CheeseCameraDeviceMonitor *monitor,
 				    GUdevDevice *udevice)
 {
-  const char             *device_path;
+  const char             *device_file;
   const char             *gstreamer_src, *product_name;
   const char             *vendor;
   const char             *product;
@@ -115,17 +116,17 @@ cheese_camera_device_monitor_added (CheeseCameraDeviceMonitor *monitor,
     g_print ("Not an usb device, skipping vendor and model id retrieval\n");
   }
 
-  device_path = g_udev_device_get_device_file (udevice);
-  if (device_path == NULL) {
+  device_file = g_udev_device_get_device_file (udevice);
+  if (device_file == NULL) {
     g_warning ("Error getting V4L device");
     return;
   }
 
   /* vbi devices support capture capability too, but cannot be used,
    * so detect them by device name */
-  if (strstr (device_path, "vbi"))
+  if (strstr (device_file, "vbi"))
   {
-    g_print ("Skipping vbi device: %s\n", device_path);
+    g_print ("Skipping vbi device: %s\n", device_file);
     return;
   }
 
@@ -137,13 +138,13 @@ cheese_camera_device_monitor_added (CheeseCameraDeviceMonitor *monitor,
     if (caps == NULL || strstr (caps, ":capture:") == NULL)
     {
       g_print ("Device %s seems to not have the capture capability, (radio tuner?)\n"
-	       "Removing it from device list.\n", device_path);
+	       "Removing it from device list.\n", device_file);
       return;
     }
     gstreamer_src = (v4l_version == 2) ? "v4l2src" : "v4lsrc";
     product_name = g_udev_device_get_property (udevice, "ID_V4L_PRODUCT");
   } else if (v4l_version == 0) {
-    g_warning ("Fix your udev installation to include v4l_id, ignoring %s", device_path);
+    g_warning ("Fix your udev installation to include v4l_id, ignoring %s", device_file);
     return;
   } else {
     g_assert_not_reached ();
@@ -151,17 +152,14 @@ cheese_camera_device_monitor_added (CheeseCameraDeviceMonitor *monitor,
 
   g_print ("\n");
 
-  device = g_new0 (CheeseCameraDevice, 1);
-
-  device->id                = g_strdup (g_udev_device_get_property (udevice, "DEVPATH"));
-  device->video_device      = g_strdup (device_path);
-  device->gstreamer_src     = g_strdup (gstreamer_src);
-  device->product_name      = g_strdup (product_name);
-  device->num_video_formats = 0;
-  device->video_formats     = g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
-  device->supported_resolutions =
-    g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-  //FIXME This will leak a device, we should ref/unref it instead
+  device = cheese_camera_device_new ();
+  g_object_set (G_OBJECT (device),
+                "device-id", g_udev_device_get_property (udevice, "DEVPATH"),
+                "device-file", device_file,
+                "name", product_name,
+                "src", gstreamer_src,
+                NULL);
+
   g_signal_emit (monitor, monitor_signals[ADDED], 0, device);
 }
 
@@ -303,8 +301,8 @@ cheese_camera_device_monitor_class_init (CheeseCameraDeviceMonitorClass *klass)
 					 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 					 G_STRUCT_OFFSET (CheeseCameraDeviceMonitorClass, added),
 					 NULL, NULL,
-					 g_cclosure_marshal_VOID__POINTER,
-					 G_TYPE_NONE, 1, G_TYPE_POINTER);
+					 g_cclosure_marshal_VOID__OBJECT,
+					 G_TYPE_NONE, 1, G_TYPE_OBJECT);
 
   monitor_signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (klass),
 					   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
diff --git a/libcheese/cheese-camera-device.c b/libcheese/cheese-camera-device.c
index 0125d76..4fb5f18 100644
--- a/libcheese/cheese-camera-device.c
+++ b/libcheese/cheese-camera-device.c
@@ -2,6 +2,7 @@
  * Copyright © 2007,2008 Jaap Haitsma <jaap haitsma org>
  * Copyright © 2007-2009 daniel g. siegel <dgsiegel gnome org>
  * Copyright © 2008 Ryan Zeigler <zeiglerr gmail com>
+ * Copyright © 2009 Filippo Argiolas <filippo argiolas gmail com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -22,24 +23,390 @@
   #include <cheese-config.h>
 #endif
 
+#include <glib.h>
+#include <glib/gi18n.h>
+
 #include "cheese-camera-device.h"
 
-void
-cheese_camera_device_free (CheeseCameraDevice *device)
+G_DEFINE_TYPE (CheeseCameraDevice, cheese_camera_device, G_TYPE_OBJECT)
+
+#define CHEESE_CAMERA_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_CAMERA_DEVICE, CheeseCameraDevicePrivate))
+
+static gchar *supported_formats[] =
+{
+  "video/x-raw-rgb",
+  "video/x-raw-yuv",
+  NULL
+};
+
+enum
+{
+  PROP_0,
+  PROP_NAME,
+  PROP_FILE,
+  PROP_ID,
+  PROP_SRC,
+  PROP_CAPS
+};
+
+typedef struct
+{
+  gchar *device;
+  gchar *id;
+  gchar *src;
+  gchar *name;
+
+  GstCaps *caps;
+
+  GList *formats;
+} CheeseCameraDevicePrivate;
+
+static gint
+compare_formats (gconstpointer a, gconstpointer b)
+{
+  const CheeseVideoFormat *c = a;
+  const CheeseVideoFormat *d = b;
+
+  /* descending sort for rectangle area */
+  return (d->width*d->height - c->width*c->height);
+}
+
+static
+GstCaps *cheese_webcam_device_filter_caps (CheeseCameraDevice *device, const GstCaps *caps, GStrv formats)
+{
+/*  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device); */
+  gchar *formats_string = g_strjoinv ("; ", formats);
+  GstCaps *filter = gst_caps_from_string (formats_string);
+  GstCaps *allowed = gst_caps_intersect (caps, filter);
+
+  g_free (formats_string);
+  gst_caps_unref (filter);
+
+  return allowed;
+}
+
+static void
+cheese_camera_device_add_format (CheeseCameraDevice *device, CheeseVideoFormat *format)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+  GList *l;
+  for (l = priv->formats; l != NULL; l = l->next)
+  {
+    CheeseVideoFormat *item = l->data;
+    if ((item != NULL) &&
+        (item->width == format->width) &&
+        (item->height == format->height)) return;
+  }
+
+  priv->formats = g_list_append (priv->formats, format);
+}
+
+static void
+free_formats_list (CheeseCameraDevice *device)
 {
-  guint j;
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
-  for (j = 0; j < device->num_video_formats; j++)
+  GList *l;
+  for (l = priv->formats; l != NULL; l = l->next)
+    g_free (l->data);
+  g_list_free (priv->formats);
+  priv->formats = NULL;
+}
+
+static void
+cheese_webcam_device_update_format_table (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  int i;
+  int num_structures;
+
+  /* FIXME: limit maximum framerate somehow, we don't want those
+   * stupid 100Hz webcams that slow down the whole pipeline for a
+   * merely perceivable refresh reate gain. I'd say let's throw away
+   * everything over 30/1 */
+
+  free_formats_list (device);
+
+  num_structures = gst_caps_get_size (priv->caps);
+  for (i = 0; i < num_structures; i++)
   {
-    g_free (g_array_index (device->video_formats, CheeseVideoFormat, j).framerates);
-    g_free (g_array_index (device->video_formats, CheeseVideoFormat, j).mimetype);
+    GstStructure *structure;
+    const GValue *width, *height;
+    structure = gst_caps_get_structure (priv->caps, i);
+
+    width  = gst_structure_get_value (structure, "width");
+    height = gst_structure_get_value (structure, "height");
+
+    if (G_VALUE_HOLDS_INT (width))
+    {
+      CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
+
+      gst_structure_get_int (structure, "width", &(format->width));
+      gst_structure_get_int (structure, "height", &(format->height));
+      cheese_camera_device_add_format (device, format);
+    }
+    else if (GST_VALUE_HOLDS_INT_RANGE (width))
+    {
+      int min_width, max_width, min_height, max_height;
+      int cur_width, cur_height;
+
+      min_width  = gst_value_get_int_range_min (width);
+      max_width  = gst_value_get_int_range_max (width);
+      min_height = gst_value_get_int_range_min (height);
+      max_height = gst_value_get_int_range_max (height);
+
+      cur_width  = min_width;
+      cur_height = min_height;
+
+      /* Gstreamer will sometimes give us a range with min_xxx == max_xxx,
+       * we use <= here (and not below) to make this work */
+      while (cur_width <= max_width && cur_height <= max_height)
+      {
+        CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
+
+        format->width = cur_width;
+        format->height = cur_height;
+
+        cheese_camera_device_add_format (device, format);
+
+        cur_width  *= 2;
+        cur_height *= 2;
+      }
+
+      cur_width  = max_width;
+      cur_height = max_height;
+      while (cur_width > min_width && cur_height > min_height)
+      {
+        CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
+
+        format->width = cur_width;
+        format->height = cur_height;
+
+        cheese_camera_device_add_format (device, format);
+
+        cur_width  /= 2;
+        cur_height /= 2;
+      }
+    }
+    else
+    {
+      g_critical ("GValue type %s, cannot be handled for resolution width", G_VALUE_TYPE_NAME (width));
+    }
   }
-  g_free (device->video_device);
-  g_free (device->id);
-  g_free (device->gstreamer_src);
-  g_free (device->product_name);
-  g_array_free (device->video_formats, TRUE);
-  if (device->supported_resolutions != NULL)
-    g_hash_table_destroy (device->supported_resolutions);
 }
 
+static void
+cheese_camera_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  switch (prop_id) {
+  case PROP_NAME:
+    g_value_set_string (value, priv->name);
+    break;
+  case PROP_FILE:
+    g_value_set_string (value, priv->device);
+    break;
+  case PROP_ID:
+    g_value_set_string (value, priv->id);
+    break;
+  case PROP_SRC:
+    g_value_set_string (value, priv->src);
+    break;
+  case PROP_CAPS:
+    gst_value_set_caps (value, priv->caps);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+cheese_camera_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+  const GstCaps *new_caps;
+
+  switch (prop_id) {
+  case PROP_NAME:
+    g_free (priv->name);
+    priv->name = g_value_dup_string (value);
+    break;
+  case PROP_ID:
+    g_free (priv->id);
+    priv->id = g_value_dup_string (value);
+    break;
+  case PROP_FILE:
+    g_free (priv->device);
+    priv->device = g_value_dup_string (value);
+    break;
+  case PROP_SRC:
+    g_free (priv->src);
+    priv->src = g_value_dup_string (value);
+    break;
+  case PROP_CAPS:
+    new_caps = gst_value_get_caps (value);
+    if (new_caps != NULL) {
+      gst_caps_unref (priv->caps);
+      priv->caps = cheese_webcam_device_filter_caps (device, new_caps, supported_formats);
+      cheese_webcam_device_update_format_table (device);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+cheese_camera_device_finalize (GObject *object)
+{
+  CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  g_free (priv->device);
+  g_free (priv->id);
+  g_free (priv->src);
+  g_free (priv->name);
+
+  // free_formats_list (priv->formats);
+}
+
+static void
+cheese_camera_device_class_init (CheeseCameraDeviceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize     = cheese_camera_device_finalize;
+  object_class->get_property = cheese_camera_device_get_property;
+  object_class->set_property = cheese_camera_device_set_property;
+
+  g_object_class_install_property (object_class, PROP_NAME,
+                                   g_param_spec_string ("name",
+                                                        NULL, NULL, NULL,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_FILE,
+                                   g_param_spec_string ("device-file",
+                                                        NULL, NULL, NULL,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_ID,
+                                   g_param_spec_string ("device-id",
+                                                        NULL, NULL, NULL,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_SRC,
+                                   g_param_spec_string ("src",
+                                                        NULL, NULL, NULL,
+                                                        G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_CAPS,
+                                   g_param_spec_boxed ("caps",
+                                                       NULL, NULL,
+                                                       GST_TYPE_CAPS,
+                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_type_class_add_private (klass, sizeof (CheeseCameraDevicePrivate));
+}
+
+static void
+cheese_camera_device_init (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+  priv->device = NULL;
+  priv->id = NULL;
+  priv->src = NULL;
+  priv->name = g_strdup(_("Unknown device"));
+  priv->caps = gst_caps_new_empty ();
+
+  priv->formats = NULL;
+}
+
+CheeseCameraDevice *cheese_camera_device_new (void)
+{
+  return g_object_new (CHEESE_TYPE_CAMERA_DEVICE, NULL);
+}
+
+
+/* public methods */
+
+GList *cheese_camera_device_get_format_list (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  return g_list_sort (g_list_copy (priv->formats), compare_formats);
+}
+
+const gchar *cheese_camera_device_get_name (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  return priv->name;
+}
+const gchar *cheese_camera_device_get_id (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  return priv->id;
+}
+const gchar *cheese_camera_device_get_src (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  return priv->src;
+}
+const gchar *cheese_camera_device_get_device_file (CheeseCameraDevice *device)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+
+  return priv->device;
+}
+
+GstCaps *cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
+                                                   CheeseVideoFormat *format)
+{
+  CheeseCameraDevicePrivate *priv =
+    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
+  GstCaps *caps;
+  gint i;
+
+  caps = gst_caps_new_simple (supported_formats[0],
+                              "width", G_TYPE_INT,
+                              format->width,
+                              "height", G_TYPE_INT,
+                              format->height,
+                              NULL);
+
+  for (i = 1; i < g_strv_length (supported_formats); i++)
+  {
+    gst_caps_append (caps,
+                     gst_caps_new_simple (supported_formats[i],
+                                          "width", G_TYPE_INT,
+                                          format->width,
+                                          "height", G_TYPE_INT,
+                                          format->height,
+                                          NULL));
+  }
+
+  if (gst_caps_can_intersect (caps, priv->caps))
+    return caps;
+  else
+    return gst_caps_new_empty ();
+}
diff --git a/libcheese/cheese-camera-device.h b/libcheese/cheese-camera-device.h
index 0f7d305..ec9fcc4 100644
--- a/libcheese/cheese-camera-device.h
+++ b/libcheese/cheese-camera-device.h
@@ -2,6 +2,7 @@
  * Copyright © 2007,2008 Jaap Haitsma <jaap haitsma org>
  * Copyright © 2007-2009 daniel g. siegel <dgsiegel gnome org>
  * Copyright © 2008 Ryan zeigler <zeiglerr gmail com>
+ * Copyright © 2009 Filippo Argiolas <filippo argiolas gmail com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -19,44 +20,49 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
 #ifndef __CHEESE_CAMERA_DEVICE_H__
 #define __CHEESE_CAMERA_DEVICE_H__
 
-#include <glib.h>
+#include <glib-object.h>
+#include <gst/gst.h>
+
 
 G_BEGIN_DECLS
 
+#define CHEESE_TYPE_CAMERA_DEVICE (cheese_camera_device_get_type ())
+#define CHEESE_CAMERA_DEVICE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CHEESE_TYPE_CAMERA_DEVICE, CheeseCameraDevice))
+#define CHEESE_CAMERA_DEVICE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), CHEESE_TYPE_CAMERA_DEVICE, CheeseCameraDeviceClass))
+#define CHEESE_IS_CAMERA_DEVICE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CHEESE_TYPE_CAMERA_DEVICE))
+#define CHEESE_IS_CAMERA_DEVICE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CHEESE_TYPE_CAMERA_DEVICE))
+#define CHEESE_CAMERA_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CHEESE_TYPE_CAMERA_DEVICE, CheeseCameraDeviceClass))
+
+typedef struct
+{
+  GObject parent;
+} CheeseCameraDevice;
+
 typedef struct
 {
-  int numerator;
-  int denominator;
-} CheeseFramerate;
+  GObjectClass parent_class;
+} CheeseCameraDeviceClass;
 
 typedef struct
 {
-  char *mimetype;
   int   width;
   int   height;
-  int   num_framerates;
-  CheeseFramerate *framerates;
-  CheeseFramerate  highest_framerate;
 } CheeseVideoFormat;
 
-typedef struct
-{
-  char *video_device;
-  char *id;
-  char *gstreamer_src;
-  char *product_name;
-  int   num_video_formats;
-  GArray *video_formats;
-
-  /* Hash table for resolution based lookup of video_formats */
-  GHashTable *supported_resolutions;
-} CheeseCameraDevice;
+CheeseCameraDevice        *cheese_camera_device_new (void);
+GstCaps                   *cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
+                                                                     CheeseVideoFormat *format);
+
+GList                     *cheese_camera_device_get_readable_format_list (CheeseCameraDevice *device);
+const gchar               *cheese_camera_device_get_name (CheeseCameraDevice *device);
+const gchar               *cheese_camera_device_get_src (CheeseCameraDevice *device);
+const gchar               *cheese_camera_device_get_id (CheeseCameraDevice *device);
+const gchar               *cheese_camera_device_get_device_file (CheeseCameraDevice *device);
+
 
-void cheese_camera_device_free (CheeseCameraDevice *device);
 
 G_END_DECLS
 
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index 5182a7c..9a567eb 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -33,6 +33,7 @@
 #include <X11/Xlib.h>
 
 #include "cheese-camera.h"
+#include "cheese-camera-device.h"
 #include "cheese-camera-device-monitor.h"
 
 G_DEFINE_TYPE (CheeseCamera, cheese_camera, G_TYPE_OBJECT)
@@ -43,8 +44,6 @@ G_DEFINE_TYPE (CheeseCamera, cheese_camera, G_TYPE_OBJECT)
 
 #define MIN_DEFAULT_RATE 15.0
 
-static void find_highest_framerate (CheeseVideoFormat *format);
-
 enum CheeseCameraError
 {
   CHEESE_CAMERA_ERROR_UNKNOWN,
@@ -298,7 +297,7 @@ cheese_camera_get_video_devices_from_udev (CheeseCamera *camera)
   CheeseCameraDeviceMonitor *monitor;
 
   priv->num_camera_devices = 0;
-  priv->camera_devices = g_ptr_array_new_with_free_func ((GDestroyNotify) cheese_camera_device_free);
+  priv->camera_devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 
   monitor = cheese_camera_device_monitor_new ();
   g_signal_connect (G_OBJECT (monitor), "added",
@@ -313,312 +312,88 @@ cheese_camera_get_video_devices_from_udev (CheeseCamera *camera)
     CheeseCameraDevice *device;
     if (priv->camera_devices == NULL)
       priv->camera_devices = g_ptr_array_new ();
-    device = g_new0 (CheeseCameraDevice, 1);
-    device->num_video_formats = 0;
-    device->video_formats     = g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
-    device->id = g_strdup ("cheese_fake_videodevice");
+    device = cheese_camera_device_new ();
+    g_object_set (device, "device-id", "cheese_fake_device", NULL);
     g_ptr_array_add (priv->camera_devices, device);
   }
 }
 
 static void
-cheese_camera_get_supported_framerates (CheeseVideoFormat *video_format, GstStructure *structure)
-{
-  const GValue *framerates;
-  int           i, j;
-
-  framerates = gst_structure_get_value (structure, "framerate");
-  if (GST_VALUE_HOLDS_FRACTION (framerates))
-  {
-    video_format->num_framerates            = 1;
-    video_format->framerates                = g_new0 (CheeseFramerate, video_format->num_framerates);
-    video_format->framerates[0].numerator   = gst_value_get_fraction_numerator (framerates);
-    video_format->framerates[0].denominator = gst_value_get_fraction_denominator (framerates);
-  }
-  else if (GST_VALUE_HOLDS_LIST (framerates))
-  {
-    video_format->num_framerates = gst_value_list_get_size (framerates);
-    video_format->framerates     = g_new0 (CheeseFramerate, video_format->num_framerates);
-    for (i = 0; i < video_format->num_framerates; i++)
-    {
-      const GValue *value;
-      value                                   = gst_value_list_get_value (framerates, i);
-      video_format->framerates[i].numerator   = gst_value_get_fraction_numerator (value);
-      video_format->framerates[i].denominator = gst_value_get_fraction_denominator (value);
-    }
-  }
-  else if (GST_VALUE_HOLDS_FRACTION_RANGE (framerates))
-  {
-    int           numerator_min, denominator_min, numerator_max, denominator_max;
-    const GValue *fraction_range_min;
-    const GValue *fraction_range_max;
-
-    fraction_range_min = gst_value_get_fraction_range_min (framerates);
-    numerator_min      = gst_value_get_fraction_numerator (fraction_range_min);
-    denominator_min    = gst_value_get_fraction_denominator (fraction_range_min);
-
-    fraction_range_max = gst_value_get_fraction_range_max (framerates);
-    numerator_max      = gst_value_get_fraction_numerator (fraction_range_max);
-    denominator_max    = gst_value_get_fraction_denominator (fraction_range_max);
-    g_print ("FractionRange: %d/%d - %d/%d\n", numerator_min, denominator_min, numerator_max, denominator_max);
-
-    video_format->num_framerates = (numerator_max - numerator_min + 1) * (denominator_max - denominator_min + 1);
-    video_format->framerates     = g_new0 (CheeseFramerate, video_format->num_framerates);
-    int k = 0;
-    for (i = numerator_min; i <= numerator_max; i++)
-    {
-      for (j = denominator_min; j <= denominator_max; j++)
-      {
-        video_format->framerates[k].numerator   = i;
-        video_format->framerates[k].denominator = j;
-        k++;
-      }
-    }
-  }
-  else
-  {
-    g_critical ("GValue type %s, cannot be handled for framerates", G_VALUE_TYPE_NAME (framerates));
-  }
-}
-
-static void
-cheese_camera_add_video_format (CheeseCameraDevice *camera_device,
-                                CheeseVideoFormat *video_format, GstStructure *format_structure)
-{
-  int    i;
-  gchar *resolution;
-
-  cheese_camera_get_supported_framerates (video_format, format_structure);
-  find_highest_framerate (video_format);
-
-  g_print ("%s %d x %d num_framerates %d\n", video_format->mimetype, video_format->width,
-           video_format->height, video_format->num_framerates);
-  for (i = 0; i < video_format->num_framerates; i++)
-  {
-    g_print ("%d/%d ", video_format->framerates[i].numerator,
-             video_format->framerates[i].denominator);
-  }
-
-  resolution = g_strdup_printf ("%ix%i", video_format->width,
-                                video_format->height);
-  i = GPOINTER_TO_INT (g_hash_table_lookup (
-                         camera_device->supported_resolutions,
-                         resolution));
-  if (i)   /* Resolution already added ? */
-  {
-    CheeseVideoFormat *curr_format = &g_array_index (
-      camera_device->video_formats,
-      CheeseVideoFormat, i - 1);
-    float new_framerate = (float) video_format->highest_framerate.numerator /
-                          video_format->highest_framerate.denominator;
-    float curr_framerate = (float) curr_format->highest_framerate.numerator /
-                           curr_format->highest_framerate.denominator;
-    if (new_framerate > curr_framerate)
-    {
-      g_print ("higher framerate replacing existing format\n");
-      *curr_format = *video_format;
-    }
-    else
-      g_print ("already added, skipping\n");
-
-    g_free (resolution);
-    return;
-  }
-
-  g_array_append_val (camera_device->video_formats, *video_format);
-  g_hash_table_insert (camera_device->supported_resolutions, resolution,
-                       GINT_TO_POINTER (camera_device->num_video_formats + 1));
-
-  camera_device->num_video_formats++;
-}
-
-static gint
-cheese_resolution_compare (gconstpointer _a, gconstpointer _b)
-{
-  const CheeseVideoFormat *a = _a;
-  const CheeseVideoFormat *b = _b;
-
-  if (a->width == b->width)
-    return a->height - b->height;
-
-  return a->width - b->width;
-}
-
-static void
-cheese_camera_get_supported_video_formats (CheeseCameraDevice *camera_device, GstCaps *caps)
-{
-  int i;
-  int num_structures;
-
-  num_structures = gst_caps_get_size (caps);
-  for (i = 0; i < num_structures; i++)
-  {
-    GstStructure *structure;
-    const GValue *width, *height;
-    structure = gst_caps_get_structure (caps, i);
-
-    /* only interested in raw formats; we don't want to end up using image/jpeg
-     * (or whatever else the cam may produce) since we won't be able to link
-     * that to ffmpegcolorspace or the effect plugins, which makes it rather
-     * useless (although we could plug a decoder of course) */
-    if (!gst_structure_has_name (structure, "video/x-raw-yuv") &&
-        !gst_structure_has_name (structure, "video/x-raw-rgb"))
-    {
-      continue;
-    }
-
-    width  = gst_structure_get_value (structure, "width");
-    height = gst_structure_get_value (structure, "height");
-
-    if (G_VALUE_HOLDS_INT (width))
-    {
-      CheeseVideoFormat video_format;
-
-      video_format.mimetype = g_strdup (gst_structure_get_name (structure));
-      gst_structure_get_int (structure, "width", &(video_format.width));
-      gst_structure_get_int (structure, "height", &(video_format.height));
-      cheese_camera_add_video_format (camera_device, &video_format, structure);
-    }
-    else if (GST_VALUE_HOLDS_INT_RANGE (width))
-    {
-      int min_width, max_width, min_height, max_height;
-      int cur_width, cur_height;
-
-      min_width  = gst_value_get_int_range_min (width);
-      max_width  = gst_value_get_int_range_max (width);
-      min_height = gst_value_get_int_range_min (height);
-      max_height = gst_value_get_int_range_max (height);
-
-      cur_width  = min_width;
-      cur_height = min_height;
-
-      /* Gstreamer will sometimes give us a range with min_xxx == max_xxx,
-       * we use <= here (and not below) to make this work */
-      while (cur_width <= max_width && cur_height <= max_height)
-      {
-        CheeseVideoFormat video_format;
-
-        video_format.mimetype = g_strdup (gst_structure_get_name (structure));
-        video_format.width    = cur_width;
-        video_format.height   = cur_height;
-        cheese_camera_add_video_format (camera_device, &video_format, structure);
-        cur_width  *= 2;
-        cur_height *= 2;
-      }
-
-      cur_width  = max_width;
-      cur_height = max_height;
-      while (cur_width > min_width && cur_height > min_height)
-      {
-        CheeseVideoFormat video_format;
-
-        video_format.mimetype = g_strdup (gst_structure_get_name (structure));
-        video_format.width    = cur_width;
-        video_format.height   = cur_height;
-        cheese_camera_add_video_format (camera_device, &video_format, structure);
-        cur_width  /= 2;
-        cur_height /= 2;
-      }
-    }
-    else
-    {
-      g_critical ("GValue type %s, cannot be handled for resolution width", G_VALUE_TYPE_NAME (width));
-    }
-  }
-
-  /* Sort the format array (so that it will show sorted in the resolution
-   * selection GUI), and rebuild the hashtable (as that will be invalid after
-   * the sorting) */
-  g_array_sort (camera_device->video_formats, cheese_resolution_compare);
-  g_hash_table_remove_all (camera_device->supported_resolutions);
-  for (i = 0; i < camera_device->num_video_formats; i++)
-  {
-    CheeseVideoFormat *format = &g_array_index (camera_device->video_formats,
-                                                CheeseVideoFormat, i);
-    g_hash_table_insert (camera_device->supported_resolutions,
-                         g_strdup_printf ("%ix%i", format->width,
-                                          format->height),
-                         GINT_TO_POINTER (i + 1));
-  }
-}
-
-static void
 cheese_camera_get_camera_device_data (CheeseCamera       *camera,
-                                      CheeseCameraDevice *camera_device)
+                                      CheeseCameraDevice *device)
 {
   char                *pipeline_desc;
   GstElement          *pipeline;
-  GError              *err;
   GstStateChangeReturn ret;
   GstMessage          *msg;
   GstBus              *bus;
+  gchar               *src;
+  gchar               *devpath;
+  GError              *err = NULL;
 
+  g_object_get (G_OBJECT (device), "device-file", &devpath, "src", &src, NULL);
+
+  pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink",
+                                   src, devpath);
+  pipeline = gst_parse_launch (pipeline_desc, &err);
+  if ((pipeline != NULL) && (err == NULL))
   {
-    pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink",
-                                     camera_device->gstreamer_src,
-                                     camera_device->video_device);
-    err      = NULL;
-    pipeline = gst_parse_launch (pipeline_desc, &err);
-    if ((pipeline != NULL) && (err == NULL))
-    {
-      /* Start the pipeline and wait for max. 10 seconds for it to start up */
-      gst_element_set_state (pipeline, GST_STATE_READY);
-      ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
+    /* Start the pipeline and wait for max. 10 seconds for it to start up */
+    gst_element_set_state (pipeline, GST_STATE_READY);
+    ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
 
-      /* Check if any error messages were posted on the bus */
-      bus = gst_element_get_bus (pipeline);
-      msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
-      gst_object_unref (bus);
+    /* Check if any error messages were posted on the bus */
+    bus = gst_element_get_bus (pipeline);
+    msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
+    gst_object_unref (bus);
 
-      if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS))
-      {
-        GstElement *src;
-        GstPad     *pad;
-        char       *name;
-        GstCaps    *caps;
-
-        src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
-
-        g_object_get (G_OBJECT (src), "device-name", &name, NULL);
-        if (name == NULL)
-          name = "Unknown";
-
-        g_print ("Device: %s (%s)\n", name, camera_device->video_device);
-        pad  = gst_element_get_pad (src, "src");
-        caps = gst_pad_get_caps (pad);
-        gst_object_unref (pad);
-        cheese_camera_get_supported_video_formats (camera_device, caps);
-        gst_caps_unref (caps);
-      }
-      gst_element_set_state (pipeline, GST_STATE_NULL);
-      gst_object_unref (pipeline);
+    if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS))
+    {
+      GstElement *src;
+      GstPad     *pad;
+      char       *name;
+      GstCaps    *caps;
+
+      src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
+
+      g_object_get (G_OBJECT (src), "device-name", &name, NULL);
+      if (name == NULL)
+        name = "Unknown";
+
+      g_print ("Device: %s (%s)\n", name, devpath);
+      pad  = gst_element_get_pad (src, "src");
+      caps = gst_pad_get_caps (pad);
+      gst_object_unref (pad);
+      g_object_set (G_OBJECT (device), "caps", caps, NULL);
+      gst_caps_unref (caps);
     }
-    if (err)
-      g_error_free (err);
-
-    g_free (pipeline_desc);
+    gst_element_set_state (pipeline, GST_STATE_NULL);
+    gst_object_unref (pipeline);
   }
+  if (err)
+    g_error_free (err);
+
+  g_free (pipeline_desc);
+  g_free (devpath);
+  g_free (src);
 }
 
 static void
 cheese_camera_create_fake_format (CheeseCamera *camera, CheeseCameraDevice *device)
 {
-  CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
-
-  CheeseVideoFormat format;
+//  CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
 
   /* Right now just emulate one format: video/x-raw-yuv, 320x240 @ 30 Hz */
+  GstCaps *caps = gst_caps_new_simple ("video/x-raw-yuv",
+                                       "width", G_TYPE_INT,
+                                       320,
+                                       "height", G_TYPE_INT,
+                                       240,
+                                       "framerate", GST_TYPE_FRACTION,
+                                       30, 1,
+                                       NULL);
 
-  format.mimetype                  = g_strdup ("video/x-raw-yuv");
-  format.width                     = 320;
-  format.height                    = 240;
-  format.num_framerates            = 1;
-  format.framerates                = g_new0 (CheeseFramerate, 1);
-  format.framerates[0].numerator   = 30;
-  format.framerates[0].denominator = 1;
-
-  g_array_append_val (device->video_formats, format);
-  priv->current_format = &format;
+  g_object_set (G_OBJECT (device), "caps", caps, NULL);
 }
 
 static void
@@ -641,31 +416,6 @@ cheese_camera_detect_camera_devices (CheeseCamera *camera)
     cheese_camera_create_fake_format (camera, g_ptr_array_index (priv->camera_devices, 0));
 }
 
-static void
-find_highest_framerate (CheeseVideoFormat *format)
-{
-  int framerate_numerator;
-  int framerate_denominator;
-  int i;
-
-  /* Select the highest framerate up to 30 Hz*/
-  framerate_numerator   = 1;
-  framerate_denominator = 1;
-  for (i = 0; i < format->num_framerates; i++)
-  {
-    float framerate = format->framerates[i].numerator / format->framerates[i].denominator;
-    if (framerate > ((float) framerate_numerator / framerate_denominator)
-        && framerate <= 30)
-    {
-      framerate_numerator   = format->framerates[i].numerator;
-      framerate_denominator = format->framerates[i].denominator;
-    }
-  }
-
-  format->highest_framerate.numerator   = framerate_numerator;
-  format->highest_framerate.denominator = framerate_denominator;
-}
-
 static gboolean
 cheese_camera_create_camera_source_bin (CheeseCamera *camera)
 {
@@ -674,6 +424,8 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
   GError *err = NULL;
   char   *camera_input;
 
+  GstCaps *caps;
+
   if (priv->num_camera_devices == 0)
   {
     priv->camera_source_bin = gst_parse_bin_from_description (
@@ -683,75 +435,42 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
   }
   else
   {
-    CheeseVideoFormat  *format;
     int                 i;
-    gchar              *resolution;
     CheeseCameraDevice *selected_camera;
 
     /* If we have a matching video device use that one, otherwise use the first */
     priv->selected_device = 0;
     selected_camera       = g_ptr_array_index (priv->camera_devices, 0);
-    format                = NULL;
+
     for (i = 1; i < priv->num_camera_devices; i++)
     {
       CheeseCameraDevice *device = g_ptr_array_index (priv->camera_devices, i);
-      if (g_strcmp0 (device->video_device, priv->device_name) == 0) {
+      if (g_strcmp0 (cheese_camera_device_get_device_file (device),
+                     priv->device_name) == 0) {
         selected_camera = device;
         priv->selected_device = i;
         break;
       }
     }
 
-    resolution = g_strdup_printf ("%ix%i", priv->x_resolution,
-                                  priv->y_resolution);
-
     /* Use the previously set resolution from gconf if it is set and the
      * camera supports it. */
-    if (priv->x_resolution != 0 && priv->y_resolution != 0)
-    {
-      i = GPOINTER_TO_INT (g_hash_table_lookup (selected_camera->supported_resolutions, resolution));
-      if (i)
-        format = &g_array_index (selected_camera->video_formats,
-                                 CheeseVideoFormat, i - 1);
-    }
+    CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
+    format->width = priv->x_resolution;
+    format->height = priv->y_resolution;
+    caps = cheese_camera_device_get_caps_for_format (selected_camera, format);
 
-    if (!format)
+    if (gst_caps_is_empty (caps))
     {
-      /* Select the highest resolution */
-      format = &(g_array_index (selected_camera->video_formats,
-                                CheeseVideoFormat, 0));
-      for (i = 1; i < selected_camera->num_video_formats; i++)
-      {
-        CheeseVideoFormat *new = &g_array_index (selected_camera->video_formats,
-                                                 CheeseVideoFormat, i);
-        gfloat newrate = new->highest_framerate.numerator /
-                         new->highest_framerate.denominator;
-        if ((new->width + new->height) > (format->width + format->height) &&
-            (newrate >= MIN_DEFAULT_RATE))
-        {
-          format = new;
-        }
-      }
+      gst_caps_unref (caps);
+      g_object_get (G_OBJECT (selected_camera), "caps", &caps, NULL);
     }
 
-    priv->current_format = format;
-    g_free (resolution);
-
-    if (format == NULL)
-      goto fallback;
-
     camera_input = g_strdup_printf (
-      "%s name=video_source device=%s ! capsfilter name=capsfilter caps=video/x-raw-rgb,width=%d,height=%d,framerate=%d/%d;video/x-raw-yuv,width=%d,height=%d,framerate=%d/%d ! identity",
-      selected_camera->gstreamer_src,
-      selected_camera->video_device,
-      format->width,
-      format->height,
-      format->highest_framerate.numerator,
-      format->highest_framerate.denominator,
-      format->width,
-      format->height,
-      format->highest_framerate.numerator,
-      format->highest_framerate.denominator);
+      "%s name=video_source device=%s ! capsfilter name=capsfilter ! identity",
+      cheese_camera_device_get_src (selected_camera),
+      cheese_camera_device_get_device_file (selected_camera));
+
     g_print ("%s\n", camera_input);
 
     priv->camera_source_bin = gst_parse_bin_from_description (camera_input,
@@ -764,6 +483,12 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
 
   priv->video_source = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "video_source");
   priv->capsfilter   = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "capsfilter");
+
+  GST_ERROR ("caps are %" GST_PTR_FORMAT, caps);
+
+  g_object_set (G_OBJECT (priv->capsfilter), "caps", caps, NULL);
+  gst_caps_unref (caps);
+
   return TRUE;
 
 fallback:
@@ -1576,55 +1301,37 @@ cheese_camera_set_device_by_dev_udi (CheeseCamera *camera, char *udi)
   for (i = 0; i < priv->num_camera_devices; i++)
   {
     CheeseCameraDevice *device = g_ptr_array_index (priv->camera_devices, i);
-    if (strcmp (device->id, udi) == 0)
+    if (strcmp (cheese_camera_device_get_id (device), udi) == 0)
     {
-      g_object_set (camera, "device_name", device->video_device, NULL);
+      g_object_set (camera,
+                    "device_name", cheese_camera_device_get_id (device),
+                    NULL);
       break;
     }
   }
 }
 
-GArray *
+GList *
 cheese_camera_get_video_formats (CheeseCamera *camera)
 {
   CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
   CheeseCameraDevice  *device = g_ptr_array_index (priv->camera_devices, priv->selected_device);
 
-  return device->video_formats;
+//  return cheese_camera_device_get_readable_format_list (device);
 }
 
 void
 cheese_camera_set_video_format (CheeseCamera *camera, CheeseVideoFormat *format)
 {
+#if 0
   CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
 
-  GstCaps *new_caps;
-
-  new_caps = gst_caps_new_simple ("video/x-raw-rgb",
-                                  "width", G_TYPE_INT,
-                                  format->width,
-                                  "height", G_TYPE_INT,
-                                  format->height,
-                                  "framerate", GST_TYPE_FRACTION,
-                                  format->highest_framerate.numerator,
-                                  format->highest_framerate.denominator,
-                                  NULL);
-
-  gst_caps_append (new_caps, gst_caps_new_simple ("video/x-raw-yuv",
-                                                  "width", G_TYPE_INT,
-                                                  format->width,
-                                                  "height", G_TYPE_INT,
-                                                  format->height,
-                                                  "framerate", GST_TYPE_FRACTION,
-                                                  format->highest_framerate.numerator,
-                                                  format->highest_framerate.denominator,
-                                                  NULL));
-
-  priv->current_format = format;
+  GstCaps *caps = cheese_camera_device_get_caps_for_format (priv->selected_camera, format);
 
   cheese_camera_stop (camera);
-  g_object_set (priv->capsfilter, "caps", new_caps, NULL);
+  g_object_set (priv->capsfilter, "caps", caps, NULL);
   cheese_camera_play (camera);
+#endif
 }
 
 CheeseVideoFormat *
diff --git a/libcheese/cheese-camera.h b/libcheese/cheese-camera.h
index 763420a..f7f15cf 100644
--- a/libcheese/cheese-camera.h
+++ b/libcheese/cheese-camera.h
@@ -90,7 +90,7 @@ GPtrArray *        cheese_camera_get_camera_devices (CheeseCamera *camera);
 void               cheese_camera_set_device_by_dev_file (CheeseCamera *camera, char *file);
 void               cheese_camera_set_device_by_dev_udi (CheeseCamera *camera, char *udi);
 gboolean           cheese_camera_switch_camera_device (CheeseCamera *camera);
-GArray    *        cheese_camera_get_video_formats (CheeseCamera *camera);
+GList     *        cheese_camera_get_video_formats (CheeseCamera *camera);
 void               cheese_camera_set_video_format (CheeseCamera      *camera,
                                                    CheeseVideoFormat *format);
 void cheese_camera_get_balance_property_range (CheeseCamera *camera,
diff --git a/src/cheese-prefs-camera-combo.c b/src/cheese-prefs-camera-combo.c
index 97f2c32..02e24dc 100644
--- a/src/cheese-prefs-camera-combo.c
+++ b/src/cheese-prefs-camera-combo.c
@@ -95,6 +95,7 @@ cheese_prefs_camera_combo_selection_changed (GtkComboBox *combo_box, CheesePrefs
 static void
 cheese_prefs_camera_combo_synchronize (CheesePrefsWidget *prefs_widget)
 {
+#if 0
   CheesePrefsCameraCombo        *self = CHEESE_PREFS_CAMERA_COMBO (prefs_widget);
   CheesePrefsCameraComboPrivate *priv = CHEESE_PREFS_CAMERA_COMBO_GET_PRIVATE (self);
 
@@ -180,6 +181,7 @@ cheese_prefs_camera_combo_synchronize (CheesePrefsWidget *prefs_widget)
   gtk_widget_set_sensitive (combo_box, num_devices > 1);
 
   g_ptr_array_unref (camera_devices);
+#endif
 }
 
 static void
diff --git a/tests/cheese-test-monitor.c b/tests/cheese-test-monitor.c
index 8c3c65d..c7779c7 100644
--- a/tests/cheese-test-monitor.c
+++ b/tests/cheese-test-monitor.c
@@ -6,7 +6,10 @@ static void
 added_cb (CheeseCameraDeviceMonitor *monitor,
 	  CheeseCameraDevice *device)
 {
-	g_message ("Added new device with ID '%s'", device->id);
+        gchar *id;
+        g_object_get (device, "device-id", &id, NULL);
+	g_message ("Added new device with ID '%s'", id);
+        g_free (id);
 }
 
 static void



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