/* * Syncdaemon API * * Authors: Rodrigo Moya * * Copyright 2010 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * */ #include "config.h" #include "syncdaemon-folders-interface.h" #include "utils.h" G_DEFINE_TYPE(SyncdaemonFoldersInterface, syncdaemon_folders_interface, SYNCDAEMON_TYPE_INTERFACE) struct _SyncdaemonFoldersInterfacePrivate { GObject *proxy; GHashTable *folders; }; static void syncdaemon_folders_interface_finalize (GObject *object) { SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (object); if (interface->priv != NULL) { if (interface->priv->folders != NULL) g_hash_table_destroy (interface->priv->folders); g_free (interface->priv); } G_OBJECT_CLASS (syncdaemon_folders_interface_parent_class)->finalize (object); } static void syncdaemon_folders_interface_class_init (SyncdaemonFoldersInterfaceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = syncdaemon_folders_interface_finalize; } static void folder_created_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); /* Update our cache of folders */ if (interface->priv->folders != NULL) { g_hash_table_insert (interface->priv->folders, g_strdup (syncdaemon_folder_info_get_path (folder_info)), folder_info); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_created", TRUE, folder_info); } else { if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_created", TRUE, folder_info); g_object_unref (G_OBJECT (folder_info)); } } static void folder_create_error_cb (DBusGProxy *proxy, GHashTable *hash, gchar *error, gpointer user_data) { SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); /* Notify listeners */ g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) { SyncdaemonFolderInfo *folder_info; folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_signal_emit_by_name (daemon, "folder_created", FALSE, folder_info); g_object_unref (G_OBJECT (folder_info)); } } static void folder_deleted_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); /* Notify listeners */ g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_deleted", TRUE, folder_info); /* Update our cache of folders */ if (interface->priv->folders != NULL) g_hash_table_remove (interface->priv->folders, syncdaemon_folder_info_get_path (folder_info)); g_object_unref (G_OBJECT (folder_info)); } static void folder_delete_error_cb (DBusGProxy *proxy, GHashTable *hash, gchar *error, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); /* Notify listeners */ g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_deleted", FALSE, folder_info); g_object_unref (G_OBJECT (folder_info)); } static void folder_subscribed_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_subscribed", TRUE, folder_info); if (interface->priv->folders != NULL) { g_hash_table_insert (interface->priv->folders, g_strdup (syncdaemon_folder_info_get_path (folder_info)), folder_info); } else g_object_unref (G_OBJECT (folder_info)); } static void folder_subscribe_error_cb (DBusGProxy *proxy, GHashTable *hash, gchar *error, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_subscribed", FALSE, folder_info); g_object_unref (G_OBJECT (folder_info)); } static void folder_unsubscribed_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_unsubscribed", TRUE, folder_info); if (interface->priv->folders != NULL) { g_hash_table_insert (interface->priv->folders, g_strdup (syncdaemon_folder_info_get_path (folder_info)), folder_info); } else g_object_unref (G_OBJECT (folder_info)); } static void folder_unsubscribe_error_cb (DBusGProxy *proxy, GHashTable *hash, gchar *error, gpointer user_data) { SyncdaemonFolderInfo *folder_info; SyncdaemonDaemon *daemon = NULL; SyncdaemonFoldersInterface *interface = SYNCDAEMON_FOLDERS_INTERFACE (user_data); folder_info = syncdaemon_folder_info_new_from_hash_table (hash); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "folder_unsubscribed", FALSE, folder_info); g_object_unref (G_OBJECT (folder_info)); } static void syncdaemon_folders_interface_init (SyncdaemonFoldersInterface *interface) { interface->priv = g_new0 (SyncdaemonFoldersInterfacePrivate, 1); /* Setup DBus proxy */ interface->priv->proxy = syncdaemon_interface_setup_proxy (SYNCDAEMON_INTERFACE (interface), "com.ubuntuone.SyncDaemon", "/folders", "com.ubuntuone.SyncDaemon.Folders"); if (interface->priv->proxy != NULL) { /* Connect to DBus proxy signals */ dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderCreated", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderCreated", G_CALLBACK (folder_created_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderDeleted", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderDeleted", G_CALLBACK (folder_deleted_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderSubscribed", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderSubscribed", G_CALLBACK (folder_subscribed_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderUnSubscribed", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderUnSubscribed", G_CALLBACK (folder_unsubscribed_cb), interface, NULL); /* Error signals */ dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderCreateError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderCreateError", G_CALLBACK (folder_create_error_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderDeleteError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderDeleteError", G_CALLBACK (folder_delete_error_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderSubscribeError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderSubscribeError", G_CALLBACK (folder_subscribe_error_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderUnSubscribeError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "FolderUnSubscribeError", G_CALLBACK (folder_unsubscribe_error_cb), interface, NULL); } } /** * syncdaemon_folders_interface_new: */ SyncdaemonFoldersInterface * syncdaemon_folders_interface_new (SyncdaemonDaemon *daemon) { g_return_val_if_fail (SYNCDAEMON_IS_DAEMON (daemon), NULL); return g_object_new (SYNCDAEMON_TYPE_FOLDERS_INTERFACE, "daemon", daemon, NULL); } /** * syncdaemon_folders_interface_create: */ void syncdaemon_folders_interface_create (SyncdaemonFoldersInterface *interface, const gchar *path) { g_return_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface)); g_return_if_fail (path != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "create", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, path, G_TYPE_INVALID); } /** * syncdaemon_folders_interface_delete: */ void syncdaemon_folders_interface_delete (SyncdaemonFoldersInterface *interface, const gchar *folder_id) { g_return_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface)); g_return_if_fail (folder_id != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "delete", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, folder_id, G_TYPE_INVALID); } /** * syncdaemon_folders_interface_get_folders: * * Return value: A GSList of #SyncdaemonFolderInfo containing all the folders being * synchronized by the user. When no longer needed, the list should be freed * by calling g_slist_free. */ GSList * syncdaemon_folders_interface_get_folders (SyncdaemonFoldersInterface *interface) { GSList *returned_folders = NULL; GError *error = NULL; g_return_val_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface), NULL); if (interface->priv->folders != NULL) { GHashTableIter iter; gchar *path; SyncdaemonFolderInfo *folder_info; /* If we already got the folders list, no need for an extra DBus call */ g_hash_table_iter_init (&iter, interface->priv->folders); while (g_hash_table_iter_next (&iter, (gpointer *) &path, (gpointer *) &folder_info)) returned_folders = g_slist_append (returned_folders, folder_info); } else { GSList *list; if (dbus_g_proxy_call (DBUS_G_PROXY (interface->priv->proxy), "get_folders", &error, G_TYPE_INVALID, dbus_g_type_get_collection ("GSList", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)), &list, G_TYPE_INVALID)) { GSList *l; /* Add the folders to our live-updating list */ interface->priv->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); for (l = list; l != NULL; l = l->next) { SyncdaemonFolderInfo *folder_info; folder_info = syncdaemon_folder_info_new_from_hash_table (l->data); g_hash_table_insert (interface->priv->folders, g_strdup (g_hash_table_lookup (l->data, "path")), folder_info); returned_folders = g_slist_append (returned_folders, folder_info); } /* Free memory */ g_slist_foreach (list, (GFunc) g_hash_table_destroy, NULL); g_slist_free (list); } else { g_warning ("Error calling get_folders: %s", error->message); g_error_free (error); } } return returned_folders; } /** * syncdaemon_folders_interface_get_info: * * Return value: A #SyncdaemonFolderInfo object containing all the information * for the node. When no longer needed, it should be freed by calling * g_object_unref. */ SyncdaemonFolderInfo * syncdaemon_folders_interface_get_info (SyncdaemonFoldersInterface *interface, const gchar *path) { SyncdaemonFolderInfo *folder_info = NULL; GError *error = NULL; g_return_val_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface), NULL); g_return_val_if_fail (path != NULL, NULL); if (interface->priv->folders != NULL) { folder_info = g_hash_table_lookup (interface->priv->folders, path); if (folder_info != NULL) folder_info = g_object_ref (G_OBJECT (folder_info)); } if (!folder_info) { GHashTable *hash; if (dbus_g_proxy_call (DBUS_G_PROXY (interface->priv->proxy), "get_info", &error, G_TYPE_STRING, path, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), &hash, G_TYPE_INVALID)) { folder_info = syncdaemon_folder_info_new_from_hash_table (hash); } else { g_warning ("Error calling get_info: %s", error->message); g_error_free (error); } } return folder_info; } /** * syncdaemon_folders_interface_refresh_volumes: */ void syncdaemon_folders_interface_refresh_volumes (SyncdaemonFoldersInterface *interface) { g_return_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface)); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "refresh_volumes", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_INVALID); } /** * syncdaemon_folders_interface_subscribe: */ void syncdaemon_folders_interface_subscribe (SyncdaemonFoldersInterface *interface, const gchar *folder_id) { g_return_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface)); g_return_if_fail (folder_id != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "subscribe", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, folder_id, G_TYPE_INVALID); } /** * syncdaemon_folders_interface_unsubscribe: */ void syncdaemon_folders_interface_unsubscribe (SyncdaemonFoldersInterface *interface, const gchar *folder_id) { g_return_if_fail (SYNCDAEMON_IS_FOLDERS_INTERFACE (interface)); g_return_if_fail (folder_id != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "unsubscribe", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, folder_id, G_TYPE_INVALID); }