[patch] gvfs gphoto2 vm bits
- From: David Zeuthen <david fubar dk>
- To: gnome-vfs-list <gnome-vfs-list gnome org>, Alexander Larsson <alexl redhat com>
- Subject: [patch] gvfs gphoto2 vm bits
- Date: Fri, 18 Jan 2008 02:52:28 -0500
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]