]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-camera-monitor.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / libempathy / empathy-camera-monitor.c
index 7028381278c8040f2b76d5c0601d89c240806de6..6e6691120fd501df075be6840389d9aa2e039470 100644 (file)
  * Authors: Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
  */
 
-#include <config.h>
-
-#include <string.h>
-
-#include <telepathy-glib/util.h>
-
+#include "config.h"
 #include "empathy-camera-monitor.h"
+
 #include "cheese-camera-device-monitor.h"
-#include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
 #include "empathy-debug.h"
 
 struct _EmpathyCameraMonitorPrivate
 {
-  CheeseCameraDeviceMonitor *cheese_monitor;
+  EmpathyCameraDeviceMonitor *empathy_monitor;
+  GQueue *cameras;
   gint num_cameras;
 };
 
@@ -43,33 +39,130 @@ enum
   PROP_AVAILABLE,
 };
 
+enum
+{
+  CAMERA_ADDED,
+  CAMERA_REMOVED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
 G_DEFINE_TYPE (EmpathyCameraMonitor, empathy_camera_monitor, G_TYPE_OBJECT);
 
 static EmpathyCameraMonitor *manager_singleton = NULL;
 
+static EmpathyCamera *
+empathy_camera_new (const gchar *id,
+    const gchar *device,
+    const gchar *name)
+{
+  EmpathyCamera *camera = g_slice_new (EmpathyCamera);
+
+  camera->id = g_strdup (id);
+  camera->device = g_strdup (device);
+  camera->name = g_strdup (name);
+
+  return camera;
+}
+
+static EmpathyCamera *
+empathy_camera_copy (EmpathyCamera *camera)
+{
+  return empathy_camera_new (camera->id, camera->device, camera->name);
+}
+
+static void
+empathy_camera_free (EmpathyCamera *camera)
+{
+  g_free (camera->id);
+  g_free (camera->device);
+  g_free (camera->name);
+
+  g_slice_free (EmpathyCamera, camera);
+}
+
+G_DEFINE_BOXED_TYPE (EmpathyCamera, empathy_camera,
+    empathy_camera_copy, empathy_camera_free)
+
+static gint
+empathy_camera_find (gconstpointer a,
+    gconstpointer b)
+{
+  const EmpathyCamera *camera = a;
+  const gchar *id = b;
+
+  return g_strcmp0 (camera->id, id);
+}
+
 static void
-on_camera_added (CheeseCameraDeviceMonitor *device,
+empathy_camera_monitor_free_camera_foreach (gpointer data,
+    gpointer user_data)
+{
+  empathy_camera_free (data);
+}
+
+static void
+on_camera_added (EmpathyCameraDeviceMonitor *device,
     gchar *id,
     gchar *filename,
     gchar *product_name,
     gint api_version,
     EmpathyCameraMonitor *self)
 {
+  EmpathyCamera *camera;
+
+  if (self->priv->cameras == NULL)
+    return;
+
+  camera = empathy_camera_new (id, filename, product_name);
+
+  g_queue_push_tail (self->priv->cameras, camera);
+
   self->priv->num_cameras++;
 
   if (self->priv->num_cameras == 1)
     g_object_notify (G_OBJECT (self), "available");
+
+  g_signal_emit (self, signals[CAMERA_ADDED], 0, camera);
 }
 
 static void
-on_camera_removed (CheeseCameraDeviceMonitor *device,
+on_camera_removed (EmpathyCameraDeviceMonitor *device,
     gchar *id,
     EmpathyCameraMonitor *self)
 {
+  EmpathyCamera *camera;
+  GList *l;
+
+  if (self->priv->cameras == NULL)
+    return;
+
+  l = g_queue_find_custom (self->priv->cameras, id, empathy_camera_find);
+
+  g_return_if_fail (l != NULL);
+
+  camera = l->data;
+
+  g_queue_delete_link (self->priv->cameras, l);
+
   self->priv->num_cameras--;
 
   if (self->priv->num_cameras == 0)
     g_object_notify (G_OBJECT (self), "available");
+
+  g_signal_emit (self, signals[CAMERA_REMOVED], 0, camera);
+
+  empathy_camera_free (camera);
+}
+
+const GList *
+empathy_camera_monitor_get_cameras (EmpathyCameraMonitor *self)
+{
+  if (self->priv->cameras != NULL)
+    return self->priv->cameras->head;
+  else
+    return NULL;
 }
 
 static void
@@ -96,33 +189,13 @@ empathy_camera_monitor_dispose (GObject *object)
 {
   EmpathyCameraMonitor *self = EMPATHY_CAMERA_MONITOR (object);
 
-  tp_clear_object (&self->priv->cheese_monitor);
-
-  G_OBJECT_CLASS (empathy_camera_monitor_parent_class)->dispose (object);
-}
-
-static GObject *
-empathy_camera_monitor_constructor (GType type,
-    guint n_props,
-    GObjectConstructParam *props)
-{
-  GObject *retval;
-
-  if (manager_singleton)
-    {
-      retval = g_object_ref (manager_singleton);
-    }
-  else
-    {
-      retval =
-          G_OBJECT_CLASS (empathy_camera_monitor_parent_class)->
-          constructor (type, n_props, props);
+  tp_clear_object (&self->priv->empathy_monitor);
 
-      manager_singleton = EMPATHY_CAMERA_MONITOR (retval);
-      g_object_add_weak_pointer (retval, (gpointer) & manager_singleton);
-    }
+  g_queue_foreach (self->priv->cameras,
+      empathy_camera_monitor_free_camera_foreach, NULL);
+  tp_clear_pointer (&self->priv->cameras, g_queue_free);
 
-  return retval;
+  G_OBJECT_CLASS (empathy_camera_monitor_parent_class)->dispose (object);
 }
 
 static void
@@ -132,7 +205,7 @@ empathy_camera_monitor_constructed (GObject *object)
 
   G_OBJECT_CLASS (empathy_camera_monitor_parent_class)->constructed (object);
 
-  cheese_camera_device_monitor_coldplug (self->priv->cheese_monitor);
+  empathy_camera_device_monitor_coldplug (self->priv->empathy_monitor);
 }
 
 static void
@@ -141,7 +214,6 @@ empathy_camera_monitor_class_init (EmpathyCameraMonitorClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = empathy_camera_monitor_dispose;
-  object_class->constructor = empathy_camera_monitor_constructor;
   object_class->constructed = empathy_camera_monitor_constructed;
   object_class->get_property = empathy_camera_monitor_get_property;
 
@@ -149,6 +221,20 @@ empathy_camera_monitor_class_init (EmpathyCameraMonitorClass *klass)
       g_param_spec_boolean ("available", "Available",
       "Camera available", TRUE, G_PARAM_READABLE));
 
+  signals[CAMERA_ADDED] =
+      g_signal_new ("added", G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0, NULL, NULL,
+          g_cclosure_marshal_generic,
+          G_TYPE_NONE, 1, EMPATHY_TYPE_CAMERA);
+
+  signals[CAMERA_REMOVED] =
+      g_signal_new ("removed", G_OBJECT_CLASS_TYPE (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0, NULL, NULL,
+          g_cclosure_marshal_generic,
+          G_TYPE_NONE, 1, EMPATHY_TYPE_CAMERA);
+
   g_type_class_add_private (object_class,
       sizeof (EmpathyCameraMonitorPrivate));
 }
@@ -159,16 +245,51 @@ empathy_camera_monitor_init (EmpathyCameraMonitor *self)
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       EMPATHY_TYPE_CAMERA_MONITOR, EmpathyCameraMonitorPrivate);
 
-  self->priv->cheese_monitor = cheese_camera_device_monitor_new ();
+  self->priv->cameras = g_queue_new ();
 
-  g_signal_connect (self->priv->cheese_monitor, "added",
+  self->priv->empathy_monitor = empathy_camera_device_monitor_new ();
+
+  g_signal_connect (self->priv->empathy_monitor, "added",
       G_CALLBACK (on_camera_added), self);
-  g_signal_connect (self->priv->cheese_monitor, "removed",
+  g_signal_connect (self->priv->empathy_monitor, "removed",
       G_CALLBACK (on_camera_removed), self);
+
+#ifndef HAVE_UDEV
+  /* No udev, assume there are cameras present */
+  self->priv->num_cameras = 1;
+#endif
 }
 
 EmpathyCameraMonitor *
 empathy_camera_monitor_dup_singleton (void)
 {
-  return g_object_new (EMPATHY_TYPE_CAMERA_MONITOR, NULL);
+  GObject *retval;
+
+  if (manager_singleton)
+    {
+      retval = g_object_ref (manager_singleton);
+    }
+  else
+    {
+      retval = g_object_new (EMPATHY_TYPE_CAMERA_MONITOR, NULL);
+
+      manager_singleton = EMPATHY_CAMERA_MONITOR (retval);
+      g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
+    }
+
+  return EMPATHY_CAMERA_MONITOR (retval);
+}
+
+EmpathyCameraMonitor *
+empathy_camera_monitor_new (void)
+{
+  return EMPATHY_CAMERA_MONITOR (
+      g_object_new (EMPATHY_TYPE_CAMERA_MONITOR, NULL));
+}
+
+gboolean empathy_camera_monitor_get_available (EmpathyCameraMonitor *self)
+{
+  g_return_val_if_fail (EMPATHY_IS_CAMERA_MONITOR (self), FALSE);
+
+  return self->priv->num_cameras > 0;
 }