diff options
author | David Zeuthen <davidz@redhat.com> | 2008-07-21 21:23:37 +0000 |
---|---|---|
committer | David Zeuthen <davidz@src.gnome.org> | 2008-07-21 21:23:37 +0000 |
commit | 3b86aa16f6ee6e130b9ba146374e94485e7dc02e (patch) | |
tree | 4256eca2f087da321b53d0fb31e47476d7e7ba1d | |
parent | 254da483f3fd9eb7bb6ffa51768fc64fb243e17c (diff) | |
download | gvfs-3b86aa16f6ee6e130b9ba146374e94485e7dc02e.tar.gz |
Separate the hal and gphoto2 volume monitors - this is in part needed to
2008-07-21 David Zeuthen <davidz@redhat.com>
* configure.ac:
* monitor/Makefile.am:
* monitor/hal/*:
* monitor/gphoto2/*:
Separate the hal and gphoto2 volume monitors - this is in part
needed to solve bug #520123.
svn path=/trunk/; revision=1827
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | monitor/Makefile.am | 4 | ||||
-rw-r--r-- | monitor/gphoto2/Makefile.am | 60 | ||||
-rw-r--r-- | monitor/gphoto2/ggphoto2volume.c | 575 | ||||
-rw-r--r-- | monitor/gphoto2/ggphoto2volume.h | 66 | ||||
-rw-r--r-- | monitor/gphoto2/ggphoto2volumemonitor.c | 564 | ||||
-rw-r--r-- | monitor/gphoto2/ggphoto2volumemonitor.h | 54 | ||||
-rw-r--r-- | monitor/gphoto2/gphoto2-volume-monitor-daemon.c | 43 | ||||
-rw-r--r-- | monitor/gphoto2/gphoto2.monitor | 4 | ||||
-rw-r--r-- | monitor/gphoto2/hal-device.c | 297 | ||||
-rw-r--r-- | monitor/gphoto2/hal-device.h | 93 | ||||
-rw-r--r-- | monitor/gphoto2/hal-marshal.c | 163 | ||||
-rw-r--r-- | monitor/gphoto2/hal-marshal.h | 36 | ||||
-rw-r--r-- | monitor/gphoto2/hal-marshal.list | 3 | ||||
-rw-r--r-- | monitor/gphoto2/hal-pool.c | 458 | ||||
-rw-r--r-- | monitor/gphoto2/hal-pool.h | 74 | ||||
-rw-r--r-- | monitor/gphoto2/hal-utils.c | 142 | ||||
-rw-r--r-- | monitor/gphoto2/hal-utils.h | 40 | ||||
-rw-r--r-- | monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in | 3 | ||||
-rw-r--r-- | monitor/hal/ghalvolume.c | 101 | ||||
-rw-r--r-- | monitor/hal/ghalvolumemonitor.c | 163 | ||||
-rw-r--r-- | po/POTFILES.in | 3 |
23 files changed, 2693 insertions, 263 deletions
@@ -1,5 +1,14 @@ 2008-07-21 David Zeuthen <davidz@redhat.com> + * configure.ac: + * monitor/Makefile.am: + * monitor/hal/*: + * monitor/gphoto2/*: + Separate the hal and gphoto2 volume monitors - this is in part + needed to solve bug #520123. + +2008-07-21 David Zeuthen <davidz@redhat.com> + * monitor/proxy/gproxyvolumemonitor.c (g_proxy_volume_monitor_setup_session_bus_connection): Use the correct hash functions for the hash table of existing proxy diff --git a/configure.ac b/configure.ac index a6b0f4f3..df4e1ccf 100644 --- a/configure.ac +++ b/configure.ac @@ -557,6 +557,7 @@ daemon/Makefile monitor/Makefile monitor/proxy/Makefile monitor/hal/Makefile +monitor/gphoto2/Makefile gconf/Makefile programs/Makefile test/Makefile diff --git a/monitor/Makefile.am b/monitor/Makefile.am index 4e3aabde..d4197d52 100644 --- a/monitor/Makefile.am +++ b/monitor/Makefile.am @@ -4,3 +4,7 @@ SUBDIRS = proxy if USE_HAL SUBDIRS += hal endif + +if USE_GPHOTO2 +SUBDIRS += gphoto2 +endif diff --git a/monitor/gphoto2/Makefile.am b/monitor/gphoto2/Makefile.am new file mode 100644 index 00000000..df37aa20 --- /dev/null +++ b/monitor/gphoto2/Makefile.am @@ -0,0 +1,60 @@ + +NULL = + +libexec_PROGRAMS = gvfs-gphoto2-volume-monitor + +BUILT_SOURCES = \ + hal-marshal.h hal-marshal.c + +hal-marshal.h: hal-marshal.list + glib-genmarshal $< --prefix=hal_marshal --header > $@ + +hal-marshal.c: hal-marshal.list + echo "#include \"hal-marshal.h\"" > $@ && glib-genmarshal $< --prefix=hal_marshal --body >> $@ + + +gvfs_gphoto2_volume_monitor_SOURCES = \ + hal-utils.c hal-utils.h \ + hal-marshal.c hal-marshal.h \ + hal-device.c hal-device.h \ + hal-pool.c hal-pool.h \ + gphoto2-volume-monitor-daemon.c \ + ggphoto2volume.c ggphoto2volume.h \ + ggphoto2volumemonitor.c ggphoto2volumemonitor.h \ + $(NULL) + +gvfs_gphoto2_volume_monitor_CFLAGS = \ + -DG_LOG_DOMAIN=\"GVFS-GPhoto2\" \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/monitor/proxy \ + $(GLIB_CFLAGS) \ + $(HAL_CFLAGS) \ + -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \ + -DGVFS_LOCALEDIR=\""$(localedir)"\" \ + -DG_DISABLE_DEPRECATED \ + $(NULL) + +gvfs_gphoto2_volume_monitor_LDFLAGS = \ + $(NULL) + +gvfs_gphoto2_volume_monitor_LDADD = \ + $(GLIB_LIBS) \ + $(HAL_LIBS) \ + $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \ + $(NULL) + +remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors +remote_volume_monitors_DATA = gphoto2.monitor + +servicedir = $(datadir)/dbus-1/services +service_in_files = org.gtk.Private.GPhoto2VolumeMonitor.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +clean-local: + rm -f *~ *.loT $(BUILT_SOURCES) $(service_DATA) + +EXTRA_DIST = hal-marshal.list $(service_in_files) gphoto2.monitor diff --git a/monitor/gphoto2/ggphoto2volume.c b/monitor/gphoto2/ggphoto2volume.c new file mode 100644 index 00000000..1d7a14ff --- /dev/null +++ b/monitor/gphoto2/ggphoto2volume.c @@ -0,0 +1,575 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include <config.h> + +#include <string.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gio/gio.h> + +#include "ggphoto2volume.h" + +#include "hal-utils.h" + +/* Protects all fields of GHalDrive that can change */ +G_LOCK_DEFINE_STATIC(gphoto2_volume); + +struct _GGPhoto2Volume { + GObject parent; + + GVolumeMonitor *volume_monitor; /* owned by volume monitor */ + + char *device_path; + HalDevice *device; + HalDevice *drive_device; + + GFile *foreign_mount_root; + GMount *foreign_mount; + + char *name; + char *icon; +}; + +static void g_gphoto2_volume_volume_iface_init (GVolumeIface *iface); + +G_DEFINE_TYPE_EXTENDED (GGPhoto2Volume, g_gphoto2_volume, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, + g_gphoto2_volume_volume_iface_init)) + +static void +g_gphoto2_volume_finalize (GObject *object) +{ + GGPhoto2Volume *volume; + + volume = G_GPHOTO2_VOLUME (object); + + if (volume->device != NULL) + g_object_unref (volume->device); + + if (volume->foreign_mount_root != NULL) + g_object_unref (volume->foreign_mount_root); + + if (volume->foreign_mount != NULL) + g_object_unref (volume->foreign_mount); + + if (volume->volume_monitor != NULL) + g_object_remove_weak_pointer (G_OBJECT (volume->volume_monitor), (gpointer) &(volume->volume_monitor)); + + g_free (volume->name); + g_free (volume->icon); + + if (G_OBJECT_CLASS (g_gphoto2_volume_parent_class)->finalize) + (*G_OBJECT_CLASS (g_gphoto2_volume_parent_class)->finalize) (object); +} + +static void +g_gphoto2_volume_class_init (GGPhoto2VolumeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_gphoto2_volume_finalize; +} + +static void +g_gphoto2_volume_init (GGPhoto2Volume *gphoto2_volume) +{ +} + +static gboolean +changed_in_idle (gpointer data) +{ + GGPhoto2Volume *volume = data; + + g_signal_emit_by_name (volume, "changed"); + if (volume->volume_monitor != NULL) + g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume); + g_object_unref (volume); + + return FALSE; +} + +static char ** +dupv_and_uniqify (char **str_array) +{ + int n, m, o; + int len; + char **result; + + result = g_strdupv (str_array); + len = g_strv_length (result); + + for (n = 0; n < len; n++) + { + char *s = result[n]; + for (m = n + 1; m < len; m++) + { + char *p = result[m]; + if (strcmp (s, p) == 0) + { + for (o = m + 1; o < len; o++) + result[o - 1] = result[o]; + len--; + result[len] = NULL; + m--; + } + } + } + + return result; +} + +static void +do_update_from_hal_for_camera (GGPhoto2Volume *v) +{ + const char *vendor; + const char *product; + const char *icon_from_hal; + const char *name_from_hal; + gboolean is_audio_player; + + vendor = hal_device_get_property_string (v->drive_device, "usb_device.vendor"); + product = hal_device_get_property_string (v->drive_device, "usb_device.product"); + icon_from_hal = hal_device_get_property_string (v->device, "info.desktop.icon"); + name_from_hal = hal_device_get_property_string (v->device, "info.desktop.name"); + + is_audio_player = hal_device_has_capability (v->device, "portable_audio_player"); + + v->name = NULL; + if (strlen (name_from_hal) > 0) + v->name = g_strdup (name_from_hal); + else if (vendor == NULL) + { + if (product != NULL) + v->name = g_strdup (product); + } + else + { + if (product != NULL) + v->name = g_strdup_printf ("%s %s", vendor, product); + else + { + if (is_audio_player) + { + /* Translators: %s is the device vendor */ + v->name = g_strdup_printf (_("%s Audio Player"), vendor); + } + else + { + /* Translators: %s is the device vendor */ + v->name = g_strdup_printf (_("%s Camera"), vendor); + } + } + } + if (v->name == NULL) + { + if (is_audio_player) + v->name = g_strdup (_("Audio Player")); + else + v->name = g_strdup (_("Camera")); + } + + if (strlen (icon_from_hal) > 0) + v->icon = g_strdup (icon_from_hal); + else if (is_audio_player) + v->icon = g_strdup ("multimedia-player"); + else + v->icon = g_strdup ("camera"); + + g_object_set_data_full (G_OBJECT (v), + "hal-storage-device-capabilities", + dupv_and_uniqify (hal_device_get_property_strlist (v->device, "info.capabilities")), + (GDestroyNotify) g_strfreev); +} + +static void +update_from_hal (GGPhoto2Volume *mv, gboolean emit_changed) +{ + char *old_name; + char *old_icon; + + G_LOCK (gphoto2_volume); + + old_name = g_strdup (mv->name); + old_icon = g_strdup (mv->icon); + + g_free (mv->name); + g_free (mv->icon); + + do_update_from_hal_for_camera (mv); + + if (emit_changed) + { + if (old_name == NULL || + old_icon == NULL || + strcmp (old_name, mv->name) != 0 || + strcmp (old_icon, mv->icon) != 0) + g_idle_add (changed_in_idle, g_object_ref (mv)); + } + g_free (old_name); + g_free (old_icon); + + G_UNLOCK (gphoto2_volume); +} + +static void +hal_changed (HalDevice *device, const char *key, gpointer user_data) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (user_data); + + /*g_warning ("hal modifying %s (property %s changed)", gphoto2_volume->device_path, key);*/ + update_from_hal (gphoto2_volume, TRUE); +} + +GGPhoto2Volume * +g_gphoto2_volume_new (GVolumeMonitor *volume_monitor, + HalDevice *device, + HalPool *pool, + GFile *foreign_mount_root) +{ + GGPhoto2Volume *volume; + HalDevice *drive_device; + const char *storage_udi; + const char *device_path; + + g_return_val_if_fail (volume_monitor != NULL, NULL); + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (pool != NULL, NULL); + g_return_val_if_fail (foreign_mount_root != NULL, NULL); + + if (!hal_device_has_capability (device, "camera") || + (hal_device_has_capability (device, "portable_audio_player") && + hal_device_get_property_bool (device, "camera.libgphoto2.support"))) + return NULL; + + /* 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; + + volume = g_object_new (G_TYPE_GPHOTO2_VOLUME, NULL); + volume->volume_monitor = volume_monitor; + g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor)); + 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; + + g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, volume, 0); + g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, volume, 0); + + update_from_hal (volume, FALSE); + + return volume; +} + +void +g_gphoto2_volume_removed (GGPhoto2Volume *volume) +{ + ; +} + +static GIcon * +g_gphoto2_volume_get_icon (GVolume *volume) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + GIcon *icon; + + G_LOCK (gphoto2_volume); + icon = g_themed_icon_new (gphoto2_volume->icon); + G_UNLOCK (gphoto2_volume); + return icon; +} + +static char * +g_gphoto2_volume_get_name (GVolume *volume) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + char *name; + + G_LOCK (gphoto2_volume); + name = g_strdup (gphoto2_volume->name); + G_UNLOCK (gphoto2_volume); + + return name; +} + +static char * +g_gphoto2_volume_get_uuid (GVolume *volume) +{ + return NULL; +} + +static gboolean +g_gphoto2_volume_can_mount (GVolume *volume) +{ + return TRUE; +} + +static gboolean +g_gphoto2_volume_can_eject (GVolume *volume) +{ + return FALSE; +} + +static gboolean +g_gphoto2_volume_should_automount (GVolume *volume) +{ + return TRUE; +} + +static GDrive * +g_gphoto2_volume_get_drive (GVolume *volume) +{ + return NULL; +} + +static GMount * +g_gphoto2_volume_get_mount (GVolume *volume) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + GMount *mount; + + G_LOCK (gphoto2_volume); + mount = NULL; + if (gphoto2_volume->foreign_mount != NULL) + mount = g_object_ref (gphoto2_volume->foreign_mount); + G_UNLOCK (gphoto2_volume); + + return mount; +} + +gboolean +g_gphoto2_volume_has_udi (GGPhoto2Volume *volume, + const char *udi) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + gboolean res; + + G_LOCK (gphoto2_volume); + res = FALSE; + if (gphoto2_volume->device != NULL) + res = strcmp (hal_device_get_udi (gphoto2_volume->device), udi) == 0; + G_UNLOCK (gphoto2_volume); + return res; +} + +static void +foreign_mount_unmounted (GMount *mount, gpointer user_data) +{ + GGPhoto2Volume *volume = G_GPHOTO2_VOLUME (user_data); + gboolean check; + + G_LOCK (gphoto2_volume); + check = volume->foreign_mount == mount; + G_UNLOCK (gphoto2_volume); + if (check) + g_gphoto2_volume_adopt_foreign_mount (volume, NULL); +} + +void +g_gphoto2_volume_adopt_foreign_mount (GGPhoto2Volume *volume, GMount *foreign_mount) +{ + G_LOCK (gphoto2_volume); + if (volume->foreign_mount != NULL) + g_object_unref (volume->foreign_mount); + + if (foreign_mount != NULL) + { + volume->foreign_mount = g_object_ref (foreign_mount); + g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0); + } + else + volume->foreign_mount = NULL; + + g_idle_add (changed_in_idle, g_object_ref (volume)); + G_UNLOCK (gphoto2_volume); +} + +gboolean +g_gphoto2_volume_has_foreign_mount_root (GGPhoto2Volume *volume, + GFile *mount_root) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + gboolean res; + + G_LOCK (gphoto2_volume); + res = FALSE; + if (gphoto2_volume->foreign_mount_root != NULL) + res = g_file_equal (gphoto2_volume->foreign_mount_root, mount_root); + G_UNLOCK (gphoto2_volume); + + return res; +} + + + +typedef struct +{ + GGPhoto2Volume *enclosing_volume; + GAsyncReadyCallback callback; + gpointer user_data; +} ForeignMountOp; + +static void +mount_foreign_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + ForeignMountOp *data = user_data; + data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data); + g_free (data); +} + +static void +g_gphoto2_volume_mount (GVolume *volume, + GMountMountFlags flags, + GMountOperation *mount_operation, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + ForeignMountOp *data; + + /*g_warning ("gphoto2_volume_mount (can_mount=%d foreign=%p device_path=%s)", + g_gphoto2_volume_can_mount (volume), + gphoto2_volume->foreign_mount_root, + gphoto2_volume->device_path);*/ + + G_LOCK (gphoto2_volume); + + data = g_new0 (ForeignMountOp, 1); + data->enclosing_volume = gphoto2_volume; + data->callback = callback; + data->user_data = user_data; + + g_file_mount_enclosing_volume (gphoto2_volume->foreign_mount_root, + 0, + mount_operation, + cancellable, + mount_foreign_callback, + data); + + G_UNLOCK (gphoto2_volume); +} + +static gboolean +g_gphoto2_volume_mount_finish (GVolume *volume, + GAsyncResult *result, + GError **error) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + gboolean res; + + G_LOCK (gphoto2_volume); + res = g_file_mount_enclosing_volume_finish (gphoto2_volume->foreign_mount_root, result, error); + G_UNLOCK (gphoto2_volume); + + return res; +} + +static char * +g_gphoto2_volume_get_identifier (GVolume *volume, + const char *kind) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + char *id; + + G_LOCK (gphoto2_volume); + id = NULL; + if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0) + id = g_strdup (hal_device_get_udi (gphoto2_volume->device)); + else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0) + id = g_strdup (gphoto2_volume->device_path); + G_UNLOCK (gphoto2_volume); + + return id; +} + +static char ** +g_gphoto2_volume_enumerate_identifiers (GVolume *volume) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + GPtrArray *res; + + G_LOCK (gphoto2_volume); + + res = g_ptr_array_new (); + + g_ptr_array_add (res, + g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI)); + + if (gphoto2_volume->device_path && *gphoto2_volume->device_path != 0) + g_ptr_array_add (res, + g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE)); + + /* Null-terminate */ + g_ptr_array_add (res, NULL); + + G_UNLOCK (gphoto2_volume); + + return (char **)g_ptr_array_free (res, FALSE); +} + +static GFile * +g_gphoto2_volume_get_activation_root (GVolume *volume) +{ + GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume); + + return g_object_ref (gphoto2_volume->foreign_mount_root); +} + +static void +g_gphoto2_volume_volume_iface_init (GVolumeIface *iface) +{ + iface->get_name = g_gphoto2_volume_get_name; + iface->get_icon = g_gphoto2_volume_get_icon; + iface->get_uuid = g_gphoto2_volume_get_uuid; + iface->get_drive = g_gphoto2_volume_get_drive; + iface->get_mount = g_gphoto2_volume_get_mount; + iface->can_mount = g_gphoto2_volume_can_mount; + iface->can_eject = g_gphoto2_volume_can_eject; + iface->should_automount = g_gphoto2_volume_should_automount; + iface->mount_fn = g_gphoto2_volume_mount; + iface->mount_finish = g_gphoto2_volume_mount_finish; + iface->eject = NULL; + iface->eject_finish = NULL; + iface->get_identifier = g_gphoto2_volume_get_identifier; + iface->enumerate_identifiers = g_gphoto2_volume_enumerate_identifiers; + iface->get_activation_root = g_gphoto2_volume_get_activation_root; +} diff --git a/monitor/gphoto2/ggphoto2volume.h b/monitor/gphoto2/ggphoto2volume.h new file mode 100644 index 00000000..20fe486a --- /dev/null +++ b/monitor/gphoto2/ggphoto2volume.h @@ -0,0 +1,66 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __G_GPHOTO2_VOLUME_H__ +#define __G_GPHOTO2_VOLUME_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +#include "hal-pool.h" +#include "ggphoto2volumemonitor.h" + +G_BEGIN_DECLS + +#define G_TYPE_GPHOTO2_VOLUME (g_gphoto2_volume_get_type ()) +#define G_GPHOTO2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_GPHOTO2_VOLUME, GGPhoto2Volume)) +#define G_GPHOTO2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_GPHOTO2_VOLUME, GGPhoto2VolumeClass)) +#define G_IS_GPHOTO2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_GPHOTO2_VOLUME)) +#define G_IS_GPHOTO2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_GPHOTO2_VOLUME)) + +typedef struct _GGPhoto2VolumeClass GGPhoto2VolumeClass; + +struct _GGPhoto2VolumeClass { + GObjectClass parent_class; +}; + +GType g_gphoto2_volume_get_type (void) G_GNUC_CONST; + +GGPhoto2Volume *g_gphoto2_volume_new (GVolumeMonitor *volume_monitor, + HalDevice *device, + HalPool *pool, + GFile *foreign_mount_root); + +gboolean g_gphoto2_volume_has_udi (GGPhoto2Volume *volume, + const char *udi); + +gboolean g_gphoto2_volume_has_foreign_mount_root (GGPhoto2Volume *volume, + GFile *mount_root); + +void g_gphoto2_volume_adopt_foreign_mount (GGPhoto2Volume *volume, + GMount *foreign_mount); + +void g_gphoto2_volume_removed (GGPhoto2Volume *volume); + +G_END_DECLS + +#endif /* __G_GPHOTO2_VOLUME_H__ */ diff --git a/monitor/gphoto2/ggphoto2volumemonitor.c b/monitor/gphoto2/ggphoto2volumemonitor.c new file mode 100644 index 00000000..5b8e8341 --- /dev/null +++ b/monitor/gphoto2/ggphoto2volumemonitor.c @@ -0,0 +1,564 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include <config.h> + +#include <limits.h> +#include <string.h> +#include <stdlib.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gio/gio.h> + +#include "ggphoto2volumemonitor.h" +#include "ggphoto2volume.h" + +#include "hal-pool.h" + +G_LOCK_DEFINE_STATIC(hal_vm); + +static GGPhoto2VolumeMonitor *the_volume_monitor = NULL; +static HalPool *pool = NULL; + +struct _GGPhoto2VolumeMonitor { + GNativeVolumeMonitor parent; + + GUnixMountMonitor *mount_monitor; + + HalPool *pool; + + GList *last_camera_devices; + + GList *camera_volumes; +}; + +static void hal_changed (HalPool *pool, + HalDevice *device, + gpointer user_data); + +static void update_all (GGPhoto2VolumeMonitor *monitor, + gboolean emit_changes); + +static void update_cameras (GGPhoto2VolumeMonitor *monitor, + GList **added_volumes, + GList **removed_volumes); + + +G_DEFINE_TYPE (GGPhoto2VolumeMonitor, g_gphoto2_volume_monitor, G_TYPE_VOLUME_MONITOR) + +static void +list_free (GList *objects) +{ + g_list_foreach (objects, (GFunc)g_object_unref, NULL); + g_list_free (objects); +} + +static HalPool * +get_hal_pool (void) +{ + char *cap_only[] = {"camera", "portable_audio_player", "usb_device", NULL}; + + if (pool == NULL) + pool = hal_pool_new (cap_only); + + return pool; +} + +static void +g_gphoto2_volume_monitor_dispose (GObject *object) +{ + GGPhoto2VolumeMonitor *monitor; + + monitor = G_GPHOTO2_VOLUME_MONITOR (object); + + G_LOCK (hal_vm); + the_volume_monitor = NULL; + G_UNLOCK (hal_vm); + + if (G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->dispose) + (*G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->dispose) (object); +} + +static void +g_gphoto2_volume_monitor_finalize (GObject *object) +{ + GGPhoto2VolumeMonitor *monitor; + + monitor = G_GPHOTO2_VOLUME_MONITOR (object); + + g_signal_handlers_disconnect_by_func (monitor->pool, hal_changed, monitor); + + g_object_unref (monitor->pool); + + list_free (monitor->last_camera_devices); + list_free (monitor->camera_volumes); + + if (G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->finalize) + (*G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->finalize) (object); +} + +static GList * +get_mounts (GVolumeMonitor *volume_monitor) +{ + return NULL; +} + +static GList * +get_volumes (GVolumeMonitor *volume_monitor) +{ + GGPhoto2VolumeMonitor *monitor; + GList *l; + + monitor = G_GPHOTO2_VOLUME_MONITOR (volume_monitor); + + G_LOCK (hal_vm); + + l = g_list_copy (monitor->camera_volumes); + g_list_foreach (l, (GFunc)g_object_ref, NULL); + + G_UNLOCK (hal_vm); + + return l; +} + +static GList * +get_connected_drives (GVolumeMonitor *volume_monitor) +{ + return NULL; +} + +static GVolume * +get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) +{ + return NULL; +} + +static GMount * +get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) +{ + return NULL; +} + +static void +hal_changed (HalPool *pool, + HalDevice *device, + gpointer user_data) +{ + GGPhoto2VolumeMonitor *monitor = G_GPHOTO2_VOLUME_MONITOR (user_data); + + /*g_warning ("hal changed");*/ + + update_all (monitor, TRUE); +} + +static GObject * +g_gphoto2_volume_monitor_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *object; + GGPhoto2VolumeMonitor *monitor; + GGPhoto2VolumeMonitorClass *klass; + GObjectClass *parent_class; + + G_LOCK (hal_vm); + if (the_volume_monitor != NULL) + { + object = g_object_ref (the_volume_monitor); + G_UNLOCK (hal_vm); + return object; + } + G_UNLOCK (hal_vm); + + /*g_warning ("creating hal vm");*/ + + object = NULL; + + /* Invoke parent constructor. */ + klass = G_GPHOTO2_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_GPHOTO2_VOLUME_MONITOR)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + object = parent_class->constructor (type, + n_construct_properties, + construct_properties); + + monitor = G_GPHOTO2_VOLUME_MONITOR (object); + monitor->pool = g_object_ref (get_hal_pool ()); + + g_signal_connect (monitor->pool, + "device_added", G_CALLBACK (hal_changed), + monitor); + + g_signal_connect (monitor->pool, + "device_removed", G_CALLBACK (hal_changed), + monitor); + + update_all (monitor, FALSE); + + G_LOCK (hal_vm); + the_volume_monitor = monitor; + G_UNLOCK (hal_vm); + + return object; +} + +static void +g_gphoto2_volume_monitor_init (GGPhoto2VolumeMonitor *monitor) +{ +} + +static gboolean +is_supported (void) +{ + return get_hal_pool() != NULL; +} + +static GVolume * +adopt_orphan_mount (GMount *mount, GVolumeMonitor *monitor) +{ + GList *l; + GFile *mount_root; + GVolume *ret; + + /* This is called by the union volume monitor which does + have a ref to this. So its guaranteed to live, unfortunately + the pointer is not passed as an argument :/ + */ + ret = NULL; + + G_LOCK (hal_vm); + if (the_volume_monitor == NULL) + { + G_UNLOCK (hal_vm); + return NULL; + } + + mount_root = g_mount_get_root (mount); + + /* gphoto2:// are foreign mounts */ + for (l = the_volume_monitor->camera_volumes; l != NULL; l = l->next) + { + GGPhoto2Volume *volume = l->data; + + if (g_gphoto2_volume_has_foreign_mount_root (volume, mount_root)) + { + g_gphoto2_volume_adopt_foreign_mount (volume, mount); + ret = g_object_ref (volume); + goto found; + } + } + + found: + g_object_unref (mount_root); + + G_UNLOCK (hal_vm); + return ret; +} + +static void +g_gphoto2_volume_monitor_class_init (GGPhoto2VolumeMonitorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); + + gobject_class->constructor = g_gphoto2_volume_monitor_constructor; + gobject_class->finalize = g_gphoto2_volume_monitor_finalize; + gobject_class->dispose = g_gphoto2_volume_monitor_dispose; + + monitor_class->get_mounts = get_mounts; + monitor_class->get_volumes = get_volumes; + monitor_class->get_connected_drives = get_connected_drives; + monitor_class->get_volume_for_uuid = get_volume_for_uuid; + monitor_class->get_mount_for_uuid = get_mount_for_uuid; + monitor_class->adopt_orphan_mount = adopt_orphan_mount; + monitor_class->is_supported = is_supported; +} + +/** + * g_gphoto2_volume_monitor_new: + * + * Returns: a new #GVolumeMonitor. + **/ +GVolumeMonitor * +g_gphoto2_volume_monitor_new (void) +{ + GGPhoto2VolumeMonitor *monitor; + + monitor = g_object_new (G_TYPE_GPHOTO2_VOLUME_MONITOR, NULL); + + return G_VOLUME_MONITOR (monitor); +} + +static void +diff_sorted_lists (GList *list1, + GList *list2, + GCompareFunc compare, + GList **added, + GList **removed) +{ + int order; + + *added = *removed = NULL; + + while (list1 != NULL && + list2 != NULL) + { + order = (*compare) (list1->data, list2->data); + if (order < 0) + { + *removed = g_list_prepend (*removed, list1->data); + list1 = list1->next; + } + else if (order > 0) + { + *added = g_list_prepend (*added, list2->data); + list2 = list2->next; + } + else + { /* same item */ + list1 = list1->next; + list2 = list2->next; + } + } + + while (list1 != NULL) + { + *removed = g_list_prepend (*removed, list1->data); + list1 = list1->next; + } + while (list2 != NULL) + { + *added = g_list_prepend (*added, list2->data); + list2 = list2->next; + } +} + +static GGPhoto2Volume * +find_camera_volume_by_udi (GGPhoto2VolumeMonitor *monitor, const char *udi) +{ + GList *l; + + for (l = monitor->camera_volumes; l != NULL; l = l->next) + { + GGPhoto2Volume *volume = l->data; + + if (g_gphoto2_volume_has_udi (volume, udi)) + return volume; + } + + return NULL; +} + +static gint +hal_device_compare (HalDevice *a, HalDevice *b) +{ + return strcmp (hal_device_get_udi (a), hal_device_get_udi (b)); +} + +static void +list_emit (GGPhoto2VolumeMonitor *monitor, + const char *monitor_signal, + const char *object_signal, + GList *objects) +{ + GList *l; + + for (l = objects; l != NULL; l = l->next) + { + g_signal_emit_by_name (monitor, monitor_signal, l->data); + if (object_signal) + g_signal_emit_by_name (l->data, object_signal); + } +} + +typedef struct { + GGPhoto2VolumeMonitor *monitor; + GList *added_volumes, *removed_volumes; +} ChangedLists; + + +static gboolean +emit_lists_in_idle (gpointer data) +{ + ChangedLists *lists = data; + + list_emit (lists->monitor, + "volume_removed", "removed", + lists->removed_volumes); + list_emit (lists->monitor, + "volume_added", NULL, + lists->added_volumes); + + list_free (lists->removed_volumes); + list_free (lists->added_volumes); + g_object_unref (lists->monitor); + g_free (lists); + + return FALSE; +} + +/* Must be called from idle if emit_changes, with no locks held */ +static void +update_all (GGPhoto2VolumeMonitor *monitor, + gboolean emit_changes) +{ + ChangedLists *lists; + GList *added_volumes, *removed_volumes; + + added_volumes = NULL; + removed_volumes = NULL; + + G_LOCK (hal_vm); + update_cameras (monitor, &added_volumes, &removed_volumes); + G_UNLOCK (hal_vm); + + if (emit_changes) + { + lists = g_new0 (ChangedLists, 1); + lists->monitor = g_object_ref (monitor); + lists->added_volumes = added_volumes; + lists->removed_volumes = removed_volumes; + + g_idle_add (emit_lists_in_idle, lists); + } + else + { + list_free (removed_volumes); + list_free (added_volumes); + } +} + +static void +update_cameras (GGPhoto2VolumeMonitor *monitor, + GList **added_volumes, + GList **removed_volumes) +{ + GList *new_camera_devices; + GList *new_mtp_devices; + GList *removed, *added; + GList *l, *ll; + GGPhoto2Volume *volume; + const char *udi; + + new_mtp_devices = hal_pool_find_by_capability (monitor->pool, "portable_audio_player"); + for (l = new_mtp_devices; l != NULL; l = ll) + { + HalDevice *d = l->data; + ll = l->next; + 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_mtp_devices = g_list_delete_link (new_mtp_devices, l); + } + } + + new_camera_devices = hal_pool_find_by_capability (monitor->pool, "camera"); + new_camera_devices = g_list_concat (new_camera_devices, new_mtp_devices); + for (l = new_camera_devices; l != NULL; l = ll) + { + HalDevice *d = l->data; + ll = l->next; + /*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_gphoto2_volume_removed (volume); + monitor->camera_volumes = g_list_remove (monitor->camera_volumes, volume); + *removed_volumes = g_list_prepend (*removed_volumes, 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; + gboolean found; + + /* Look for the device in the added volumes, so as + * not to add devices that are both audio players, and cameras */ + found = FALSE; + for (ll = *added_volumes; ll; ll = ll->next) + { + if (g_gphoto2_volume_has_udi (ll->data, hal_device_get_udi (d)) != FALSE) + { + found = TRUE; + break; + } + } + + if (found) + continue; + + 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_gphoto2_volume_new (G_VOLUME_MONITOR (monitor), + d, + monitor->pool, + foreign_mount_root); + g_object_unref (foreign_mount_root); + if (volume != NULL) + { + monitor->camera_volumes = g_list_prepend (monitor->camera_volumes, volume); + *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume)); + } + } + + g_list_free (added); + g_list_free (removed); + list_free (monitor->last_camera_devices); + monitor->last_camera_devices = new_camera_devices; +} diff --git a/monitor/gphoto2/ggphoto2volumemonitor.h b/monitor/gphoto2/ggphoto2volumemonitor.h new file mode 100644 index 00000000..fcb74fef --- /dev/null +++ b/monitor/gphoto2/ggphoto2volumemonitor.h @@ -0,0 +1,54 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __G_GPHOTO2_VOLUME_MONITOR_H__ +#define __G_GPHOTO2_VOLUME_MONITOR_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define G_TYPE_GPHOTO2_VOLUME_MONITOR (g_gphoto2_volume_monitor_get_type ()) +#define G_GPHOTO2_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_GPHOTO2_VOLUME_MONITOR, GGPhoto2VolumeMonitor)) +#define G_GPHOTO2_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_GPHOTO2_VOLUME_MONITOR, GGPhoto2VolumeMonitorClass)) +#define G_IS_GPHOTO2_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_GPHOTO2_VOLUME_MONITOR)) +#define G_IS_GPHOTO2_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_GPHOTO2_VOLUME_MONITOR)) + +typedef struct _GGPhoto2VolumeMonitor GGPhoto2VolumeMonitor; +typedef struct _GGPhoto2VolumeMonitorClass GGPhoto2VolumeMonitorClass; + +/* Forward definitions */ +typedef struct _GGPhoto2Volume GGPhoto2Volume; + +struct _GGPhoto2VolumeMonitorClass { + GVolumeMonitorClass parent_class; +}; + +GType g_gphoto2_volume_monitor_get_type (void) G_GNUC_CONST; + +GVolumeMonitor *g_gphoto2_volume_monitor_new (void); +void g_gphoto2_volume_monitor_force_update (GGPhoto2VolumeMonitor *monitor); + +G_END_DECLS + +#endif /* __G_GPHOTO2_VOLUME_MONITOR_H__ */ diff --git a/monitor/gphoto2/gphoto2-volume-monitor-daemon.c b/monitor/gphoto2/gphoto2-volume-monitor-daemon.c new file mode 100644 index 00000000..f4998f35 --- /dev/null +++ b/monitor/gphoto2/gphoto2-volume-monitor-daemon.c @@ -0,0 +1,43 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* gvfs - extensions for gio + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include <config.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gmodule.h> +#include <gio/gio.h> + +#include <gvfsproxyvolumemonitordaemon.h> + +#include "ggphoto2volumemonitor.h" + +int +main (int argc, char *argv[]) +{ + g_vfs_proxy_volume_monitor_daemon_init (); + return g_vfs_proxy_volume_monitor_daemon_main (argc, + argv, + "org.gtk.Private.GPhoto2VolumeMonitor", + G_TYPE_GPHOTO2_VOLUME_MONITOR); +} diff --git a/monitor/gphoto2/gphoto2.monitor b/monitor/gphoto2/gphoto2.monitor new file mode 100644 index 00000000..e0a69852 --- /dev/null +++ b/monitor/gphoto2/gphoto2.monitor @@ -0,0 +1,4 @@ +[RemoteVolumeMonitor] +Name=GProxyVolumeMonitorGPhoto2 +DBusName=org.gtk.Private.GPhoto2VolumeMonitor +IsNative=false diff --git a/monitor/gphoto2/hal-device.c b/monitor/gphoto2/hal-device.c new file mode 100644 index 00000000..9f0b5bc3 --- /dev/null +++ b/monitor/gphoto2/hal-device.c @@ -0,0 +1,297 @@ +/* hal-device.c + * + * Copyright (C) 2007 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <glib/gi18n-lib.h> +#include "hal-device.h" +#include "hal-marshal.h" + +struct _HalDevicePrivate +{ + LibHalContext *hal_ctx; + LibHalPropertySet *properties; + char *udi; + GTimeVal time_added; +}; + +enum { + HAL_PROPERTY_CHANGED, + HAL_CONDITION, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (HalDevice, hal_device, G_TYPE_OBJECT) + +static void +hal_device_finalize (HalDevice *device) +{ + if (device->priv->properties != NULL) + libhal_free_property_set (device->priv->properties); + g_free (device->priv->udi); + + if (G_OBJECT_CLASS (hal_device_parent_class)->finalize) + (* G_OBJECT_CLASS (hal_device_parent_class)->finalize) (G_OBJECT (device)); +} + +static void +hal_device_class_init (HalDeviceClass *klass) +{ + GObjectClass *obj_class = (GObjectClass *) klass; + + obj_class->finalize = (GObjectFinalizeFunc) hal_device_finalize; + + signals[HAL_PROPERTY_CHANGED] = + g_signal_new ("hal_property_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceClass, hal_property_changed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[HAL_CONDITION] = + g_signal_new ("hal_condition", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalDeviceClass, hal_condition), + NULL, NULL, + hal_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); +} + +static void +hal_device_init (HalDevice *device) +{ + device->priv = g_new0 (HalDevicePrivate, 1); + g_get_current_time (&(device->priv->time_added)); +} + +const char * +hal_device_get_property_string (HalDevice *device, const char *key) +{ + const char *ret; + + ret = libhal_ps_get_string (device->priv->properties, key); + if (ret != NULL) + return ret; + + /* play it safe and don't make clients crash */ + return ""; +} + +int +hal_device_get_property_int (HalDevice *device, const char *key) +{ + return libhal_ps_get_int32 (device->priv->properties, key); +} + +double +hal_device_get_property_double (HalDevice *device, const char *key) +{ + return libhal_ps_get_double (device->priv->properties, key); +} + +guint64 +hal_device_get_property_uint64 (HalDevice *device, const char *key) +{ + return libhal_ps_get_uint64 (device->priv->properties, key); +} + +gboolean +hal_device_get_property_bool (HalDevice *device, const char *key) +{ + return libhal_ps_get_bool (device->priv->properties, key); +} + +char ** +hal_device_get_property_strlist (HalDevice *device, const char *key) +{ + static char * empty[1] = {NULL}; + char **ret; + + ret = (char **) libhal_ps_get_strlist (device->priv->properties, key); + if (ret != NULL) + return (char **) ret; + + /* play it safe and don't make clients crash */ + return empty; +} + +gboolean +hal_device_has_capability (HalDevice *device, const char *capability) +{ + int n; + char **caps; + gboolean ret; + + ret = FALSE; + caps = hal_device_get_property_strlist (device, "info.capabilities"); + if (caps == NULL) + goto out; + + for (n = 0; caps[n] != NULL; n++) + { + if (g_ascii_strcasecmp (caps[n], capability) == 0) + { + ret = TRUE; + break; + } + } + + out: + return ret; +} + +gboolean +hal_device_has_interface (HalDevice *device, const char *interface) +{ + int n; + char **ifs; + gboolean ret; + + ret = FALSE; + ifs = hal_device_get_property_strlist (device, "info.interfaces"); + if (ifs == NULL) + goto out; + + for (n = 0; ifs[n] != NULL; n++) + { + if (g_ascii_strcasecmp (ifs[n], interface) == 0) + { + ret = TRUE; + break; + } + } + +out: + return ret; +} + +gboolean +hal_device_has_property (HalDevice *device, const char *key) +{ + gboolean ret; + LibHalPropertySetIterator it; + + ret = FALSE; + if (device->priv->properties == NULL) + goto out; + + libhal_psi_init (&it, device->priv->properties); + + while (libhal_psi_has_more (&it)) + { + char *pkey = libhal_psi_get_key (&it); + + if (pkey != NULL && g_ascii_strcasecmp (pkey, key) == 0) + { + ret = TRUE; + break; + } + libhal_psi_next (&it); + } + + out: + return ret; +} + + +HalDevice * +hal_device_new_from_udi (LibHalContext *hal_ctx, const char *udi) +{ + HalDevice *device; + + device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL)); + device->priv->udi = g_strdup (udi); + device->priv->hal_ctx = hal_ctx; + device->priv->properties = libhal_device_get_all_properties (hal_ctx, udi, NULL); + return device; +} + +HalDevice * +hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx, + char *udi, + LibHalPropertySet *properties) +{ + HalDevice *device; + + device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL)); + device->priv->udi = g_strdup (udi); + device->priv->hal_ctx = hal_ctx; + device->priv->properties = properties; + return device; +} + +void +_hal_device_hal_property_changed (HalDevice *device, const char *key); + +void +_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail); + +void +_hal_device_hal_property_changed (HalDevice *device, const char *key) +{ + LibHalPropertySet *new_props; + + new_props = libhal_device_get_all_properties (device->priv->hal_ctx, device->priv->udi, NULL); + if (new_props != NULL) + { + libhal_free_property_set (device->priv->properties); + device->priv->properties = new_props; + g_signal_emit (device, signals[HAL_PROPERTY_CHANGED], 0, key); + } +} + +void +_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail) +{ + g_signal_emit (device, signals[HAL_CONDITION], 0, name, detail); +} + +const char * +hal_device_get_udi (HalDevice *device) +{ + return device->priv->udi; +} + +LibHalPropertySet * +hal_device_get_properties (HalDevice *device) +{ + return device->priv->properties; +} + +gboolean +hal_device_is_recently_plugged_in (HalDevice *device) +{ + GTimeVal now; + glong delta_msec; + + g_get_current_time (&now); + + delta_msec = (now.tv_sec - device->priv->time_added.tv_sec) * 1000 + + (now.tv_usec - device->priv->time_added.tv_usec) / 1000; + + return delta_msec < 2000; +} diff --git a/monitor/gphoto2/hal-device.h b/monitor/gphoto2/hal-device.h new file mode 100644 index 00000000..8e91aa63 --- /dev/null +++ b/monitor/gphoto2/hal-device.h @@ -0,0 +1,93 @@ +/* hal-device.h + * + * Copyright (C) 2007 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef HAL_DEVICE_H +#define HAL_DEVICE_H + +#include <glib-object.h> +#include <gio/gio.h> +#include <libhal.h> + +#define HAL_TYPE_DEVICE (hal_device_get_type ()) +#define HAL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_DEVICE, HalDevice)) +#define HAL_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_DEVICE, HalDeviceClass)) +#define HAL_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_DEVICE)) +#define HAL_IS_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_DEVICE)) +#define HAL_DEVICE_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_DEVICE, HalDeviceClass)) + + +typedef struct _HalDevice HalDevice; +typedef struct _HalDeviceClass HalDeviceClass; + +struct _HalDevicePrivate; +typedef struct _HalDevicePrivate HalDevicePrivate; + +struct _HalDevice +{ + GObject parent; + + /* private */ + HalDevicePrivate *priv; +}; + +struct _HalDeviceClass +{ + GObjectClass parent_class; + + /* signals */ + void (*hal_property_changed) (HalDevice *device, const char *key); + void (*hal_condition) (HalDevice *device, const char *name, const char *detail); +}; + + +GType hal_device_get_type (void); + +HalDevice * hal_device_new_from_udi (LibHalContext *hal_ctx, + const char *udi); + +HalDevice * hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx, + char *udi, + LibHalPropertySet *properties); + +const char * hal_device_get_udi (HalDevice *device); +LibHalPropertySet * hal_device_get_properties (HalDevice *device); +const char * hal_device_get_property_string (HalDevice *device, + const char *key); +int hal_device_get_property_int (HalDevice *device, + const char *key); +guint64 hal_device_get_property_uint64 (HalDevice *device, + const char *key); +double hal_device_get_property_double (HalDevice *device, + const char *key); +gboolean hal_device_get_property_bool (HalDevice *device, + const char *key); +char ** hal_device_get_property_strlist (HalDevice *device, + const char *key); + +gboolean hal_device_has_property (HalDevice *device, + const char *key); +gboolean hal_device_has_capability (HalDevice *device, + const char *capability); +gboolean hal_device_has_interface (HalDevice *device, + const char *interface); + +gboolean hal_device_is_recently_plugged_in (HalDevice *device); + +#endif /* HAL_DEVICE_H */ diff --git a/monitor/gphoto2/hal-marshal.c b/monitor/gphoto2/hal-marshal.c new file mode 100644 index 00000000..75fec6e4 --- /dev/null +++ b/monitor/gphoto2/hal-marshal.c @@ -0,0 +1,163 @@ +#include "hal-marshal.h" + +#include <glib-object.h> + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* VOID:OBJECT,STRING (hal-marshal.list:1) */ +void +hal_marshal_VOID__OBJECT_STRING (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_STRING) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_STRING callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_STRING) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + data2); +} + +/* VOID:OBJECT,STRING,STRING (hal-marshal.list:2) */ +void +hal_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_STRING_STRING) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_STRING_STRING callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + g_marshal_value_peek_string (param_values + 3), + data2); +} + +/* VOID:STRING,STRING (hal-marshal.list:3) */ +void +hal_marshal_VOID__STRING_STRING (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_STRING callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + data2); +} + diff --git a/monitor/gphoto2/hal-marshal.h b/monitor/gphoto2/hal-marshal.h new file mode 100644 index 00000000..0ac3074c --- /dev/null +++ b/monitor/gphoto2/hal-marshal.h @@ -0,0 +1,36 @@ + +#ifndef __hal_marshal_MARSHAL_H__ +#define __hal_marshal_MARSHAL_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* VOID:OBJECT,STRING (hal-marshal.list:1) */ +extern void hal_marshal_VOID__OBJECT_STRING (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:OBJECT,STRING,STRING (hal-marshal.list:2) */ +extern void hal_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:STRING,STRING (hal-marshal.list:3) */ +extern void hal_marshal_VOID__STRING_STRING (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +G_END_DECLS + +#endif /* __hal_marshal_MARSHAL_H__ */ + diff --git a/monitor/gphoto2/hal-marshal.list b/monitor/gphoto2/hal-marshal.list new file mode 100644 index 00000000..52c82338 --- /dev/null +++ b/monitor/gphoto2/hal-marshal.list @@ -0,0 +1,3 @@ +VOID:OBJECT,STRING +VOID:OBJECT,STRING,STRING +VOID:STRING,STRING diff --git a/monitor/gphoto2/hal-pool.c b/monitor/gphoto2/hal-pool.c new file mode 100644 index 00000000..770effd9 --- /dev/null +++ b/monitor/gphoto2/hal-pool.c @@ -0,0 +1,458 @@ +/* hal-pool.c + * + * Copyright (C) 2007 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <gdbusutils.h> + +#include "hal-pool.h" +#include "hal-marshal.h" + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + DEVICE_PROPERTY_CHANGED, + DEVICE_CONDITION, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _HalPoolPrivate +{ + char **cap_only; + + DBusConnection *dbus_connection; + LibHalContext *hal_ctx; + GHashTable *devices; +}; + +G_DEFINE_TYPE (HalPool, hal_pool, G_TYPE_OBJECT) + +static void +hal_pool_finalize (HalPool *pool) +{ + g_strfreev (pool->priv->cap_only); + + dbus_bus_remove_match (pool->priv->dbus_connection, + "type='signal'," + "interface='org.freedesktop.Hal.Device'," + "sender='org.freedesktop.Hal'", NULL); + libhal_ctx_shutdown (pool->priv->hal_ctx, NULL); + dbus_connection_close (pool->priv->dbus_connection); + dbus_connection_unref (pool->priv->dbus_connection); + + if (G_OBJECT_CLASS (hal_pool_parent_class)->finalize) + (* G_OBJECT_CLASS (hal_pool_parent_class)->finalize) (G_OBJECT (pool)); +} + +static void +hal_pool_class_init (HalPoolClass *klass) +{ + GObjectClass *obj_class = (GObjectClass *) klass; + + obj_class->finalize = (GObjectFinalizeFunc) hal_pool_finalize; + + g_type_class_ref (HAL_TYPE_DEVICE); + + signals[DEVICE_ADDED] = + g_signal_new ("device_added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalPoolClass, device_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + HAL_TYPE_DEVICE); + + signals[DEVICE_REMOVED] = + g_signal_new ("device_removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalPoolClass, device_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + HAL_TYPE_DEVICE); + + signals[DEVICE_PROPERTY_CHANGED] = + g_signal_new ("device_property_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalPoolClass, device_property_changed), + NULL, NULL, + hal_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, 2, + HAL_TYPE_DEVICE, + G_TYPE_STRING); + + signals[DEVICE_CONDITION] = + g_signal_new ("device_condition", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HalPoolClass, device_condition), + NULL, NULL, + hal_marshal_VOID__OBJECT_STRING_STRING, + G_TYPE_NONE, 3, + HAL_TYPE_DEVICE, + G_TYPE_STRING, + G_TYPE_STRING); +} + +static void +hal_pool_init (HalPool *pool) +{ + pool->priv = g_new0 (HalPoolPrivate, 1); + pool->priv->hal_ctx = NULL; +} + +static gboolean +has_cap_only (HalPool *pool, HalDevice *device) +{ + const char *subsys; + unsigned int n; + + for (n = 0; pool->priv->cap_only != NULL && pool->priv->cap_only[n] != NULL; n++) + { + if (hal_device_has_capability (device, pool->priv->cap_only[n])) + return TRUE; + + subsys = hal_device_get_property_string (device, "info.subsystem"); + + if (subsys != NULL && strcmp (subsys, pool->priv->cap_only[n]) == 0) + return TRUE; + } + + return FALSE; +} + +static void +hal_pool_add_device_by_udi (HalPool *pool, + const char *udi, + gboolean emit_signal) +{ + HalDevice *device; + + device = hal_device_new_from_udi (pool->priv->hal_ctx, udi); + if (device != NULL) + { + if (!has_cap_only (pool, device)) + g_object_unref (device); + else + { + g_hash_table_insert (pool->priv->devices, g_strdup (udi), device); + if (emit_signal) + g_signal_emit (pool, signals[DEVICE_ADDED], 0, device); + } + } +} + +#ifdef HAVE_HAL_FAST_INIT +static void +hal_pool_add_device_by_udi_and_properties (HalPool *pool, + char *udi, + LibHalPropertySet *properties, + gboolean emit_signal) +{ + HalDevice *device; + + device = hal_device_new_from_udi_and_properties (pool->priv->hal_ctx, udi, properties); + if (device != NULL) + { + if (!has_cap_only (pool, device)) + g_object_unref (device); + else + { + g_hash_table_insert (pool->priv->devices, g_strdup (udi), device); + if (emit_signal) + g_signal_emit (pool, signals[DEVICE_ADDED], 0, device); + } + } +} +#endif + +static void +_hal_device_added (LibHalContext *hal_ctx, const char *udi) +{ + HalPool *pool; + + pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx)); + hal_pool_add_device_by_udi (pool, udi, TRUE); +} + +static void +_hal_device_removed (LibHalContext *hal_ctx, const char *udi) +{ + HalPool *pool; + HalDevice *device; + + pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx)); + if ((device = hal_pool_get_device_by_udi (pool, udi)) != NULL) + { + g_object_ref (device); + g_hash_table_remove (pool->priv->devices, udi); + g_signal_emit (pool, signals[DEVICE_REMOVED], 0, device); + g_object_unref (device); + } +} + +void +_hal_device_hal_property_changed (HalDevice *device, const char *key); + +void +_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail); + +static void +_hal_property_modified (LibHalContext *ctx, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ + HalPool *pool; + HalDevice *device; + + pool = HAL_POOL (libhal_ctx_get_user_data (ctx)); + + device = hal_pool_get_device_by_udi (pool, udi); + if (device != NULL) + { + _hal_device_hal_property_changed (device, key); + g_signal_emit (pool, signals[DEVICE_PROPERTY_CHANGED], 0, device, key); + } +} + +static void +_hal_condition (LibHalContext *ctx, + const char *udi, + const char *condition_name, + const char *condition_detail) +{ + HalPool *pool; + HalDevice *device; + + pool = HAL_POOL (libhal_ctx_get_user_data (ctx)); + + device = hal_pool_get_device_by_udi (pool, udi); + if (device != NULL) + { + _hal_device_hal_condition (device, condition_name, condition_detail); + g_signal_emit (pool, signals[DEVICE_CONDITION], 0, device, condition_name, condition_detail); + } +} + +LibHalContext * +hal_pool_get_hal_ctx (HalPool *pool) +{ + return pool->priv->hal_ctx; +} + +DBusConnection * +hal_pool_get_dbus_connection (HalPool *pool) +{ + return pool->priv->dbus_connection; +} + +HalPool * +hal_pool_new (char **cap_only) +{ + int i; + char **devices; + int num_devices; + HalPool *pool; + LibHalContext *hal_ctx; + DBusError error; + DBusConnection *dbus_connection; +#ifdef HAVE_HAL_FAST_INIT + LibHalPropertySet **properties; +#endif + + pool = NULL; + + dbus_error_init (&error); + /* see discussion on gtk-devel-list (Subject: Re: gvfs hal volume monitoring backend) on + * why this is private + */ + dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) + { + dbus_error_free (&error); + goto out; + } + + dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE); + + hal_ctx = libhal_ctx_new (); + if (hal_ctx == NULL) + { + dbus_connection_close (dbus_connection); + dbus_connection_unref (dbus_connection); + goto out; + } + + _g_dbus_connection_integrate_with_main (dbus_connection); + libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection); + + if (!libhal_ctx_init (hal_ctx, &error)) + { + dbus_connection_close (dbus_connection); + dbus_connection_unref (dbus_connection); + dbus_error_free (&error); + goto out; + } + + pool = HAL_POOL (g_object_new (HAL_TYPE_POOL, NULL)); + 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_strdupv (cap_only); + + /* Gah, unfortunately we have to watch all devices as HAL's PropertyModified signal + * doesn't include the capabilities... + */ + dbus_bus_add_match (dbus_connection, + "type='signal'," + "interface='org.freedesktop.Hal.Device'," + "sender='org.freedesktop.Hal'", NULL); + libhal_ctx_set_device_added (hal_ctx, _hal_device_added); + libhal_ctx_set_device_removed (hal_ctx, _hal_device_removed); + libhal_ctx_set_device_property_modified (hal_ctx, _hal_property_modified); + libhal_ctx_set_device_condition (hal_ctx, _hal_condition); + libhal_ctx_set_user_data (hal_ctx, pool); + +#ifdef HAVE_HAL_FAST_INIT + /* First try new O(1) algorithm to get all devices and properties in a single call.. + * + * This method is only available in post hal 0.5.10. + */ + if (libhal_get_all_devices_with_properties (pool->priv->hal_ctx, + &num_devices, + &devices, + &properties, + NULL)) + { + for (i = 0; i < num_devices; i++) + hal_pool_add_device_by_udi_and_properties (pool, devices[i], properties[i], FALSE); + libhal_free_string_array (devices); + free (properties); /* hal_pool_add_device_by_udi_and_properties steals the given properties */ + goto out; + } +#endif + + /* fallback to using O(n) algorithm; will work on any hal 0.5.x release */ + devices = libhal_get_all_devices (pool->priv->hal_ctx, &num_devices, NULL); + if (devices != NULL) + { + for (i = 0; i < num_devices; i++) + { + char *device_udi; + device_udi = devices[i]; + hal_pool_add_device_by_udi (pool, device_udi, FALSE); + } + libhal_free_string_array (devices); + goto out; + } + + /* FAIL! */ + + g_object_unref (pool); + return NULL; + + out: + return pool; +} + +HalDevice * +hal_pool_get_device_by_udi (HalPool *pool, const char *udi) +{ + return g_hash_table_lookup (pool->priv->devices, udi); +} + +HalDevice * +hal_pool_get_device_by_capability_and_string (HalPool *pool, + const char *capability, + const char *key, + const char *value) +{ + GList *i; + GList *devices; + HalDevice *result; + + result = NULL; + devices = NULL; + + if (pool->priv->devices == NULL) + goto out; + + devices = g_hash_table_get_values (pool->priv->devices); + for (i = devices; i != NULL; i = i->next) + { + HalDevice *d = i->data; + const char *s; + + if (!hal_device_has_capability (d, capability)) + continue; + + s = hal_device_get_property_string (d, key); + if (s == NULL) + continue; + + if (strcmp (s, value) == 0) + { + result = d; + goto out; + } + } + +out: + if (devices != NULL) + g_list_free (devices); + return result; +} + +GList * +hal_pool_find_by_capability (HalPool *pool, const char *capability) +{ + GList *i; + GList *j; + GList *devices; + + devices = NULL; + + if (pool->priv->devices == NULL) + goto out; + + devices = g_hash_table_get_values (pool->priv->devices); + for (i = devices; i != NULL; i = j) + { + HalDevice *d = i->data; + + j = i->next; + + if (!hal_device_has_capability (d, capability)) + devices = g_list_delete_link (devices, i); + } + + out: + return devices; +} diff --git a/monitor/gphoto2/hal-pool.h b/monitor/gphoto2/hal-pool.h new file mode 100644 index 00000000..04c8687d --- /dev/null +++ b/monitor/gphoto2/hal-pool.h @@ -0,0 +1,74 @@ +/* hal-pool.h + * + * Copyright (C) 2007 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#if !defined(HAL_POOL_H) +#define HAL_POOL_H + +#include <gio/gio.h> +#include <gio/gunixmounts.h> +#include "hal-device.h" + +#define HAL_TYPE_POOL (hal_pool_get_type ()) +#define HAL_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_POOL, HalPool)) +#define HAL_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_POOL, HalPoolClass)) +#define HAL_IS_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_POOL)) +#define HAL_IS_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_POOL)) +#define HAL_POOL_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_POOL, HalPoolClass)) + + +typedef struct _HalPool HalPool; +typedef struct _HalPoolClass HalPoolClass; + +struct _HalPoolPrivate; +typedef struct _HalPoolPrivate HalPoolPrivate; + +struct _HalPool +{ + GObject parent; + + /* private */ + HalPoolPrivate *priv; +}; + +struct _HalPoolClass +{ + GObjectClass parent_class; + + /* signals */ + void (*device_added) (HalPool *pool, HalDevice *device); + void (*device_removed) (HalPool *pool, HalDevice *device); + void (*device_property_changed) (HalPool *pool, HalDevice *device, const char *key); + void (*device_condition) (HalPool *pool, HalDevice *device, const char *name, const char *detail); +}; + +GType hal_pool_get_type (void); +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, + const char *udi); +HalDevice * hal_pool_get_device_by_capability_and_string (HalPool *pool, + const char *capability, + const char *key, + const char *value); +GList * hal_pool_find_by_capability (HalPool *pool, + const char *capability); + +#endif /* HAL_POOL_H */ diff --git a/monitor/gphoto2/hal-utils.c b/monitor/gphoto2/hal-utils.c new file mode 100644 index 00000000..ca90bc7c --- /dev/null +++ b/monitor/gphoto2/hal-utils.c @@ -0,0 +1,142 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + * Christian Kellner <gicmo@gnome.org> + */ + +#include <config.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gio/gio.h> + +#include "string.h" + +#include "hal-utils.h" + +static const struct { + const char *disc_type; + const char *icon_name; + char *ui_name; + char *ui_name_blank; +} disc_data[] = { + {"cd_rom", "media-optical-cd-rom", N_("CD-ROM Disc"), N_("Blank CD-ROM Disc")}, + {"cd_r", "media-optical-cd-r", N_("CD-R Disc"), N_("Blank CD-R Disc")}, + {"cd_rw", "media-optical-cd-rw", N_("CD-RW Disc"), N_("Blank CD-RW Disc")}, + {"dvd_rom", "media-optical-dvd-rom", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")}, + {"dvd_ram", "media-optical-dvd-ram", N_("DVD-RAM Disc"), N_("Blank DVD-RAM Disc")}, + {"dvd_r", "media-optical-dvd-r", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")}, + {"dvd_rw", "media-optical-dvd-rw", N_("DVD-RW Disc"), N_("Blank DVD-RW Disc")}, + {"dvd_plus_r", "media-optical-dvd-r-plus", N_("DVD+R Disc"), N_("Blank DVD+R Disc")}, + {"dvd_plus_rw", "media-optical-dvd-rw-plus", N_("DVD+RW Disc"), N_("Blank DVD+RW Disc")}, + {"dvd_plus_r_dl", "media-optical-dvd-dl-r-plus", N_("DVD+R DL Disc"), N_("Blank DVD+R DL Disc")}, + {"bd_rom", "media-optical-bd-rom", N_("Blu-Ray Disc"), N_("Blank Blu-Ray Disc")}, + {"bd_r", "media-optical-bd-r", N_("Blu-Ray R Disc"), N_("Blank Blu-Ray R Disc")}, + {"bd_re", "media-optical-bd-re", N_("Blu-Ray RW Disc"), N_("Blank Blu-Ray RW Disc")}, + {"hddvd_rom", "media-optical-hddvd-rom", N_("HD DVD Disc"), N_("Blank HD DVD Disc")}, + {"hddvd_r", "media-optical-hddvd-r", N_("HD DVD-R Disc"), N_("Blank HD DVD-R Disc")}, + {"hddvd_rw", "media-optical-hddvd-rw", N_("HD DVD-RW Disc"), N_("Blank HD DVD-RW Disc")}, + {"mo", "media-optical-mo", N_("MO Disc"), N_("Blank MO Disc")}, + {NULL, "media-optical", N_("Disc"), N_("Blank Disc")} +}; + +const char * +get_disc_icon (const char *disc_type) +{ + int n; + + for (n = 0; disc_data[n].disc_type != NULL; n++) + { + if (strcmp (disc_data[n].disc_type, disc_type) == 0) + break; + } + + return disc_data[n].icon_name; +} + +const char * +get_disc_name (const char *disc_type, gboolean is_blank) +{ + int n; + + for (n = 0; disc_data[n].disc_type != NULL; n++) + { + if (strcmp (disc_data[n].disc_type, disc_type) == 0) + break; + } + + if (is_blank) + return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name_blank); + else + return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name); +} + +/* + * Creates a GThemedIcon from icon_name and creates default + * fallbacks from fallbacks. Is smart in the case that icon_name + * and fallbacks are identically. + * Note: See the GThemedIcon documentation for more information + * on default fallbacks + */ +GIcon * +get_themed_icon_with_fallbacks (const char *icon_name, + const char *fallbacks) +{ + int i = 0, dashes = 0; + const char *p; + char *dashp; + char *last; + char **names; + GIcon *icon; + + if (G_UNLIKELY (icon_name == NULL)) + return NULL; + + if (fallbacks == NULL) + return g_themed_icon_new (icon_name); + + p = fallbacks; + while (*p) + { + if (*p == '-') + dashes++; + p++; + } + + if (strcmp (icon_name, fallbacks)) + { + names = g_new (char *, dashes + 3); + names[i++] = g_strdup (icon_name); + } + else + names = g_new (char *, dashes + 2); + + names[i++] = last = g_strdup (fallbacks); + + while ((dashp = strrchr (last, '-')) != NULL) + names[i++] = last = g_strndup (last, dashp - last); + + names[i++] = NULL; + icon = g_themed_icon_new_from_names (names, -1); + g_strfreev (names); + + return icon; +} + diff --git a/monitor/gphoto2/hal-utils.h b/monitor/gphoto2/hal-utils.h new file mode 100644 index 00000000..7244a29c --- /dev/null +++ b/monitor/gphoto2/hal-utils.h @@ -0,0 +1,40 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + * Chrsitian Kellner <gicmo@gnome.org> + */ + +#ifndef __HAL_UTILS_H__ +#define __HAL_UTILS_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +const char * get_disc_icon (const char *disc_type); +const char * get_disc_name (const char *disc_type, gboolean is_blank); + +GIcon * get_themed_icon_with_fallbacks (const char *icon_name, + const char *fallbacks); + +G_END_DECLS + +#endif /* __HAL_UTILS_H__ */ diff --git a/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in b/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in new file mode 100644 index 00000000..b06e3df6 --- /dev/null +++ b/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.gtk.Private.GPhoto2VolumeMonitor +Exec=@libexecdir@/gvfs-gphoto2-volume-monitor diff --git a/monitor/hal/ghalvolume.c b/monitor/hal/ghalvolume.c index 9cb9c951..ced7dcc9 100644 --- a/monitor/hal/ghalvolume.c +++ b/monitor/hal/ghalvolume.c @@ -304,72 +304,6 @@ do_update_from_hal (GHalVolume *mv) (GDestroyNotify) g_free); } -#ifdef HAVE_GPHOTO2 -static void -do_update_from_hal_for_camera (GHalVolume *v) -{ - const char *vendor; - const char *product; - const char *icon_from_hal; - const char *name_from_hal; - gboolean is_audio_player; - - vendor = hal_device_get_property_string (v->drive_device, "usb_device.vendor"); - product = hal_device_get_property_string (v->drive_device, "usb_device.product"); - icon_from_hal = hal_device_get_property_string (v->device, "info.desktop.icon"); - name_from_hal = hal_device_get_property_string (v->device, "info.desktop.name"); - - is_audio_player = hal_device_has_capability (v->device, "portable_audio_player"); - - v->name = NULL; - if (strlen (name_from_hal) > 0) - v->name = g_strdup (name_from_hal); - else if (vendor == NULL) - { - if (product != NULL) - v->name = g_strdup (product); - } - else - { - if (product != NULL) - v->name = g_strdup_printf ("%s %s", vendor, product); - else - { - if (is_audio_player) - { - /* Translators: %s is the device vendor */ - v->name = g_strdup_printf (_("%s Audio Player"), vendor); - } - else - { - /* Translators: %s is the device vendor */ - v->name = g_strdup_printf (_("%s Camera"), vendor); - } - } - } - if (v->name == NULL) - { - if (is_audio_player) - v->name = g_strdup (_("Audio Player")); - else - v->name = g_strdup (_("Camera")); - } - - if (strlen (icon_from_hal) > 0) - v->icon = g_strdup (icon_from_hal); - else if (is_audio_player) - v->icon = g_strdup ("multimedia-player"); - else - v->icon = g_strdup ("camera"); - v->mount_path = NULL; - - g_object_set_data_full (G_OBJECT (v), - "hal-storage-device-capabilities", - dupv_and_uniqify (hal_device_get_property_strlist (v->device, "info.capabilities")), - (GDestroyNotify) g_strfreev); -} -#endif - static void update_from_hal (GHalVolume *mv, gboolean emit_changed) { @@ -386,16 +320,7 @@ update_from_hal (GHalVolume *mv, gboolean emit_changed) g_free (mv->name); g_free (mv->icon); g_free (mv->mount_path); -#ifdef HAVE_GPHOTO2 - if (hal_device_has_capability (mv->device, "camera") || - (hal_device_has_capability (mv->device, "portable_audio_player") && - hal_device_get_property_bool (mv->device, "camera.libgphoto2.support"))) - do_update_from_hal_for_camera (mv); - else - do_update_from_hal (mv); -#else do_update_from_hal (mv); -#endif if (emit_changed) { @@ -481,32 +406,6 @@ g_hal_volume_new (GVolumeMonitor *volume_monitor, device_path = hal_device_get_property_string (device, "block.device"); } -#ifdef HAVE_GPHOTO2 - else if (hal_device_has_capability (device, "camera") || - (hal_device_has_capability (device, "portable_audio_player") && - hal_device_get_property_bool (device, "camera.libgphoto2.support"))) - { - - /* 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; diff --git a/monitor/hal/ghalvolumemonitor.c b/monitor/hal/ghalvolumemonitor.c index 76b88bde..1313e6b4 100644 --- a/monitor/hal/ghalvolumemonitor.c +++ b/monitor/hal/ghalvolumemonitor.c @@ -57,7 +57,6 @@ struct _GHalVolumeMonitor { HalPool *pool; - GList *last_camera_devices; GList *last_optical_disc_devices; GList *last_drive_devices; GList *last_volume_devices; @@ -72,8 +71,6 @@ struct _GHalVolumeMonitor { GList *disc_volumes; GList *disc_mounts; - /* Digital cameras (e.g. gphoto2) are kept here */ - GList *camera_volumes; }; static void mountpoints_changed (GUnixMountMonitor *mount_monitor, @@ -99,9 +96,6 @@ static void update_discs (GHalVolumeMonitor *monitor, GList **removed_volumes, GList **added_mounts, GList **removed_mounts); -static void update_cameras (GHalVolumeMonitor *monitor, - GList **added_volumes, - GList **removed_volumes); G_DEFINE_TYPE (GHalVolumeMonitor, g_hal_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR) @@ -116,7 +110,7 @@ list_free (GList *objects) static HalPool * get_hal_pool (void) { - char *cap_only[] = {"block", "camera", "portable_audio_player", "usb_device", NULL}; + char *cap_only[] = {"block", NULL}; if (pool == NULL) pool = hal_pool_new (cap_only); @@ -153,7 +147,6 @@ g_hal_volume_monitor_finalize (GObject *object) g_object_unref (monitor->mount_monitor); g_object_unref (monitor->pool); - list_free (monitor->last_camera_devices); list_free (monitor->last_optical_disc_devices); list_free (monitor->last_drive_devices); list_free (monitor->last_volume_devices); @@ -168,7 +161,6 @@ g_hal_volume_monitor_finalize (GObject *object) list_free (monitor->disc_volumes); list_free (monitor->disc_mounts); - 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); @@ -208,8 +200,6 @@ 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); @@ -512,19 +502,6 @@ adopt_orphan_mount (GMount *mount, GVolumeMonitor *monitor) } } - /* gphoto2:// as foreign mounts */ - for (l = the_volume_monitor->camera_volumes; l != NULL; l = l->next) - { - GHalVolume *volume = l->data; - - if (g_hal_volume_has_foreign_mount_root (volume, mount_root)) - { - g_hal_volume_adopt_foreign_mount (volume, mount); - ret = g_object_ref (volume); - goto found; - } - } - found: g_object_unref (mount_root); @@ -736,24 +713,6 @@ find_disc_volume_by_udi (GHalVolumeMonitor *monitor, const char *udi) return NULL; } -#ifdef HAVE_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) { @@ -1034,7 +993,6 @@ update_all (GHalVolumeMonitor *monitor, update_discs (monitor, &added_volumes, &removed_volumes, &added_mounts, &removed_mounts); - update_cameras (monitor, &added_volumes, &removed_volumes); G_UNLOCK (hal_vm); if (emit_changes) @@ -1438,122 +1396,3 @@ update_discs (GHalVolumeMonitor *monitor, list_free (monitor->last_optical_disc_devices); monitor->last_optical_disc_devices = new_optical_disc_devices; } - -static void -update_cameras (GHalVolumeMonitor *monitor, - GList **added_volumes, - GList **removed_volumes) -{ -#ifdef HAVE_GPHOTO2 - GList *new_camera_devices; - GList *new_mpt_devices; - GList *removed, *added; - GList *l, *ll; - GHalVolume *volume; - const char *udi; - - new_mpt_devices = hal_pool_find_by_capability (monitor->pool, "portable_audio_player"); - for (l = new_mpt_devices; l != NULL; l = ll) - { - HalDevice *d = l->data; - ll = l->next; - 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_mpt_devices = g_list_delete_link (new_mpt_devices, l); - } - } - - new_camera_devices = hal_pool_find_by_capability (monitor->pool, "camera"); - new_camera_devices = g_list_concat (new_camera_devices, new_mpt_devices); - for (l = new_camera_devices; l != NULL; l = ll) - { - HalDevice *d = l->data; - ll = l->next; - /*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); - *removed_volumes = g_list_prepend (*removed_volumes, 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; - gboolean found; - - /* Look for the device in the added volumes, so as - * not to add devices that are both audio players, and cameras */ - found = FALSE; - for (ll = *added_volumes; ll; ll = ll->next) - { - if (g_hal_volume_has_udi (ll->data, hal_device_get_udi (d)) != FALSE) - { - found = TRUE; - break; - } - } - - if (found) - continue; - - 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); - *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume)); - } - } - - g_list_free (added); - g_list_free (removed); - list_free (monitor->last_camera_devices); - monitor->last_camera_devices = new_camera_devices; -#endif -} diff --git a/po/POTFILES.in b/po/POTFILES.in index 8a593f0f..10f278ae 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -65,6 +65,9 @@ monitor/hal/ghalmount.c monitor/hal/ghalvolume.c monitor/hal/ghalvolumemonitor.c monitor/hal/hal-utils.c +monitor/gphoto2/ggphoto2volume.c +monitor/gphoto2/ggphoto2volumemonitor.c +monitor/gphoto2/hal-utils.c programs/gvfs-cat.c programs/gvfs-copy.c programs/gvfs-info.c |