summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2008-01-18 08:06:39 +0000
committerDavid Zeuthen <davidz@src.gnome.org>2008-01-18 08:06:39 +0000
commit71500d8d36e2157397d275110c34bbe0d658f1e1 (patch)
tree1ce473cc30ae59237e4b802f39d7cedc5a6e52e6
parent45aaa4ee822956140f3acabc548792f389e584b3 (diff)
downloadgvfs-71500d8d36e2157397d275110c34bbe0d658f1e1.tar.gz
The volume monitor bits of gphoto2 support. The actual backend will follow
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: svn path=/trunk/; revision=1148
-rw-r--r--ChangeLog20
-rw-r--r--hal/ghalvolume.c88
-rw-r--r--hal/ghalvolumemonitor.c122
-rw-r--r--hal/ghalvolumemonitor.h5
-rw-r--r--hal/hal-pool.c31
-rw-r--r--hal/hal-pool.h2
6 files changed, 251 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index d2f6d5f9..140254c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
diff --git a/hal/ghalvolume.c b/hal/ghalvolume.c
index 6705b376..48a886d2 100644
--- a/hal/ghalvolume.c
+++ b/hal/ghalvolume.c
@@ -289,6 +289,36 @@ do_update_from_hal (GHalVolume *mv)
(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)
{
@@ -303,7 +333,14 @@ update_from_hal (GHalVolume *mv, gboolean emit_changed)
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 @@ g_hal_volume_new (GVolumeMonitor *volume_monitor,
GHalVolume *volume;
HalDevice *drive_device;
const char *storage_udi;
+ const char *device_path;
+
+ if (hal_device_has_capability (device, "block"))
+ {
+ storage_udi = hal_device_get_property_string (device, "block.storage_device");
+ if (storage_udi == NULL)
+ return NULL;
- 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;
diff --git a/hal/ghalvolumemonitor.c b/hal/ghalvolumemonitor.c
index ad831779..86abb284 100644
--- a/hal/ghalvolumemonitor.c
+++ b/hal/ghalvolumemonitor.c
@@ -54,6 +54,7 @@ struct _GHalVolumeMonitor {
HalPool *pool;
+ GList *last_camera_devices;;
GList *last_optical_disc_devices;
GList *last_drive_devices;
GList *last_volume_devices;
@@ -67,6 +68,9 @@ struct _GHalVolumeMonitor {
/* 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_drives (GHalVolumeMonitor *monitor);
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 @@ G_DEFINE_DYNAMIC_TYPE (GHalVolumeMonitor, g_hal_volume_monitor, G_TYPE_NATIVE_VO
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_hal_volume_monitor_finalize (GObject *object)
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_hal_volume_monitor_finalize (GObject *object)
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 @@ get_volumes (GVolumeMonitor *volume_monitor)
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 @@ mountpoints_changed (GUnixMountMonitor *mount_monitor,
update_volumes (monitor);
update_mounts (monitor);
update_discs (monitor);
+ update_cameras (monitor);
}
static void
@@ -318,6 +332,7 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
update_volumes (monitor);
update_mounts (monitor);
update_discs (monitor);
+ update_cameras (monitor);
}
void
@@ -327,6 +342,7 @@ g_hal_volume_monitor_force_update (GHalVolumeMonitor *monitor)
update_volumes (monitor);
update_mounts (monitor);
update_discs (monitor);
+ update_cameras (monitor);
}
static void
@@ -342,6 +358,7 @@ hal_changed (HalPool *pool,
update_volumes (monitor);
update_mounts (monitor);
update_discs (monitor);
+ update_cameras (monitor);
}
static GObject *
@@ -396,6 +413,7 @@ g_hal_volume_monitor_constructor (GType type,
update_volumes (monitor);
update_mounts (monitor);
update_discs (monitor);
+ update_cameras (monitor);
the_volume_monitor = monitor;
@@ -651,6 +669,24 @@ find_disc_volume_by_udi (GHalVolumeMonitor *monitor, const char *udi)
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 @@ update_discs (GHalVolumeMonitor *monitor)
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)
{
diff --git a/hal/ghalvolumemonitor.h b/hal/ghalvolumemonitor.h
index 0ec355df..31c39ab8 100644
--- a/hal/ghalvolumemonitor.h
+++ b/hal/ghalvolumemonitor.h
@@ -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 ())
diff --git a/hal/hal-pool.c b/hal/hal-pool.c
index 91e91291..3a19daa0 100644
--- a/hal/hal-pool.c
+++ b/hal/hal-pool.c
@@ -42,7 +42,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
struct _HalPoolPrivate
{
- char *cap_only;
+ char **cap_only;
DBusConnection *dbus_connection;
LibHalContext *hal_ctx;
@@ -54,7 +54,7 @@ G_DEFINE_DYNAMIC_TYPE (HalPool, hal_pool, G_TYPE_OBJECT);
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 @@ hal_pool_init (HalPool *pool)
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 @@ hal_pool_add_device_by_udi (HalPool *pool,
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 @@ hal_pool_add_device_by_udi_and_properties (HalPool *pool,
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 @@ hal_pool_get_dbus_connection (HalPool *pool)
}
HalPool *
-hal_pool_new (const char *cap_only)
+hal_pool_new (char **cap_only)
{
int i;
char **devices;
@@ -311,7 +330,7 @@ hal_pool_new (const char *cap_only)
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...
diff --git a/hal/hal-pool.h b/hal/hal-pool.h
index 0b441f36..1a84793d 100644
--- a/hal/hal-pool.h
+++ b/hal/hal-pool.h
@@ -62,7 +62,7 @@ struct _HalPoolClass
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,