[patch] gvfs gphoto2 vm bits



Hi,

Here's the first half of the gphoto2 support for gvfs. This patch adds
support for creating/destroying GVolume objects in the volume monitor
representing connected cameras supported by gphoto2. The other half is
the actual backend code; I'll submit that later.

Here's a screenshot showing three gphoto2 supported devices.

 http://people.freedesktop.org/~david/gvfs-gphoto2-1.png

      David

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1147)
+++ ChangeLog	(working copy)
@@ -1,3 +1,23 @@
+2008-01-18  David Zeuthen  <davidz redhat com>
+
+	The volume monitor bits of gphoto2 support. The actual backend
+	will follow later. Right now the code is only enabled on Linux,
+	need trivial changes to work on other operating systems.
+
+	* hal/ghalvolume.c: (do_update_from_hal_for_camera),
+	(update_from_hal), (g_hal_volume_new):
+	* hal/ghalvolumemonitor.c: (get_hal_pool),
+	(g_hal_volume_monitor_finalize), (get_volumes),
+	(mountpoints_changed), (mounts_changed),
+	(g_hal_volume_monitor_force_update), (hal_changed),
+	(g_hal_volume_monitor_constructor), (find_camera_volume_by_udi),
+	(update_cameras):
+	* hal/ghalvolumemonitor.h:
+	* hal/hal-pool.c: (hal_pool_finalize), (has_cap_only),
+	(hal_pool_add_device_by_udi),
+	(hal_pool_add_device_by_udi_and_properties), (hal_pool_new):
+	* hal/hal-pool.h:
+
 2008-01-17  Christian Kellner  <gicmo gnome org>
 
 	* daemon/gvfsbackenddav.c: 
Index: hal/ghalvolume.c
===================================================================
--- hal/ghalvolume.c	(revision 1147)
+++ hal/ghalvolume.c	(working copy)
@@ -289,7 +289,37 @@
                           (GDestroyNotify) g_free);
 }
 
+#ifdef _WITH_GPHOTO2
 static void
+do_update_from_hal_for_camera (GHalVolume *v)
+{
+  const char *vendor;
+  const char *product;
+
+  vendor = hal_device_get_property_string (v->drive_device, "usb_device.vendor");
+  product = hal_device_get_property_string (v->drive_device, "usb_device.product");
+
+  if (vendor == NULL)
+    {
+      if (product != NULL)
+        v->name = g_strdup (product);
+      else
+        v->name = g_strdup (_("Camera"));
+    }
+  else
+    {
+      if (product != NULL)
+        v->name = g_strdup_printf ("%s %s", vendor, product);
+      else
+        v->name = g_strdup_printf (_("%s Camera"), vendor);
+    }
+
+  v->icon = g_strdup ("camera");
+  v->mount_path = NULL;
+}
+#endif
+
+static void
 update_from_hal (GHalVolume *mv, gboolean emit_changed)
 {
   char *old_name;
@@ -303,7 +333,14 @@
   g_free (mv->name);
   g_free (mv->icon);
   g_free (mv->mount_path);
-  do_update_from_hal (mv);
+#ifdef _WITH_GPHOTO2
+  if (hal_device_has_capability (mv->device, "camera"))
+    do_update_from_hal_for_camera (mv);
+  else
+    do_update_from_hal (mv);
+#else
+    do_update_from_hal (mv);
+#endif
 
   if (emit_changed)
     {
@@ -380,20 +417,53 @@
   GHalVolume *volume;
   HalDevice *drive_device;
   const char *storage_udi;
+  const char *device_path;
       
-  storage_udi = hal_device_get_property_string (device, "block.storage_device");
-  if (storage_udi == NULL)
-    return NULL;
+  if (hal_device_has_capability (device, "block"))
+    {
+      storage_udi = hal_device_get_property_string (device, "block.storage_device");
+      if (storage_udi == NULL)
+        return NULL;
       
-  drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
-  if (drive_device == NULL)
-    return NULL;
-  
+      drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+      if (drive_device == NULL)
+        return NULL;
+      
+      device_path = hal_device_get_property_string (device, "block.device");
+    }
+#ifdef _WITH_GPHOTO2
+  else if (hal_device_has_capability (device, "camera"))
+    {
+      /* OK, so we abuse storage_udi and drive_device for the USB main
+       * device that holds this interface... 
+       */
+      storage_udi = hal_device_get_property_string (device, "info.parent");
+      if (storage_udi == NULL)
+        return NULL;
+      
+      drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+      if (drive_device == NULL)
+        return NULL;
+
+      /* TODO: other OS'es? Will address this with DK aka HAL 2.0 */
+      device_path = hal_device_get_property_string (drive_device, "linux.device_file");
+      if (strlen (device_path) == 0)
+        device_path = NULL;
+
+      if (foreign_mount_root == NULL)
+        return NULL;
+    }
+#endif
+  else
+    {
+      return NULL;
+    }
+
   volume = g_object_new (G_TYPE_HAL_VOLUME, NULL);
   volume->volume_monitor = volume_monitor;
   g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor));
   volume->mount_path = NULL;
-  volume->device_path = g_strdup (hal_device_get_property_string (device, "block.device"));
+  volume->device_path = g_strdup (device_path);
   volume->device = g_object_ref (device);
   volume->drive_device = g_object_ref (drive_device);
   volume->foreign_mount_root = foreign_mount_root != NULL ? g_object_ref (foreign_mount_root) : NULL;
Index: hal/hal-pool.c
===================================================================
--- hal/hal-pool.c	(revision 1147)
+++ hal/hal-pool.c	(working copy)
@@ -42,7 +42,7 @@
 
 struct _HalPoolPrivate
 {
-  char *cap_only;
+  char **cap_only;
   
   DBusConnection *dbus_connection;
   LibHalContext *hal_ctx;
@@ -54,7 +54,7 @@
 static void
 hal_pool_finalize (HalPool *pool)
 {
-  g_free (pool->priv->cap_only);
+  g_strfreev (pool->priv->cap_only);
 
   dbus_bus_remove_match (pool->priv->dbus_connection,
                          "type='signal',"
@@ -134,6 +134,25 @@
   pool->priv->hal_ctx = NULL;
 }
 
+static gboolean
+has_cap_only (HalPool *pool, HalDevice *device)
+{
+  unsigned int n;
+
+  if (pool->priv->cap_only)
+    return TRUE;
+
+  for (n = 0; pool->priv->cap_only[n] != NULL; n++)
+    {
+      if (hal_device_has_capability (device, pool->priv->cap_only[n]))
+        {
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 static void
 hal_pool_add_device_by_udi (HalPool *pool, 
                             const char *udi, 
@@ -144,7 +163,7 @@
   
   if (device != NULL)
     {
-      if (pool->priv->cap_only != NULL && !hal_device_has_capability (device, pool->priv->cap_only))
+      if (!has_cap_only (pool, device))
         {
           g_object_unref (device);
         } 
@@ -169,7 +188,7 @@
   
   if (device != NULL)
     {
-      if (pool->priv->cap_only != NULL && !hal_device_has_capability (device, pool->priv->cap_only))
+      if (!has_cap_only (pool, device))
         {
           g_object_unref (device);
         } 
@@ -266,7 +285,7 @@
 }
 
 HalPool *
-hal_pool_new (const char *cap_only)
+hal_pool_new (char **cap_only)
 {
   int i;
   char **devices;
@@ -311,7 +330,7 @@
   pool->priv->dbus_connection = dbus_connection;
   pool->priv->hal_ctx = hal_ctx;
   pool->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-  pool->priv->cap_only = g_strdup (cap_only);
+  pool->priv->cap_only = g_strdupv (cap_only);
   
   /* Gah, unfortunately we have to watch all devices as HAL's PropertyModified signal
    * doesn't include the capabilities...
Index: hal/ghalvolumemonitor.c
===================================================================
--- hal/ghalvolumemonitor.c	(revision 1147)
+++ hal/ghalvolumemonitor.c	(working copy)
@@ -54,6 +54,7 @@
 
   HalPool *pool;
 
+  GList *last_camera_devices;;
   GList *last_optical_disc_devices;
   GList *last_drive_devices;
   GList *last_volume_devices;
@@ -67,6 +68,9 @@
   /* we keep volumes/mounts for blank and audio discs separate to handle e.g. mixed discs properly */
   GList *disc_volumes;
   GList *disc_mounts;
+
+  /* Digital cameras (e.g. gphoto2) are kept here */
+  GList *camera_volumes;
 };
 
 static void mountpoints_changed      (GUnixMountMonitor  *mount_monitor,
@@ -80,6 +84,7 @@
 static void update_volumes           (GHalVolumeMonitor *monitor);
 static void update_mounts            (GHalVolumeMonitor *monitor);
 static void update_discs             (GHalVolumeMonitor *monitor);
+static void update_cameras           (GHalVolumeMonitor *monitor);
 
 #define g_hal_volume_monitor_get_type g_hal_volume_monitor_get_type
 G_DEFINE_DYNAMIC_TYPE (GHalVolumeMonitor, g_hal_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR);
@@ -87,8 +92,10 @@
 static HalPool *
 get_hal_pool (void)
 {
+  char *cap_only[] = {"block", "camera", NULL};
+
   if (pool == NULL)
-    pool = hal_pool_new ("block");
+    pool = hal_pool_new (cap_only);
   
   return pool;
 }
@@ -109,6 +116,8 @@
   g_object_unref (monitor->mount_monitor);
   g_object_unref (monitor->pool);
 
+  g_list_foreach (monitor->last_camera_devices, (GFunc)g_object_unref, NULL);
+  g_list_free (monitor->last_optical_disc_devices);
   g_list_foreach (monitor->last_optical_disc_devices, (GFunc)g_object_unref, NULL);
   g_list_free (monitor->last_optical_disc_devices);
   g_list_foreach (monitor->last_drive_devices, (GFunc)g_object_unref, NULL);
@@ -131,6 +140,8 @@
   g_list_free (monitor->disc_volumes);
   g_list_foreach (monitor->disc_mounts, (GFunc)g_object_unref, NULL);
   g_list_free (monitor->disc_mounts);
+  g_list_foreach (monitor->camera_volumes, (GFunc)g_object_unref, NULL);
+  g_list_free (monitor->camera_volumes);
   
   if (G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize) (object);
@@ -164,6 +175,8 @@
   l = g_list_copy (monitor->volumes);
   ll = g_list_copy (monitor->disc_volumes);
   l = g_list_concat (l, ll);
+  ll = g_list_copy (monitor->camera_volumes);
+  l = g_list_concat (l, ll);
 
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
@@ -306,6 +319,7 @@
   update_volumes (monitor);
   update_mounts (monitor);
   update_discs (monitor);
+  update_cameras (monitor);
 }
 
 static void
@@ -318,6 +332,7 @@
   update_volumes (monitor);
   update_mounts (monitor);
   update_discs (monitor);
+  update_cameras (monitor);
 }
 
 void 
@@ -327,6 +342,7 @@
   update_volumes (monitor);
   update_mounts (monitor);
   update_discs (monitor);
+  update_cameras (monitor);
 }
 
 static void
@@ -342,6 +358,7 @@
   update_volumes (monitor);
   update_mounts (monitor);
   update_discs (monitor);
+  update_cameras (monitor);
 }
 
 static GObject *
@@ -396,6 +413,7 @@
   update_volumes (monitor);
   update_mounts (monitor);
   update_discs (monitor);
+  update_cameras (monitor);
 
   the_volume_monitor = monitor;
 
@@ -651,6 +669,24 @@
   return NULL;
 }
 
+#ifdef _WITH_GPHOTO2
+static GHalVolume *
+find_camera_volume_by_udi (GHalVolumeMonitor *monitor, const char *udi)
+{
+  GList *l;
+
+  for (l = monitor->camera_volumes; l != NULL; l = l->next)
+    {
+      GHalVolume *volume = l->data;
+
+      if (g_hal_volume_has_udi (volume, udi))
+	return volume;
+    }
+  
+  return NULL;
+}
+#endif
+
 static gint
 hal_device_compare (HalDevice *a, HalDevice *b)
 {
@@ -1028,6 +1064,90 @@
   monitor->last_optical_disc_devices = new_optical_disc_devices;
 }
 
+static void
+update_cameras (GHalVolumeMonitor *monitor)
+{
+#ifdef _WITH_GPHOTO2
+  GList *new_camera_devices;
+  GList *removed, *added;
+  GList *l, *ll;
+  GHalVolume *volume;
+  const char *udi;
+
+  new_camera_devices = hal_pool_find_by_capability (monitor->pool, "camera");
+  for (l = new_camera_devices; l != NULL; l = ll)
+    {
+      ll = l->next;
+      HalDevice *d = l->data;
+      /*g_warning ("got %s", hal_device_get_udi (d));*/
+      if (! hal_device_get_property_bool (d, "camera.libgphoto2.support"))
+        {
+          /*g_warning ("ignoring %s", hal_device_get_udi (d));*/
+          /* filter out everything that isn't supported by libgphoto2 */
+          new_camera_devices = g_list_delete_link (new_camera_devices, l);
+        }
+    }
+  g_list_foreach (new_camera_devices, (GFunc) g_object_ref, NULL);
+
+  new_camera_devices = g_list_sort (new_camera_devices, (GCompareFunc) hal_device_compare);
+  diff_sorted_lists (monitor->last_camera_devices,
+                     new_camera_devices, (GCompareFunc) hal_device_compare,
+                     &added, &removed);
+
+  for (l = removed; l != NULL; l = l->next)
+    {
+      HalDevice *d = l->data;
+
+      udi = hal_device_get_udi (d);
+      /*g_warning ("camera removing %s", udi);*/
+
+      volume = find_camera_volume_by_udi (monitor, udi);
+      if (volume != NULL)
+        {
+	  g_hal_volume_removed (volume);
+	  monitor->camera_volumes = g_list_remove (monitor->camera_volumes, volume);
+	  g_signal_emit_by_name (monitor, "volume_removed", volume);
+	  g_signal_emit_by_name (volume, "removed");
+	  g_object_unref (volume);
+        }
+    }
+  
+  for (l = added; l != NULL; l = l->next)
+    {
+      HalDevice *d = l->data;
+      char *uri;
+      GFile *foreign_mount_root;
+      int usb_bus_num;
+      int usb_device_num;
+
+      usb_bus_num = hal_device_get_property_int (d, "usb.bus_number");
+      usb_device_num = hal_device_get_property_int (d, "usb.linux.device_number");
+
+      uri = g_strdup_printf ("gphoto2://usb:%03d,%03d", usb_bus_num, usb_device_num);
+      /*g_warning ("uri is '%s'", uri);*/
+      foreign_mount_root = g_file_new_for_uri (uri);
+      g_free (uri);
+
+      udi = hal_device_get_udi (d);
+      /*g_warning ("camera adding %s", udi);*/
+
+      volume = g_hal_volume_new (G_VOLUME_MONITOR (monitor), d, monitor->pool, foreign_mount_root, TRUE, NULL);
+      g_object_unref (foreign_mount_root);
+      if (volume != NULL)
+        {
+          monitor->camera_volumes = g_list_prepend (monitor->camera_volumes, volume);
+          g_signal_emit_by_name (monitor, "volume_added", volume);
+        }
+    }
+
+  g_list_free (added);
+  g_list_free (removed);
+  g_list_foreach (monitor->last_camera_devices, (GFunc)g_object_unref, NULL);
+  g_list_free (monitor->last_camera_devices);
+  monitor->last_camera_devices = new_camera_devices;
+#endif
+}
+
 void 
 g_hal_volume_monitor_register (GIOModule *module)
 {
Index: hal/hal-pool.h
===================================================================
--- hal/hal-pool.h	(revision 1147)
+++ hal/hal-pool.h	(working copy)
@@ -62,7 +62,7 @@
 
 GType            hal_pool_get_type                            (void);
 void             hal_pool_register                            (GIOModule    *module);
-HalPool *        hal_pool_new                                 (const char   *cap_only);
+HalPool *        hal_pool_new                                 (char        **cap_only);
 LibHalContext *  hal_pool_get_hal_ctx                         (HalPool      *pool);
 DBusConnection * hal_pool_get_dbus_connection                 (HalPool      *pool);
 HalDevice *      hal_pool_get_device_by_udi                   (HalPool      *pool, 
Index: hal/ghalvolumemonitor.h
===================================================================
--- hal/ghalvolumemonitor.h	(revision 1147)
+++ hal/ghalvolumemonitor.h	(working copy)
@@ -29,6 +29,11 @@
 #include <gio/gio.h>
 #include <gio/gunixmounts.h>
 
+/* TODO: need to use different properties on HAL for other OS's (!) */
+#ifdef __linux__
+#define _WITH_GPHOTO2
+#endif
+
 G_BEGIN_DECLS
 
 #define G_TYPE_HAL_VOLUME_MONITOR        (g_hal_volume_monitor_get_type ())


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