From 8924b724ebc40e630f14577234fc37daa06854be Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 13 Sep 2007 13:36:17 +0000 Subject: Add initial GDaemonVolume and GDaemonVolumeMonitor sources. Original git commit by Hans Petter Jansson at 1178826338 -0500 svn path=/trunk/; revision=550 --- client/Makefile.am | 2 + client/gdaemonvolume.c | 182 +++++++++++++++++++++++++ client/gdaemonvolume.h | 33 +++++ client/gdaemonvolumemonitor.c | 306 ++++++++++++++++++++++++++++++++++++++++++ client/gdaemonvolumemonitor.h | 33 +++++ 5 files changed, 556 insertions(+) create mode 100644 client/gdaemonvolume.c create mode 100644 client/gdaemonvolume.h create mode 100644 client/gdaemonvolumemonitor.c create mode 100644 client/gdaemonvolumemonitor.h (limited to 'client') diff --git a/client/Makefile.am b/client/Makefile.am index 12a5cbae..1077b786 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -14,6 +14,8 @@ modules_LTLIBRARIES = libgvfsdbus.la libgvfsdbus_la_LDFLAGS = $(module_flags) libgvfsdbus_la_SOURCES = \ gdaemonvfs.c gdaemonvfs.h \ + gdaemonvolume.c gdaemonvolume.h \ + gdaemonvolumemonitor.c gdaemonvolumemonitor.h \ gdaemonfile.c gdaemonfile.h \ gvfsuriutils.c gvfsuriutils.h \ gdaemonfileinputstream.c gdaemonfileinputstream.h \ diff --git a/client/gdaemonvolume.c b/client/gdaemonvolume.c new file mode 100644 index 00000000..d51da304 --- /dev/null +++ b/client/gdaemonvolume.c @@ -0,0 +1,182 @@ +#include + +#include + +#include +#include +#include "gdaemonvolumemonitor.h" +#include "gdaemonvolume.h" +#include "gdaemondrive.h" + +struct _GDaemonVolume { + GObject parent; + + GMountInfo *mount_info; + char *name; + char *icon; +}; + +static void g_daemon_volume_volume_iface_init (GVolumeIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GDaemonVolume, g_daemon_volume, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, + g_daemon_volume_volume_iface_init)) + + +static void +g_daemon_volume_finalize (GObject *object) +{ + GDaemonVolume *volume; + + volume = G_DAEMON_VOLUME (object); + + g_free (volume->name); + g_free (volume->icon); + _g_mount_info_unref (volume->mount_info); + + if (G_OBJECT_CLASS (g_daemon_volume_parent_class)->finalize) + (*G_OBJECT_CLASS (g_daemon_volume_parent_class)->finalize) (object); +} + +static void +g_daemon_volume_class_init (GDaemonVolumeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_daemon_volume_finalize; +} + +static void +g_daemon_volume_init (GDaemonVolume *daemon_volume) +{ +} + +GDaemonVolume * +g_daemon_volume_new (GVolumeMonitor *volume_monitor, + GMountInfo *mount_info) +{ + GDaemonVolume *volume; + char *volume_name; + + volume = g_object_new (G_TYPE_DAEMON_VOLUME, NULL); + volume->mount_info = _g_mount_info_ref (mount_info); + + volume_name = NULL; + + if (volume_name == NULL) + { + /* TODO: Use volume size as name? */ + volume_name = g_strdup (_("Unknown volume")); + } + + volume->name = volume_name; + + /* TODO: Figure out a better icon */ + volume->icon = g_strdup ("network"); + + return volume; +} + +static char * +g_daemon_volume_get_platform_id (GVolume *volume) +{ + GDaemonVolume *daemon_volume = G_DAEMON_VOLUME (volume); + + return g_strdup (daemon_volume->mount_info->spec->mount_prefix); +} + +static GFile * +g_daemon_volume_get_root (GVolume *volume) +{ + GDaemonVolume *daemon_volume = G_DAEMON_VOLUME (volume); + + return g_file_get_for_path (daemon_volume->mount_info->spec->mount_prefix); +} + +static char * +g_daemon_volume_get_icon (GVolume *volume) +{ + GDaemonVolume *daemon_volume = G_DAEMON_VOLUME (volume); + + return g_strdup (daemon_volume->icon); +} + +static char * +g_daemon_volume_get_name (GVolume *volume) +{ + GDaemonVolume *daemon_volume = G_DAEMON_VOLUME (volume); + + return g_strdup (daemon_volume->name); +} + +static GDrive * +g_daemon_volume_get_drive (GVolume *volume) +{ + GDaemonVolume *daemon_volume = G_DAEMON_VOLUME (volume); + + daemon_volume = NULL; + + return NULL; +} + +static gboolean +g_daemon_volume_can_unmount (GVolume *volume) +{ + /* TODO */ + return TRUE; +} + +static gboolean +g_daemon_volume_can_eject (GVolume *volume) +{ + /* TODO */ + return FALSE; +} + +static void +g_daemon_volume_unmount (GVolume *volume, + GAsyncReadyCallback callback, + gpointer user_data) +{ + /* TODO */ +} + +static gboolean +g_daemon_volume_unmount_finish (GVolume *volume, + GAsyncResult *result, + GError **error) +{ + return TRUE; +} + +static void +g_daemon_volume_eject (GVolume *volume, + GAsyncReadyCallback callback, + gpointer user_data) +{ + /* TODO */ +} + +static gboolean +g_daemon_volume_eject_finish (GVolume *volume, + GAsyncResult *result, + GError **error) +{ + return TRUE; +} + +static void +g_daemon_volume_volume_iface_init (GVolumeIface *iface) +{ + iface->get_root = g_daemon_volume_get_root; + iface->get_name = g_daemon_volume_get_name; + iface->get_icon = g_daemon_volume_get_icon; + iface->get_drive = g_daemon_volume_get_drive; + iface->can_unmount = g_daemon_volume_can_unmount; + iface->can_eject = g_daemon_volume_can_eject; + iface->unmount = g_daemon_volume_unmount; + iface->unmount_finish = g_daemon_volume_unmount_finish; + iface->eject = g_daemon_volume_eject; + iface->eject_finish = g_daemon_volume_eject_finish; + iface->get_platform_id = g_daemon_volume_get_platform_id; +} diff --git a/client/gdaemonvolume.h b/client/gdaemonvolume.h new file mode 100644 index 00000000..59512545 --- /dev/null +++ b/client/gdaemonvolume.h @@ -0,0 +1,33 @@ +#ifndef __G_DAEMON_VOLUME_H__ +#define __G_DAEMON_VOLUME_H__ + +#include +#include +#if 0 +# include +#endif +#include "gdaemonvfs.h" +#include "gdaemonvolumemonitor.h" + +G_BEGIN_DECLS + +#define G_TYPE_DAEMON_VOLUME (g_daemon_volume_get_type ()) +#define G_DAEMON_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_VOLUME, GDaemonVolume)) +#define G_DAEMON_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_VOLUME, GDaemonVolumeClass)) +#define G_IS_DAEMON_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_VOLUME)) +#define G_IS_DAEMON_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_VOLUME)) + +typedef struct _GDaemonVolumeClass GDaemonVolumeClass; + +struct _GDaemonVolumeClass { + GObjectClass parent_class; +}; + +GType g_daemon_volume_get_type (void) G_GNUC_CONST; + +GDaemonVolume *g_daemon_volume_new (GVolumeMonitor *volume_monitor, + GMountInfo *mount_info); + +G_END_DECLS + +#endif /* __G_DAEMON_VOLUME_H__ */ diff --git a/client/gdaemonvolumemonitor.c b/client/gdaemonvolumemonitor.c new file mode 100644 index 00000000..115271cf --- /dev/null +++ b/client/gdaemonvolumemonitor.c @@ -0,0 +1,306 @@ +#include + +#include + +#include +#include +#include "gdaemonvolumemonitor.h" +#include "gdaemonvolume.h" + +struct _GDaemonVolumeMonitor { + GVolumeMonitor parent; + + gpointer mount_monitor; + + GList *last_mountpoints; + GList *last_mounts; + + GList *drives; + GList *volumes; +}; + +static void update_drives (GDaemonVolumeMonitor *monitor); +static void update_volumes (GDaemonVolumeMonitor *monitor); + +G_DEFINE_TYPE (GDaemonVolumeMonitor, g_daemon_volume_monitor, G_TYPE_VOLUME_MONITOR); + +static void +g_daemon_volume_monitor_finalize (GObject *object) +{ + GDaemonVolumeMonitor *monitor; + + monitor = G_DAEMON_VOLUME_MONITOR (object); + + if (monitor->mount_monitor) + _g_stop_monitoring_daemon_mounts (monitor->mount_monitor); + + g_list_foreach (monitor->last_mounts, (GFunc)_g_daemon_mount_free, NULL); + g_list_free (monitor->last_mounts); + + g_list_foreach (monitor->volumes, (GFunc)g_object_unref, NULL); + g_list_free (monitor->volumes); + g_list_foreach (monitor->drives, (GFunc)g_object_unref, NULL); + g_list_free (monitor->drives); + + if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) + (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) (object); +} + +static GList * +get_mounted_volumes (GVolumeMonitor *volume_monitor) +{ + GDaemonVolumeMonitor *monitor; + GList *l; + + monitor = G_DAEMON_VOLUME_MONITOR (volume_monitor); + + l = g_list_copy (monitor->volumes); + g_list_foreach (l, (GFunc)g_object_ref, NULL); + + return l; +} + +static GList * +get_connected_drives (GVolumeMonitor *volume_monitor) +{ + GDaemonVolumeMonitor *monitor; + GList *l; + + monitor = G_DAEMON_VOLUME_MONITOR (volume_monitor); + + l = g_list_copy (monitor->drives); + g_list_foreach (l, (GFunc)g_object_ref, NULL); + + return l; +} + +static void +g_daemon_volume_monitor_class_init (GDaemonVolumeMonitorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); + + gobject_class->finalize = g_daemon_volume_monitor_finalize; + + monitor_class->get_mounted_volumes = get_mounted_volumes; + monitor_class->get_connected_drives = get_connected_drives; +} + +static void +mountpoints_changed (gpointer user_data) +{ + GDaemonVolumeMonitor *daemon_monitor = user_data; + + /* Update both to make sure drives are created before volumes */ + update_drives (daemon_monitor); + update_volumes (daemon_monitor); +} + +static void +mounts_changed (gpointer user_data) +{ + GDaemonVolumeMonitor *daemon_monitor = user_data; + + /* Update both to make sure drives are created before volumes */ + update_drives (daemon_monitor); + update_volumes (daemon_monitor); +} + +static void +g_daemon_volume_monitor_init (GDaemonVolumeMonitor *daemon_monitor) +{ + + daemon_monitor->mount_monitor = _g_monitor_daemon_mounts (mountpoints_changed, + mounts_changed, + daemon_monitor); + update_drives (daemon_monitor); + update_volumes (daemon_monitor); + +} + +GVolumeMonitor * +g_daemon_volume_monitor_new (void) +{ + GDaemonVolumeMonitor *monitor; + + monitor = g_object_new (G_TYPE_DAEMON_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; + } +} + +GDaemonDrive * +g_daemon_volume_monitor_lookup_drive_for_mountpoint (GDaemonVolumeMonitor *monitor, + const char *mountpoint) +{ + GList *l; + + for (l = monitor->drives; l != NULL; l = l->next) + { + GDaemonDrive *drive = l->data; + + if (g_daemon_drive_has_mountpoint (drive, mountpoint)) + return drive; + } + + return NULL; +} + +static GDaemonVolume * +find_volume_by_mountpoint (GDaemonVolumeMonitor *monitor, + const char *mountpoint) +{ + GList *l; + + for (l = monitor->volumes; l != NULL; l = l->next) + { + GDaemonVolume *volume = l->data; + + if (g_daemon_volume_has_mountpoint (volume, mountpoint)) + return volume; + } + + return NULL; +} + +static void +update_drives (GDaemonVolumeMonitor *monitor) +{ + GList *new_mountpoints; + GList *removed, *added; + GList *l; + GDaemonDrive *drive; + + if (_g_get_daemon_mount_points (&new_mountpoints)) + { + new_mountpoints = g_list_sort (new_mountpoints, (GCompareFunc) _g_daemon_mount_point_compare); + + diff_sorted_lists (monitor->last_mountpoints, + new_mountpoints, (GCompareFunc) _g_daemon_mount_point_compare, + &added, &removed); + + for (l = removed; l != NULL; l = l->next) + { + GDaemonMountPoint *mountpoint = l->data; + + drive = g_daemon_volume_monitor_lookup_drive_for_mountpoint (monitor, mountpoint->mount_path); + if (drive) + { + g_daemon_drive_disconnected (drive); + monitor->drives = g_list_remove (monitor->drives, drive); + g_signal_emit_by_name (monitor, "drive_disconnected", drive); + g_object_unref (drive); + } + } + + for (l = added; l != NULL; l = l->next) + { + GDaemonMountPoint *mountpoint = l->data; + + drive = g_daemon_drive_new (G_VOLUME_MONITOR (monitor), mountpoint); + if (drive) + { + monitor->drives = g_list_prepend (monitor->drives, drive); + g_signal_emit_by_name (monitor, "drive_connected", drive); + } + } + + g_list_free (added); + g_list_free (removed); + g_list_foreach (monitor->last_mountpoints, + (GFunc)_g_daemon_mount_point_free, NULL); + g_list_free (monitor->last_mountpoints); + monitor->last_mountpoints = new_mountpoints; + } +} + +static void +update_volumes (GDaemonVolumeMonitor *monitor) +{ + GList *new_mounts; + GList *removed, *added; + GList *l; + GDaemonVolume *volume; + + if (_g_get_daemon_mounts (&new_mounts)) + { + new_mounts = g_list_sort (new_mounts, (GCompareFunc) _g_daemon_mount_compare); + + diff_sorted_lists (monitor->last_mounts, + new_mounts, (GCompareFunc) _g_daemon_mount_compare, + &added, &removed); + + for (l = removed; l != NULL; l = l->next) + { + GDaemonMount *mount = l->data; + + volume = find_volume_by_mountpoint (monitor, mount->mount_path); + if (volume) + { + g_daemon_volume_unmounted (volume); + monitor->volumes = g_list_remove (monitor->volumes, volume); + g_signal_emit_by_name (monitor, "volume_unmounted", volume); + g_object_unref (volume); + } + } + + for (l = added; l != NULL; l = l->next) + { + GDaemonMount *mount = l->data; + + volume = g_daemon_volume_new (G_VOLUME_MONITOR (monitor), mount); + if (volume) + { + monitor->volumes = g_list_prepend (monitor->volumes, volume); + g_signal_emit_by_name (monitor, "volume_mounted", volume); + } + } + + g_list_free (added); + g_list_free (removed); + g_list_foreach (monitor->last_mounts, + (GFunc)_g_daemon_mount_free, NULL); + g_list_free (monitor->last_mounts); + monitor->last_mounts = new_mounts; + } +} diff --git a/client/gdaemonvolumemonitor.h b/client/gdaemonvolumemonitor.h new file mode 100644 index 00000000..3f867984 --- /dev/null +++ b/client/gdaemonvolumemonitor.h @@ -0,0 +1,33 @@ +#ifndef __G_DAEMON_VOLUME_MONITOR_H__ +#define __G_DAEMON_VOLUME_MONITOR_H__ + +#include +#include + +G_BEGIN_DECLS + +#define G_TYPE_DAEMON_VOLUME_MONITOR (g_daemon_volume_monitor_get_type ()) +#define G_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitor)) +#define G_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitorClass)) +#define G_IS_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_VOLUME_MONITOR)) +#define G_IS_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_VOLUME_MONITOR)) + +typedef struct _GDaemonVolumeMonitor GDaemonVolumeMonitor; +typedef struct _GDaemonVolumeMonitorClass GDaemonVolumeMonitorClass; + +/* Forward definitions */ +typedef struct _GDaemonVolume GDaemonVolume; +typedef struct _GDaemonDrive GDaemonDrive; + +struct _GDaemonVolumeMonitorClass { + GVolumeMonitorClass parent_class; + +}; + +GType g_daemon_volume_monitor_get_type (void) G_GNUC_CONST; + +GVolumeMonitor *g_daemon_volume_monitor_new (void); + +G_END_DECLS + +#endif /* __G_DAEMON_VOLUME_MONITOR_H__ */ -- cgit v1.2.1