diff options
author | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 12:15:41 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 12:15:41 +0000 |
commit | 3420ce904de916f569ea39529b6c1d78a18539d2 (patch) | |
tree | bfd44749076362d4fc5d2a9347c9ac3294a802bb /client/gdaemonfileenumerator.c | |
parent | 57ad0f59a72910370b759d844056c44fac0b6a86 (diff) | |
download | gvfs-3420ce904de916f569ea39529b6c1d78a18539d2.tar.gz |
G*Daemon -> GDaemon*
Original git commit by Alexander Larsson <alex@greebo.(none)> at 1173787131 +0100
svn path=/trunk/; revision=388
Diffstat (limited to 'client/gdaemonfileenumerator.c')
-rw-r--r-- | client/gdaemonfileenumerator.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c new file mode 100644 index 00000000..add1b0e2 --- /dev/null +++ b/client/gdaemonfileenumerator.c @@ -0,0 +1,216 @@ +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gdaemonfileenumerator.h> +#include <gio/gfileinfo.h> +#include <gvfsdaemondbus.h> +#include <gvfsdaemonprotocol.h> + +#define OBJ_PATH_PREFIX "/org/gtk/vfs/client/enumerator/" + +/* atomic */ +volatile gint path_counter = 1; + +G_LOCK_DEFINE_STATIC(infos); + +struct _GDaemonFileEnumerator +{ + GFileEnumerator parent; + + gint id; + DBusConnection *sync_connection; + + /* protected by infos lock */ + GList *infos; + gboolean done; + +}; + +G_DEFINE_TYPE (GDaemonFileEnumerator, g_daemon_file_enumerator, G_TYPE_FILE_ENUMERATOR); + +static GFileInfo * g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, + GCancellable *cancellable, + GError **error); +static gboolean g_daemon_file_enumerator_stop (GFileEnumerator *enumerator, + GCancellable *cancellable, + GError **error); +static DBusHandlerResult g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data); + +static void +g_daemon_file_enumerator_finalize (GObject *object) +{ + GDaemonFileEnumerator *daemon; + char *path; + + daemon = G_DAEMON_FILE_ENUMERATOR (object); + + path = g_daemon_file_enumerator_get_object_path (daemon); + _g_dbus_unregister_vfs_filter (path); + g_free (path); + + g_list_foreach (daemon->infos, (GFunc)g_object_unref, NULL); + g_list_free (daemon->infos); + + if (daemon->sync_connection) + dbus_connection_unref (daemon->sync_connection); + + if (G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) + (*G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (object); +} + + +static void +g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass); + + gobject_class->finalize = g_daemon_file_enumerator_finalize; + + enumerator_class->next_file = g_daemon_file_enumerator_next_file; + enumerator_class->stop = g_daemon_file_enumerator_stop; +} + +static void +g_daemon_file_enumerator_init (GDaemonFileEnumerator *daemon) +{ + char *path; + + daemon->id = g_atomic_int_exchange_and_add (&path_counter, 1); + + path = g_daemon_file_enumerator_get_object_path (daemon); + _g_dbus_register_vfs_filter (path, g_daemon_file_enumerator_dbus_filter, + G_OBJECT (daemon)); + g_free (path); +} + +GDaemonFileEnumerator * +g_daemon_file_enumerator_new (void) +{ + GDaemonFileEnumerator *daemon; + + daemon = g_object_new (G_TYPE_DAEMON_FILE_ENUMERATOR, NULL); + + return daemon; +} + +static DBusHandlerResult +g_daemon_file_enumerator_dbus_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + GDaemonFileEnumerator *enumerator = user_data; + const char *member; + DBusMessageIter iter, array_iter; + GList *infos; + GFileInfo *info; + + member = dbus_message_get_member (message); + + if (strcmp (member, G_VFS_DBUS_ENUMERATOR_DONE) == 0) + { + G_LOCK (infos); + enumerator->done = TRUE; + G_UNLOCK (infos); + } + else if (strcmp (member, G_VFS_DBUS_ENUMERATOR_GOT_INFO) == 0) + { + infos = NULL; + + dbus_message_iter_init (message, &iter); + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY && + dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_STRUCT) + { + dbus_message_iter_recurse (&iter, &array_iter); + + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) + { + info = _g_dbus_get_file_info (&array_iter, NULL); + if (info) + g_assert (G_IS_FILE_INFO (info)); + + if (info) + infos = g_list_prepend (infos, info); + + dbus_message_iter_next (&iter); + } + } + + infos = g_list_reverse (infos); + + G_LOCK (infos); + enumerator->infos = g_list_concat (enumerator->infos, infos); + G_UNLOCK (infos); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +char * +g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator) +{ + return g_strdup_printf (OBJ_PATH_PREFIX"%d", enumerator->id); +} + +void +g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator, + DBusConnection *connection) +{ + enumerator->sync_connection = dbus_connection_ref (connection); +} + +static GFileInfo * +g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, + GCancellable *cancellable, + GError **error) +{ + GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); + GFileInfo *info; + gboolean done; + + info = NULL; + done = FALSE; + while (1) + { + G_LOCK (infos); + if (daemon->infos) + { + done = TRUE; + info = daemon->infos->data; + if (info) + g_assert (G_IS_FILE_INFO (info)); + daemon->infos = g_list_delete_link (daemon->infos, daemon->infos); + } + else if (daemon->done) + done = TRUE; + G_UNLOCK (infos); + + if (info) + g_assert (G_IS_FILE_INFO (info)); + + if (done) + break; + + if (!dbus_connection_read_write_dispatch (daemon->sync_connection, -1)) + break; + } + + return info; +} + +static gboolean +g_daemon_file_enumerator_stop (GFileEnumerator *enumerator, + GCancellable *cancellable, + GError **error) +{ + /*GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); */ + + return TRUE; +} + + |