[Utopia] gnome-vfs patch, take one



Hi!

Attached is my first stab at integrating HAL into gnome-vfs; the patch
should apply against HEAD of gnome-vfs. You can see a screenshot here

 http://freedesktop.org/~david/gnome-vfs-hal1.png

To use it you'll need hal from CVS, g-v-m from CVS and, for the best
experience, something to manage /etc/fstab - hal includes an example
script; use at your own risk. Oh, and obviously some hardware and discs
to play around with.

With all these pieces more or less everything happens automatically.
However, there's still a bunch of work to be done:

 - fixup disc type detection in hal; this topic is currently being
   discussed on the hal mailing list

 - more clever selection of icons and emblems

 - Better selection of names

 - handling of non-usb-storage based cameras (pending libgphoto vfs
   module and halification of libgphoto)

 - and much more.. :-)

Anyway, the basics seems to be working now.

Cheers,
David
? gnome-vfs-hal-patch-prelim-2.patch
? gnome-vfs-hal-patch-prelim.patch
? gnome-vfs-hal-patch1.patch
? libgnomevfs/gnome-vfs-enum-types.c
? libgnomevfs/gnome-vfs-enum-types.h
? libgnomevfs/gnome-vfs-hal-mounts.c
? libgnomevfs/gnome-vfs-hal-mounts.h
? libgnomevfs/s-enum-types-c
? libgnomevfs/s-enum-types-h
? programs/gnomevfs-rm
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-vfs/configure.in,v
retrieving revision 1.293
diff -u -p -r1.293 configure.in
--- configure.in	22 Mar 2004 13:12:10 -0000	1.293
+++ configure.in	6 May 2004 22:10:41 -0000
@@ -546,8 +546,33 @@ if test "x$enable_gnutls" = "xyes"; then
   fi
 fi
 
-PKG_CHECK_MODULES(LIBGNOMEVFS, glib-2.0 >= $GLIB_REQUIRED gmodule-2.0 >= $GLIB_REQUIRED gthread-2.0 >= $GLIB_REQUIRED gconf-2.0 >= $GCONF_REQUIRED bonobo-activation-2.0 >= $BONOBO_ACTIVATION_REQUIRED libbonobo-2.0 >= $BONOBO_REQUIRED ORBit-2.0 >= $ORBIT_REQUIRED libxml-2.0 >= $XML_REQUIRED gnome-mime-data-2.0)
-LIBGNOMEVFS_CFLAGS="$LIBGNOMEVFS_CFLAGS $OPENSSL_CFLAGS $LIBGNUTLS_CFLAGS"
+
+
+dnl ****************************
+dnl HAL stuff
+dnl ****************************
+
+AC_ARG_ENABLE(hal,
+AC_HELP_STRING([--enable-hal],[use hal, if available]),
+[case "${enableval}" in
+yes) ENABLE_HAL=yes ;;
+no)  ENABLE_HAL=no ;;
+*) AC_MSG_ERROR(bad value ${enableval} for --enable-hal) ;;
+esac],
+[ENABLE_HAL=yes]) dnl Default value
+
+if test "x$ENABLE_HAL" = "xyes"; then
+	PKG_CHECK_MODULES(HAL, hal >= 0.2.90,
+		[ USE_HAL="hal >= 0.2.90, dbus-1 >= 0.21, dbus-glib-1 >= 0.21"; HAL_CFLAGS="-DUSE_HAL"],
+		[ USE_HAL=""; HAL_CFLAGS="-UUSE_HAL" ])
+else
+	HAL_CFLAGS="-UUSE_HAL"
+	USE_HAL=""
+fi
+AC_SUBST(HAL_CFLAGS)
+
+PKG_CHECK_MODULES(LIBGNOMEVFS, glib-2.0 >= $GLIB_REQUIRED gmodule-2.0 >= $GLIB_REQUIRED gthread-2.0 >= $GLIB_REQUIRED gconf-2.0 >= $GCONF_REQUIRED bonobo-activation-2.0 >= $BONOBO_ACTIVATION_REQUIRED libbonobo-2.0 >= $BONOBO_REQUIRED ORBit-2.0 >= $ORBIT_REQUIRED libxml-2.0 >= $XML_REQUIRED gnome-mime-data-2.0 $USE_HAL)
+LIBGNOMEVFS_CFLAGS="$LIBGNOMEVFS_CFLAGS $OPENSSL_CFLAGS $LIBGNUTLS_CFLAGS $HAL_CFLAGS"
 LIBGNOMEVFS_LIBS="$LIBGNOMEVFS_LIBS $OPENSSL_LIBS $LIBGNUTLS_LIBS"
 AC_SUBST(LIBGNOMEVFS_CFLAGS)
 AC_SUBST(LIBGNOMEVFS_LIBS)
Index: libgnomevfs/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/Makefile.am,v
retrieving revision 1.122
diff -u -p -r1.122 Makefile.am
--- libgnomevfs/Makefile.am	1 Mar 2004 09:43:30 -0000	1.122
+++ libgnomevfs/Makefile.am	6 May 2004 22:10:42 -0000
@@ -137,6 +137,7 @@ noinst_HEADERS =				\
 	gnome-vfs-daemon-method.h		\
 	gnome-vfs-filesystem-type.h		\
 	gnome-vfs-handle-private.h		\
+	gnome-vfs-hal-mounts.h			\
 	gnome-vfs-i18n.h			\
 	gnome-vfs-iso9660.h			\
 	gnome-vfs-job-queue.h			\
@@ -238,6 +239,7 @@ libgnomevfs_2_la_SOURCES =			\
 	gnome-vfs-filesystem-type.c		\
 	gnome-vfs-find-directory.c		\
 	gnome-vfs-handle.c			\
+	gnome-vfs-hal-mounts.c			\
 	gnome-vfs-i18n.c			\
 	gnome-vfs-inet-connection.c		\
 	gnome-vfs-init.c			\
Index: libgnomevfs/gnome-vfs-drive.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-drive.c,v
retrieving revision 1.4
diff -u -p -r1.4 gnome-vfs-drive.c
--- libgnomevfs/gnome-vfs-drive.c	26 Nov 2003 12:18:38 -0000	1.4
+++ libgnomevfs/gnome-vfs-drive.c	6 May 2004 22:10:42 -0000
@@ -171,6 +171,9 @@ gnome_vfs_drive_finalize (GObject *objec
 	g_free (priv->activation_uri);
 	g_free (priv->display_name);
 	g_free (priv->icon);
+#ifdef USE_HAL
+	g_free (priv->hal_udi);
+#endif
 	g_free (priv);
 	drive->priv = NULL;
 	
Index: libgnomevfs/gnome-vfs-volume-monitor-daemon.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-monitor-daemon.c,v
retrieving revision 1.6
diff -u -p -r1.6 gnome-vfs-volume-monitor-daemon.c
--- libgnomevfs/gnome-vfs-volume-monitor-daemon.c	27 Jan 2004 18:59:13 -0000	1.6
+++ libgnomevfs/gnome-vfs-volume-monitor-daemon.c	6 May 2004 22:10:43 -0000
@@ -34,12 +34,19 @@
 #include "gnome-vfs-cdrom.h"
 #include "gnome-vfs-filesystem-type.h"
 
+#ifdef USE_HAL
+#include "gnome-vfs-hal-mounts.h"
+#endif /* USE_HAL */
+
 static void gnome_vfs_volume_monitor_daemon_class_init (GnomeVFSVolumeMonitorDaemonClass *klass);
 static void gnome_vfs_volume_monitor_daemon_init       (GnomeVFSVolumeMonitorDaemon      *volume_monitor_daemon);
 static void gnome_vfs_volume_monitor_daemon_finalize   (GObject                          *object);
 
+#ifndef USE_HAL
 static void update_fstab_drives (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
 static void update_mtab_volumes (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
+#endif /* !USE_HAL */
+
 static void update_connected_servers (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
 
 typedef struct {
@@ -106,6 +113,7 @@ gnome_vfs_volume_monitor_daemon_class_in
 	o_class->finalize = gnome_vfs_volume_monitor_daemon_finalize;
 }
 
+#ifndef USE_HAL
 static void
 fstab_changed (gpointer data)
 {
@@ -123,6 +131,7 @@ mtab_changed (gpointer data)
 	volume_monitor = data;
 	update_mtab_volumes (volume_monitor);
 }
+#endif  /* !USE_HAL */
 
 static void
 connected_servers_changed (GConfClient* client,
@@ -140,10 +149,14 @@ connected_servers_changed (GConfClient* 
 static void
 gnome_vfs_volume_monitor_daemon_init (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon)
 {
+#ifdef USE_HAL
+	_gnome_vfs_monitor_hal_mounts_init (volume_monitor_daemon);
+#else
 	_gnome_vfs_monitor_unix_mounts (fstab_changed,
 					volume_monitor_daemon,
 					mtab_changed,
 					volume_monitor_daemon);
+#endif /* USE_HAL */
 
 	volume_monitor_daemon->gconf_client = gconf_client_get_default ();
 	gconf_client_add_dir (volume_monitor_daemon->gconf_client,
@@ -160,16 +173,24 @@ gnome_vfs_volume_monitor_daemon_init (Gn
 					 NULL);
 								       
 	
+#ifdef USE_HAL
+	_gnome_vfs_monitor_hal_get_volume_list (volume_monitor_daemon);
+#else
 	update_fstab_drives (volume_monitor_daemon);
 	update_mtab_volumes (volume_monitor_daemon);
+#endif /* USE_HAL */
 	update_connected_servers (volume_monitor_daemon);
 }
 
 void
 gnome_vfs_volume_monitor_daemon_force_probe (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon)
 {
+#ifdef USE_HAL
+	_gnome_vfs_monitor_hal_get_volume_list (volume_monitor_daemon);
+#else
 	update_fstab_drives (volume_monitor_daemon);
 	update_mtab_volumes (volume_monitor_daemon);
+#endif /* USE_HAL */
 	update_connected_servers (volume_monitor_daemon);
 }
 
@@ -184,6 +205,9 @@ gnome_vfs_volume_monitor_daemon_finalize
 		
 	_gnome_vfs_stop_monitoring_unix_mounts ();
 
+#ifdef USE_HAL
+	_gnome_vfs_monitor_hal_mounts_shutdown (volume_monitor_daemon);
+#else
 	g_list_foreach (volume_monitor_daemon->last_mtab,
 			(GFunc)_gnome_vfs_unix_mount_free, NULL);
 	g_list_free (volume_monitor_daemon->last_mtab);
@@ -191,6 +215,7 @@ gnome_vfs_volume_monitor_daemon_finalize
 	g_list_foreach (volume_monitor_daemon->last_fstab,
 			(GFunc)_gnome_vfs_unix_mount_point_free, NULL);
 	g_list_free (volume_monitor_daemon->last_fstab);	
+#endif /* USE_HAL */
 
 	gconf_client_notify_remove (volume_monitor_daemon->gconf_client,
 				    volume_monitor_daemon->connected_id);
@@ -201,6 +226,7 @@ gnome_vfs_volume_monitor_daemon_finalize
 		(* G_OBJECT_CLASS (parent_class)->finalize) (object);
 }
 
+#ifndef USE_HAL
 static GnomeVFSDeviceType
 get_device_type_from_device_and_mount (const char *device_path, const char *mount_path)
 {
@@ -376,6 +402,8 @@ get_icon_from_type (GnomeVFSDeviceType t
 
 	return g_strdup (icon_name);
 }
+#endif /* !USE_HAL */
+
 
 static void
 diff_sorted_lists (GList *list1, GList *list2, GCompareFunc compare,
@@ -412,6 +440,7 @@ diff_sorted_lists (GList *list1, GList *
 
 /************************* fstab drives ***********************************/
 
+#ifndef USE_HAL
 static void
 fixup_mountpoint (GnomeVFSUnixMountPoint *mount)
 {
@@ -861,6 +890,8 @@ update_mtab_volumes (GnomeVFSVolumeMonit
 
 	
 }
+
+#endif /* !USE_HAL */
 
 /************************* connected server ***********************************/
 
Index: libgnomevfs/gnome-vfs-volume-monitor-daemon.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-monitor-daemon.h,v
retrieving revision 1.4
diff -u -p -r1.4 gnome-vfs-volume-monitor-daemon.h
--- libgnomevfs/gnome-vfs-volume-monitor-daemon.h	27 Jan 2004 18:59:13 -0000	1.4
+++ libgnomevfs/gnome-vfs-volume-monitor-daemon.h	6 May 2004 22:10:43 -0000
@@ -29,6 +29,10 @@
 #include <gconf/gconf-client.h>
 #include "gnome-vfs-volume-monitor.h"
 
+#ifdef USE_HAL
+#include <hal/libhal.h>
+#endif /* USE_HAL */
+
 G_BEGIN_DECLS
 
 #define GNOME_VFS_TYPE_VOLUME_MONITOR_DAEMON        (gnome_vfs_volume_monitor_daemon_get_type ())
@@ -43,8 +47,12 @@ typedef struct _GnomeVFSVolumeMonitorDae
 struct _GnomeVFSVolumeMonitorDaemon {
 	GnomeVFSVolumeMonitor parent;
 
+#ifdef USE_HAL
+	LibHalContext *hal_ctx;
+#else
 	GList *last_fstab;
 	GList *last_mtab;
+#endif /* USE_HAL */
 	GList *last_connected_servers;
 	
 	GConfClient *gconf_client;
Index: libgnomevfs/gnome-vfs-volume-monitor-private.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-monitor-private.h,v
retrieving revision 1.4
diff -u -p -r1.4 gnome-vfs-volume-monitor-private.h
--- libgnomevfs/gnome-vfs-volume-monitor-private.h	22 Jan 2004 15:35:01 -0000	1.4
+++ libgnomevfs/gnome-vfs-volume-monitor-private.h	6 May 2004 22:10:43 -0000
@@ -62,6 +62,10 @@ struct _GnomeVFSVolumePrivate {
 
 	/* Only for connected servers */
 	char *gconf_id;
+
+#ifdef USE_HAL
+	char *hal_udi;
+#endif /* USE_HAL */
 };
 
 
@@ -79,6 +83,10 @@ struct _GnomeVFSDrivePrivate {
 	
 	gboolean is_user_visible;
 	gboolean is_connected;
+
+#ifdef USE_HAL
+	char *hal_udi;
+#endif /* USE_HAL */
 };
 
 void _gnome_vfs_volume_set_drive                (GnomeVFSVolume        *volume,
@@ -123,6 +131,14 @@ GnomeVFSDrive * _gnome_vfs_volume_monito
 									      const char            *activation_uri);
 GnomeVFSVolume *_gnome_vfs_volume_monitor_find_connected_server_by_gconf_id  (GnomeVFSVolumeMonitor *volume_monitor,
 									      const char            *id);
+
+#ifdef USE_HAL
+GnomeVFSVolume *_gnome_vfs_volume_monitor_find_volume_by_hal_udi (GnomeVFSVolumeMonitor *volume_monitor,
+								  const char *hal_udi);
+GnomeVFSDrive *_gnome_vfs_volume_monitor_find_drive_by_hal_udi (GnomeVFSVolumeMonitor *volume_monitor,
+								const char           *hal_udi);
+
+#endif /* USE_HAL */
 
 
 char *_gnome_vfs_volume_monitor_uniquify_volume_name (GnomeVFSVolumeMonitor *volume_monitor,
Index: libgnomevfs/gnome-vfs-volume-monitor.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-monitor.c,v
retrieving revision 1.3
diff -u -p -r1.3 gnome-vfs-volume-monitor.c
--- libgnomevfs/gnome-vfs-volume-monitor.c	26 Nov 2003 12:18:38 -0000	1.3
+++ libgnomevfs/gnome-vfs-volume-monitor.c	6 May 2004 22:10:44 -0000
@@ -253,6 +253,54 @@ _gnome_vfs_volume_monitor_shutdown (void
 }
 
 
+
+#ifdef USE_HAL
+GnomeVFSVolume *
+_gnome_vfs_volume_monitor_find_volume_by_hal_udi (GnomeVFSVolumeMonitor *volume_monitor,
+						  const char *hal_udi)
+{
+	GList *l;
+	GnomeVFSVolume *vol, *ret;
+
+	/* Doesn't need locks, only called internally on main thread and doesn't write */
+	
+	ret = NULL;
+	for (l = volume_monitor->priv->mtab_volumes; l != NULL; l = l->next) {
+		vol = l->data;
+		if (vol->priv->activation_uri != NULL &&
+		    strcmp (vol->priv->hal_udi, hal_udi) == 0) {
+			ret = vol;
+			break;
+		}
+	}
+	
+	return ret;
+}
+
+GnomeVFSDrive *
+_gnome_vfs_volume_monitor_find_drive_by_hal_udi (GnomeVFSVolumeMonitor *volume_monitor,
+						 const char           *hal_udi)
+{
+	GList *l;
+	GnomeVFSDrive *drive, *ret;
+
+	/* Doesn't need locks, only called internally on main thread and doesn't write */
+	
+	ret = NULL;
+	for (l = volume_monitor->priv->fstab_drives; l != NULL; l = l->next) {
+		drive = l->data;
+		if (drive->priv->activation_uri != NULL &&
+		    strcmp (drive->priv->hal_udi, hal_udi) == 0) {
+			ret = drive;
+			break;
+		}
+	}
+
+	return ret;
+}
+#endif /* USE_HAL */
+
+
 GnomeVFSVolume *
 _gnome_vfs_volume_monitor_find_mtab_volume_by_activation_uri (GnomeVFSVolumeMonitor *volume_monitor,
 							      const char *activation_uri)
Index: libgnomevfs/gnome-vfs-volume.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume.c,v
retrieving revision 1.4
diff -u -p -r1.4 gnome-vfs-volume.c
--- libgnomevfs/gnome-vfs-volume.c	26 Nov 2003 12:18:38 -0000	1.4
+++ libgnomevfs/gnome-vfs-volume.c	6 May 2004 22:10:44 -0000
@@ -136,6 +136,9 @@ gnome_vfs_volume_finalize (GObject *obje
 	g_free (priv->display_name);
 	g_free (priv->icon);
 	g_free (priv->gconf_id);
+#ifdef USE_HAL
+	g_free (priv->hal_udi);
+#endif
 	g_free (priv);
 	volume->priv = NULL;
 	
--- /dev/null	2004-05-06 18:32:25.967484712 +0200
+++ libgnomevfs/gnome-vfs-hal-mounts.h	2004-05-06 22:57:38.242852680 +0200
@@ -0,0 +1,45 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gnome-vfs-hal-mounts.h - read and monitor volumes using freedesktop HAL
+
+   Copyright (C) 2004 David Zeuthen
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: David Zeuthen <david fubar dk>
+*/
+
+#ifndef GNOME_VFS_HAL_MOUNTS_H
+#define GNOME_VFS_HAL_MOUNTS_H
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <hal/libhal.h>
+#include <dbus/dbus-glib.h>
+
+#include "gnome-vfs-volume-monitor-daemon.h"
+
+void _gnome_vfs_monitor_hal_mounts_init (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
+
+void _gnome_vfs_monitor_hal_mounts_shutdown (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
+
+void _gnome_vfs_monitor_hal_get_volume_list (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon);
+
+
+
+#endif /* GNOME_VFS_HAL_MOUNTS_H */
--- /dev/null	2004-05-06 18:32:25.967484712 +0200
+++ libgnomevfs/gnome-vfs-hal-mounts.c	2004-05-06 23:58:24.383555040 +0200
@@ -0,0 +1,614 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gnome-vfs-hal-mounts.c - read and monitor volumes using freedesktop HAL
+
+   Copyright (C) 2004 David Zeuthen
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: David Zeuthen <david fubar dk>
+*/
+
+#ifdef USE_HAL
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/sysmacros.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-i18n.h>
+
+#include "gnome-vfs-hal-mounts.h"
+#include "gnome-vfs-volume-monitor-daemon.h"
+#include "gnome-vfs-volume-monitor-private.h"
+
+
+/*
+static void dump_vol (GnomeVFSVolume *vol)
+{
+	FILE *f;
+	f = fopen ("/tmp/dz", "a");
+	fprintf (f, "VOLUME\n");
+	fprintf (f, "-----------------------\n");
+	fprintf (f, "volume_type = %d\n", vol->priv->volume_type);
+	fprintf (f, "device_path = %s\n", vol->priv->device_path);
+	fprintf (f, "unix_device= %d,%d\n", major(vol->priv->unix_device), minor(vol->priv->unix_device));
+	fprintf (f, "activation_uri = %s\n", vol->priv->activation_uri);
+	fprintf (f, "filesystem_type = %s\n", vol->priv->filesystem_type);
+	fprintf (f, "is_read_only = %d\n", vol->priv->is_read_only);
+	fprintf (f, "is_mounted = %d\n", vol->priv->is_mounted);
+	fprintf (f, "device_type = %d\n", vol->priv->device_type);
+	fprintf (f, "display_name = %s\n", vol->priv->display_name);
+	fprintf (f, "icon = %s\n", vol->priv->icon);
+	fprintf (f, "is_user_visible = %d\n", vol->priv->is_user_visible);
+	fprintf (f, "drive = %X\n", (unsigned int) vol->priv->drive);
+	fprintf (f, "-----------------------\n");
+	fprintf (f, "\n");
+	fclose (f);
+}
+
+
+static void dump_drive (GnomeVFSDrive *drv)
+{
+	FILE *f;
+	f = fopen ("/tmp/dz", "a");
+	fprintf (f, "DRIVE\n");
+	fprintf (f, "-----------------------\n");
+	fprintf (f, "device_path = %s\n", drv->priv->device_path);
+	fprintf (f, "activation_uri = %s\n", drv->priv->activation_uri);
+	fprintf (f, "is_connected = %d\n", drv->priv->is_connected);
+	fprintf (f, "device_type = %d\n", drv->priv->device_type);
+	fprintf (f, "icon = %s\n", drv->priv->icon);
+	fprintf (f, "display_name = %s\n", drv->priv->display_name);
+	fprintf (f, "is_user_visible = %d\n", drv->priv->is_user_visible);
+	fprintf (f, "volume = %X\n", (unsigned int) drv->priv->volume);
+	fprintf (f, "-----------------------\n");
+	fprintf (f, "\n");
+	fclose (f);
+}
+*/
+
+
+/** Add a hal-volume, that is, a HalDevice of capability 'volume'. 
+ *
+ *  It's safe to call this function multiple times for the same HAL 
+ *  UDI (Unique Device Identifier).
+ */
+static void 
+_hal_add_volume (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon,
+		 const char *udi)
+{
+	char *fstype = NULL;
+	char *device_file = NULL;
+	char *mount_point = NULL;
+	char *storage_vendor = NULL;
+	char *storage_model = NULL;
+	char *drive_type = NULL;
+	char *storage_udi = NULL;
+	char *disc_type = NULL;
+	char *volume_label = NULL;
+	gboolean storage_is_hotpluggable = FALSE;
+	gboolean storage_is_removable = FALSE;
+	GnomeVFSDrive *drive;
+	GnomeVFSVolume *vol;
+	GnomeVFSVolumeMonitor *volume_monitor;
+	char *name = NULL;
+	char *icon = "gnome-dev-harddisk";
+	GnomeVFSDeviceType device_type = GNOME_VFS_DEVICE_TYPE_UNKNOWN;
+	gboolean computer_visible = TRUE;
+	gboolean desktop_visible = FALSE;
+	int major, minor;
+
+	volume_monitor = GNOME_VFS_VOLUME_MONITOR (volume_monitor_daemon);
+
+	/* only care about capability volume */
+	if (!hal_device_query_capability (
+		    volume_monitor_daemon->hal_ctx,
+		    udi, "volume"))
+		goto out;
+
+	major = hal_device_get_property_int (volume_monitor_daemon->hal_ctx,
+					     udi, "block.major");
+	minor = hal_device_get_property_int (volume_monitor_daemon->hal_ctx,
+					     udi, "block.minor");
+
+	/* XXX special case audio cd */
+	if (hal_device_property_exists (
+		    volume_monitor_daemon->hal_ctx,
+		    udi, "volume.disc_type") &&
+	    ((strcmp ("audio", hal_device_get_property_string (
+			      volume_monitor_daemon->hal_ctx,
+			      udi, "volume.disc_type")) == 0) ||
+	     (strcmp ("mixed", hal_device_get_property_string (
+			      volume_monitor_daemon->hal_ctx,
+			      udi, "volume.disc_type")) == 0))) {
+		;
+	}
+
+
+	/* only care about mounted volumes */
+	if (!hal_device_property_exists (
+		    volume_monitor_daemon->hal_ctx,
+		    udi, "volume.is_mounted") ||
+	    !hal_device_get_property_bool (
+		    volume_monitor_daemon->hal_ctx,
+		    udi, "volume.is_mounted")) {
+		/* XXX hmm, what about Audio CD's and blank CD's */
+		goto out;
+	}
+			    
+	storage_udi = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		udi, "block.storage_device");	
+	if (storage_udi == NULL)
+		goto out;
+
+	device_file = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		udi, "block.device");
+	if (device_file == NULL)
+		goto out;
+
+	mount_point = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		udi, "volume.mount_point");
+	if (mount_point == NULL || strlen (mount_point) == 0)
+		goto out;
+
+	fstype = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		udi, "volume.fstype");
+	if (fstype == NULL || strlen (fstype) == 0)
+		goto out;
+
+	storage_vendor = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		storage_udi, "storage.vendor");
+	if (storage_vendor == NULL)
+		goto out;
+
+	storage_model = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		storage_udi, "storage.model");
+
+	if (storage_model == NULL)
+		goto out;
+
+	if (hal_device_property_exists (
+		    volume_monitor_daemon->hal_ctx,
+		    udi, "volume.label")) {
+		volume_label = hal_device_get_property_string (
+			volume_monitor_daemon->hal_ctx,
+			udi, "volume.label");
+		if (strlen (volume_label) == 0)
+			volume_label = NULL;
+	}
+
+	drive_type = hal_device_get_property_string (
+		volume_monitor_daemon->hal_ctx,
+		storage_udi, "storage.drive_type");
+
+	if (drive_type == NULL)
+		goto out;
+	
+	/* see if hal-volume is already added */
+	vol = gnome_vfs_volume_monitor_get_volume_for_path (
+		volume_monitor, mount_point);
+	if (vol != NULL ) {
+		/* yep, don't add it again */
+		gnome_vfs_volume_unref (vol);
+		goto out;
+	}
+
+	storage_is_hotpluggable = hal_device_get_property_bool (
+		volume_monitor_daemon->hal_ctx,
+		storage_udi, "storage.hotpluggable");
+
+	storage_is_removable = hal_device_get_property_bool (
+		volume_monitor_daemon->hal_ctx,
+		storage_udi, "storage.removable");
+	
+	/*  now have all the generic information required to add the
+	 *  hal-volume (and we know it should be added); all we need to
+	 *  do now is to use all the stuff provided by hal
+	 *
+	 *  This boils down to that need to set 
+	 *
+	 *   - name; as displayed in Nautilus; needs to be localisable
+	 *
+	 *   - icon; string with name of icon to use..
+	 *
+	 *   - device_type; a GnomeVFSDeviceType value
+	 *
+	 */
+
+	if (strcmp (drive_type, "cdrom") == 0) {
+		char *disc_type_name;
+
+		/* XXX fixup HAL to put this property on the storage device..
+		 * hmmm... */
+		disc_type = hal_device_get_property_string (
+			volume_monitor_daemon->hal_ctx,
+			udi, "volume.disc_type");
+		if (disc_type == NULL)
+			goto out;
+
+		/* fallback option */
+		disc_type_name = "Optical Disc";
+
+		/* Enough gathering.. */
+		device_type = GNOME_VFS_DEVICE_TYPE_CDROM;
+		if (strcmp (disc_type, "audio") == 0) {
+			device_type = GNOME_VFS_DEVICE_TYPE_AUDIO_CD;
+			icon = "gnome-dev-cdrom-audio";
+			/* XXX cdda stuff */
+		} else if (strcmp (disc_type, "mixed") == 0) {
+			icon = "gnome-dev-cdrom-audio";
+			disc_type_name = _("CD disc");
+		} else if (strcmp (disc_type, "data") == 0) {
+			icon = "gnome-dev-cdrom";
+			disc_type_name = _("CD disc");
+		} else if (strcmp (disc_type, "blank") == 0) {
+			icon = "gnome-dev-cdrom";
+			disc_type_name = _("CD-R disc");
+			/* XXX what about CD-RW? */
+		} else if (strcmp (disc_type, "dvd_rom") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD-ROM disc");
+		} else if (strcmp (disc_type, "dvd_r") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD-R disc");
+		} else if (strcmp (disc_type, "dvd_ram") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD-RAM disc");
+		} else if (strcmp (disc_type, "dvd_rw_restricted_overwrite") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD-RW disc");
+		} else if (strcmp (disc_type, "dvd_rw") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD-RW disc");
+		} else if (strcmp (disc_type, "dvd_plus_rw") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD+RW disc");
+		} else if (strcmp (disc_type, "dvdplusr") == 0) {
+			icon = "gnome-dev-dvd";
+			disc_type_name = _("DVD+R disc");
+		}
+
+		if (volume_label != NULL ) {
+			name = g_strdup (volume_label);
+		} else {
+			name = g_strdup (disc_type_name);
+		}
+
+		desktop_visible = TRUE;
+	} else if (strcmp (drive_type, "disk") == 0 ||
+		   strcmp (drive_type, "compact_flash") == 0 ||
+		   strcmp (drive_type, "memory_stick") == 0 ||
+		   strcmp (drive_type, "smart_media") == 0 ||
+		   strcmp (drive_type, "sd_mmc") == 0 ) {
+
+		/* XXX inspect storage.bus to select eleet USB, FW icons */
+		icon = "gnome-dev-harddisk";
+		device_type = GNOME_VFS_DEVICE_TYPE_HARDDRIVE;
+
+		/* XXX select appropriate icon cf type above */
+		if (strcmp (drive_type, "disk") != 0 ) {
+			icon = "gnome-dev-zipdisk";
+		}
+
+		if (storage_is_hotpluggable || storage_is_removable) {
+			/* Show us in computer:/// + desktop if we're either 
+			 * hotpluggable or removable
+			 */
+			computer_visible = TRUE;
+			desktop_visible = TRUE;
+		} else {
+			/* Prolly just a hard drive since we're neither
+			 * hotpluggable nor removable
+			 */
+			computer_visible = FALSE;
+			desktop_visible = FALSE;
+		}
+
+		if (volume_label != NULL ) {
+			/* We're for sure not a UNIX volume (we got a real
+			 * volume label, eeiww, so show us in computer:///
+			 */
+			name = g_strdup (volume_label);
+			computer_visible = TRUE;
+		}
+		else
+			name = g_strdup (_("Mass Storage Device"));
+	} else {
+		/* default; XXX cookup nice name */
+		name = g_strdup (storage_model);
+		icon = "gnome-dev-removable";
+		device_type = GNOME_VFS_DEVICE_TYPE_UNKNOWN;
+	}
+
+	drive = g_object_new (GNOME_VFS_TYPE_DRIVE, NULL);
+	drive->priv->device_path = g_strdup (device_file);
+	drive->priv->activation_uri = gnome_vfs_get_uri_from_local_path (mount_point);
+	drive->priv->is_connected = TRUE;
+	drive->priv->device_type = device_type;
+	drive->priv->icon = g_strdup (icon);
+	drive->priv->display_name = _gnome_vfs_volume_monitor_uniquify_drive_name (volume_monitor, name);
+	drive->priv->is_user_visible = computer_visible;
+	drive->priv->volume = NULL;
+	drive->priv->hal_udi = g_strdup (udi);
+
+	_gnome_vfs_volume_monitor_connected (volume_monitor, drive);
+
+	/*dump_drive (drive);*/
+
+	gnome_vfs_drive_unref (drive);
+
+	vol = g_object_new (GNOME_VFS_TYPE_VOLUME, NULL);
+	vol->priv->volume_type = GNOME_VFS_VOLUME_TYPE_MOUNTPOINT;
+	vol->priv->device_path = g_strdup (device_file);
+	vol->priv->unix_device = makedev (major, minor);
+	vol->priv->activation_uri = gnome_vfs_get_uri_from_local_path (mount_point);
+	vol->priv->filesystem_type = g_strdup (fstype);
+	vol->priv->is_read_only = FALSE;
+	vol->priv->is_mounted = TRUE;
+
+	vol->priv->device_type = device_type;
+
+	vol->priv->display_name = _gnome_vfs_volume_monitor_uniquify_volume_name (volume_monitor, name);
+	vol->priv->icon = g_strdup(icon);
+	vol->priv->is_user_visible = desktop_visible;
+	vol->priv->hal_udi = g_strdup (udi);
+
+	vol->priv->drive = drive;
+	_gnome_vfs_drive_set_mounted_volume (drive, vol);
+
+	_gnome_vfs_volume_monitor_mounted (volume_monitor, vol);
+
+	/*dump_vol (vol);*/
+
+	/*
+	{
+		FILE *f;
+		f = fopen ("/tmp/dz", "a");
+		fprintf (f, "Adding udi=%s\n", udi);
+		fclose (f);
+	}
+	*/
+
+
+out:
+	g_free (name);
+	hal_free_string (fstype);
+	hal_free_string (device_file);
+	hal_free_string (mount_point);
+	hal_free_string (volume_label);
+	hal_free_string (storage_vendor);
+	hal_free_string (storage_model);
+	hal_free_string (drive_type);
+	hal_free_string (storage_udi);
+	hal_free_string (disc_type);
+}
+
+
+/** Remove a hal-volume, that is, a HalDevice of capability 'volume'. 
+ *
+ *  It's safe to call this function even though the hal-volume doesn't
+ *  correspond to any (GnomeVFSDrive, GnomeVFSVolume) pair.
+ */
+static void 
+_hal_remove_volume (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon,
+		    const char *udi)
+{
+	GnomeVFSDrive *drive;
+	GnomeVFSVolume *vol;
+	GnomeVFSVolumeMonitor *volume_monitor;
+
+	volume_monitor = GNOME_VFS_VOLUME_MONITOR (volume_monitor_daemon);
+
+	drive = _gnome_vfs_volume_monitor_find_drive_by_hal_udi (
+		volume_monitor, udi);
+
+	if (drive != NULL ) {
+		_gnome_vfs_volume_monitor_disconnected (volume_monitor, drive);
+
+		/*
+		{
+			FILE *f;
+			f = fopen ("/tmp/dz", "a");
+			fprintf (f, "Removing udi=%s (drive)\n", udi);
+			fclose (f);
+		}
+		*/
+	}
+
+	vol = _gnome_vfs_volume_monitor_find_volume_by_hal_udi (
+		volume_monitor, udi);
+
+	if (vol != NULL ) {
+		_gnome_vfs_volume_monitor_unmounted (volume_monitor, vol);
+
+		/*
+		{
+			FILE *f;
+			f = fopen ("/tmp/dz", "a");
+			fprintf (f, "Removing udi=%s (vol)\n", udi);
+			fclose (f);
+		}
+		*/
+	}
+}
+
+void 
+_gnome_vfs_monitor_hal_get_volume_list (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon)
+{
+	int i;
+	int num_hal_volumes;
+	char **hal_volumes;
+	GnomeVFSVolumeMonitor *volume_monitor;
+
+	volume_monitor = GNOME_VFS_VOLUME_MONITOR (volume_monitor_daemon);
+
+	hal_volumes = hal_find_device_by_capability (
+		volume_monitor_daemon->hal_ctx,
+		"volume",
+		&num_hal_volumes);
+
+	for (i=0; i<num_hal_volumes; i++) {
+		char *udi;
+
+		udi = hal_volumes [i];
+
+		_hal_add_volume (volume_monitor_daemon, udi);
+	}
+
+	hal_free_string_array (hal_volumes);
+}
+
+static void
+_hal_mainloop_integration (LibHalContext *ctx, 
+			   DBusConnection * dbus_connection)
+{
+        dbus_connection_setup_with_g_main (dbus_connection, NULL);
+}
+
+static void 
+_hal_device_added (LibHalContext *ctx, 
+		   const char *udi)
+{
+	GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon;
+	volume_monitor_daemon = (GnomeVFSVolumeMonitorDaemon *)
+		hal_ctx_get_user_data (ctx);
+	_hal_add_volume (volume_monitor_daemon, udi);
+}
+
+static void 
+_hal_device_removed (LibHalContext *ctx, 
+		     const char *udi)
+{
+	GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon;
+
+	/*
+	{
+		FILE *f;
+		f = fopen ("/tmp/dz", "a");
+		fprintf (f, "_hal_device_removed udi=%s\n", udi);
+		fclose (f);
+	}
+	*/
+
+
+	volume_monitor_daemon = (GnomeVFSVolumeMonitorDaemon *)
+		hal_ctx_get_user_data (ctx);
+	_hal_remove_volume (volume_monitor_daemon, udi);
+}
+
+static void 
+_hal_device_new_capability (LibHalContext *ctx, 
+			    const char *udi, 
+			    const char *capability)
+{
+	GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon;
+	volume_monitor_daemon = (GnomeVFSVolumeMonitorDaemon *)
+		hal_ctx_get_user_data (ctx);
+	_hal_add_volume (volume_monitor_daemon, udi);
+}
+
+static void 
+_hal_device_lost_capability (LibHalContext *ctx, 
+			     const char *udi,
+			     const char *capability)
+{
+}
+
+static void 
+_hal_device_property_modified (LibHalContext *ctx, 
+			       const char *udi,
+			       const char *key,
+			       dbus_bool_t is_removed,
+			       dbus_bool_t is_added)
+{
+	GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon;
+	volume_monitor_daemon = (GnomeVFSVolumeMonitorDaemon *)
+		hal_ctx_get_user_data (ctx);
+
+	if (!is_removed && strcmp (key, "volume.is_mounted") == 0) {
+		dbus_bool_t is_mounted;
+
+		is_mounted = hal_device_get_property_bool(
+			ctx, udi, "volume.is_mounted");
+
+		if( is_mounted )
+			_hal_add_volume (volume_monitor_daemon, udi);
+		else
+			_hal_remove_volume (volume_monitor_daemon, udi);
+							  
+	} else {
+		_hal_add_volume (volume_monitor_daemon, udi);
+	}
+}
+
+static void 
+_hal_device_condition (LibHalContext *ctx, 
+		       const char *udi,
+		       const char *condition_name,
+		       DBusMessage *message)
+{
+	GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon;
+	volume_monitor_daemon = (GnomeVFSVolumeMonitorDaemon *)
+		hal_ctx_get_user_data (ctx);
+
+	if (strcmp (condition_name, "BlockForcedUnmountPartition") == 0) {
+		_hal_remove_volume (volume_monitor_daemon, udi);
+	}
+}
+
+static LibHalFunctions
+hal_functions = { _hal_mainloop_integration,
+		  _hal_device_added,
+		  _hal_device_removed,
+		  _hal_device_new_capability,
+		  _hal_device_lost_capability,
+		  _hal_device_property_modified,
+		  _hal_device_condition };
+
+void
+_gnome_vfs_monitor_hal_mounts_init (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon)
+{
+	/* initialise the connection to the hal daemon */
+	if ((volume_monitor_daemon->hal_ctx = 
+	     hal_initialize (&hal_functions, FALSE)) == NULL) {
+		g_warning ("hal_initialize failed\n");
+		/* XXX how should this be handled? */
+		exit (1);
+	}
+
+	hal_ctx_set_user_data (volume_monitor_daemon->hal_ctx,
+			       volume_monitor_daemon);
+
+	hal_device_property_watch_all (volume_monitor_daemon->hal_ctx);
+}
+
+void
+_gnome_vfs_monitor_hal_mounts_shutdown (GnomeVFSVolumeMonitorDaemon *volume_monitor_daemon)
+{
+	if (hal_shutdown (volume_monitor_daemon->hal_ctx) != 0) {
+		g_warning ("hal_shutdown failed\n");
+	}
+}
+
+#endif /* USE_HAL */


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