diff options
author | Alberto Mardegan <mardy@users.sourceforge.net> | 2008-04-08 10:39:40 +0000 |
---|---|---|
committer | Alberto Mardegan <mardy@users.sourceforge.net> | 2008-04-08 10:39:40 +0000 |
commit | 14533942c63e05d809ee14e6f25e047a15695d14 (patch) | |
tree | 7cb5360cb281add8875d9cda63d9c4958ac0900a | |
parent | b1c0b7df486c9f92a0f37dfad8d6d40582b2234e (diff) | |
download | telepathy-mission-control-14533942c63e05d809ee14e6f25e047a15695d14.tar.gz |
Implement libmissioncontrol's McAccount and McAccountMonitor using the new DBus API (called in blocking mode).
git-svn-id: https://mission-control.svn.sourceforge.net/svnroot/mission-control/trunk@322 d91c8aed-3f2b-0410-a83d-924a1c20a0ba
28 files changed, 2562 insertions, 1183 deletions
diff --git a/libmissioncontrol/Makefile.am b/libmissioncontrol/Makefile.am index b83a18fc..a7500fee 100644 --- a/libmissioncontrol/Makefile.am +++ b/libmissioncontrol/Makefile.am @@ -34,9 +34,11 @@ libmissioncontrol_client_la_SOURCES = \ mc-protocol-priv.h \ mc-profile.c \ mc-account.c \ + mc-account-proxy.c \ mc-account-priv.h \ mc-account-monitor.c \ mc-account-monitor-priv.h \ + mc-account-manager-proxy.c \ mc-signals-marshal.c \ mc-enum-types.c \ mission-control-signals-marshal.c \ @@ -48,7 +50,9 @@ libmissioncontrol_client_include_HEADERS = \ dbus-api.h \ mc.h \ mc-account.h \ + mc-account-proxy.h \ mc-account-monitor.h \ + mc-account-manager-proxy.h \ mc-enum-types.h \ mc-profile.h \ mc-protocol.h \ @@ -60,6 +64,8 @@ libmissioncontrol_client_include_HEADERS = \ genincludedir = $(libmissioncontrol_client_includedir)/_gen nodist_geninclude_HEADERS = \ + _gen/cli-Account.h \ + _gen/cli-Account_Manager.h \ _gen/cli-nmc4.h \ _gen/enums.h \ _gen/interfaces.h \ @@ -67,6 +73,8 @@ nodist_geninclude_HEADERS = \ _gen/svc-nmc4.h nodist_libmissioncontrol_client_la_SOURCES = \ + _gen/cli-Account-body.h \ + _gen/cli-Account_Manager-body.h \ _gen/cli-nmc4-body.h \ _gen/gtypes-body.h \ _gen/interfaces-body.h \ @@ -196,8 +204,8 @@ _gen/%.xml: $(top_srcdir)/xml/%.xml $(wildcard $(top_srcdir)/xml/*.xml) $< > $@ _gen/cli-%-body.h _gen/cli-%.h: _gen/%.xml \ - $(tools_dir)/glib-client-gen.py Makefile.am - $(PYTHON) $(tools_dir)/glib-client-gen.py \ + $(tools_dir)/glib-blocking-client-gen.py Makefile.am + $(PYTHON) $(tools_dir)/glib-blocking-client-gen.py \ --group=`echo $* | tr x- x_` \ --iface-quark-prefix=MC_IFACE_QUARK \ $< Mc_Cli _gen/cli-$* diff --git a/libmissioncontrol/mc-account-manager-proxy.c b/libmissioncontrol/mc-account-manager-proxy.c new file mode 100644 index 00000000..bdb4750b --- /dev/null +++ b/libmissioncontrol/mc-account-manager-proxy.c @@ -0,0 +1,60 @@ +/* + * mc-account_manager-manager-proxy.c - Subclass of TpProxy + * + * Copyright (C) 2008 Nokia Corporation + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mc-account-manager-proxy.h" +#include <telepathy-glib/proxy-subclass.h> +#include <telepathy-glib/errors.h> +#include "_gen/interfaces.h" +#include "_gen/cli-Account_Manager-body.h" +#include "_gen/signals-marshal.h" +#include "_gen/register-dbus-glib-marshallers-body.h" + +struct _McAccountManagerProxyClass { + TpProxyClass parent_class; +}; + +struct _McAccountManagerProxy { + TpProxy parent; +}; + +G_DEFINE_TYPE (McAccountManagerProxy, mc_account_manager_proxy, TP_TYPE_PROXY); + +static void +mc_account_manager_proxy_init (McAccountManagerProxy *self) +{ +} + +static void +mc_account_manager_proxy_class_init (McAccountManagerProxyClass *klass) +{ + GType type = MC_TYPE_ACCOUNT_MANAGER_PROXY; + TpProxyClass *proxy_class = (TpProxyClass *) klass; + + /* the API is stateless, so we can keep the same proxy across restarts */ + proxy_class->must_have_unique_name = FALSE; + + proxy_class->interface = MC_IFACE_QUARK_ACCOUNT_MANAGER; + _mc_ext_register_dbus_glib_marshallers (); + tp_proxy_or_subclass_hook_on_interface_add (type, mc_cli_Account_Manager_add_signals); + + tp_proxy_subclass_add_error_mapping (type, TP_ERROR_PREFIX, TP_ERRORS, + TP_TYPE_ERROR); +} + diff --git a/libmissioncontrol/mc-account-manager-proxy.h b/libmissioncontrol/mc-account-manager-proxy.h new file mode 100644 index 00000000..1f79ba38 --- /dev/null +++ b/libmissioncontrol/mc-account-manager-proxy.h @@ -0,0 +1,56 @@ +/* + * mc-account-manager-proxy.h - Subclass of TpProxy + * + * Copyright (C) 2008 Nokia Corporation + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBMISSIONCONTROL_ACCOUNT_MANAGER_PROXY_H__ +#define __LIBMISSIONCONTROL_ACCOUNT_MANAGER_PROXY_H__ + +#include <telepathy-glib/proxy.h> + +G_BEGIN_DECLS + +typedef struct _McAccountManagerProxy McAccountManagerProxy; +typedef struct _McAccountManagerProxyClass McAccountManagerProxyClass; +typedef struct _McAccountManagerProxyPrivate McAccountManagerProxyPrivate; + +GType mc_account_manager_proxy_get_type (void); + +#define MC_TYPE_ACCOUNT_MANAGER_PROXY \ + (mc_account_manager_proxy_get_type ()) +#define MC_ACCOUNT_MANAGER_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MC_TYPE_ACCOUNT_MANAGER_PROXY, \ + McAccountManagerProxy)) +#define MC_ACCOUNT_MANAGER_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MC_TYPE_ACCOUNT_MANAGER_PROXY, \ + McAccountManagerProxyClass)) +#define MC_IS_ACCOUNT_MANAGER_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MC_TYPE_ACCOUNT_MANAGER_PROXY)) +#define MC_IS_ACCOUNT_MANAGER_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MC_TYPE_ACCOUNT_MANAGER_PROXY)) +#define MC_ACCOUNT_MANAGER_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MC_TYPE_ACCOUNT_MANAGER_PROXY, \ + McAccountManagerProxyClass)) + + +G_END_DECLS + +/* auto-generated stubs */ +#include <libmissioncontrol/_gen/cli-Account_Manager.h> + +#endif diff --git a/libmissioncontrol/mc-account-monitor-priv.h b/libmissioncontrol/mc-account-monitor-priv.h index c55c2c3f..3e3c42d9 100644 --- a/libmissioncontrol/mc-account-monitor-priv.h +++ b/libmissioncontrol/mc-account-monitor-priv.h @@ -26,6 +26,11 @@ McAccount * _mc_account_monitor_lookup (McAccountMonitor *monitor, const gchar *unique_name); GList * _mc_account_monitor_list (McAccountMonitor *monitor); +McAccount *_mc_account_monitor_create_account (McAccountMonitor *monitor, + const gchar *manager, + const gchar *protocol, + const gchar *display_name, + GHashTable *parameters); #endif /* __MC_ACCOUNT_MONITOR_PRIV_H__ */ diff --git a/libmissioncontrol/mc-account-monitor.c b/libmissioncontrol/mc-account-monitor.c index 9e4ad040..db3a154f 100644 --- a/libmissioncontrol/mc-account-monitor.c +++ b/libmissioncontrol/mc-account-monitor.c @@ -24,12 +24,19 @@ #include <string.h> #include <strings.h> +#include <telepathy-glib/proxy.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/svc-generic.h> +#include "_gen/interfaces.h" #include <gconf/gconf-client.h> #include "mc-account.h" #include "mc-account-priv.h" #include "mc-account-monitor.h" +#include "mc-account-monitor-priv.h" +#include "mc-account-manager-proxy.h" #include "mc-signals-marshal.h" +#include "mc.h" G_DEFINE_TYPE (McAccountMonitor, mc_account_monitor, G_TYPE_OBJECT); @@ -51,8 +58,7 @@ static guint signals[NUM_SIGNALS]; typedef struct { - GConfClient *gconf_client; - guint gconf_connection; + TpProxy *proxy; GHashTable *accounts; } McAccountMonitorPrivate; @@ -62,11 +68,6 @@ mc_account_monitor_finalize (GObject *object) McAccountMonitor *self = MC_ACCOUNT_MONITOR (object); McAccountMonitorPrivate *priv = MC_ACCOUNT_MONITOR_PRIV (self); - gconf_client_notify_remove (priv->gconf_client, priv->gconf_connection); - gconf_client_remove_dir ( - priv->gconf_client, MC_ACCOUNTS_GCONF_BASE, NULL); - g_object_unref (priv->gconf_client); - g_hash_table_destroy (priv->accounts); } @@ -169,7 +170,7 @@ mc_account_monitor_class_init (McAccountMonitorClass *klass) * retrieve the account object). * @param: The name of the parameter which changed. * - * Emitted when an account parameter is changed. + * NOTE: this signal is no longer emitted in this version. */ signals[PARAM_CHANGED] = g_signal_new ( "param-changed", @@ -182,195 +183,138 @@ mc_account_monitor_class_init (McAccountMonitorClass *klass) G_TYPE_STRING, G_TYPE_STRING); } -static gchar * -_account_name_from_key (const gchar *key) +static void +on_account_removed (TpProxy *proxy, const gchar *object_path, + gpointer user_data, GObject *weak_object) { - guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE); - const gchar *base, *slash; - - g_assert (key == strstr (key, MC_ACCOUNTS_GCONF_BASE)); - if (strlen (key) <= base_len + 1) return NULL; - - base = key + base_len + 1; - slash = index (base, '/'); + McAccountMonitor *monitor = MC_ACCOUNT_MONITOR (weak_object); + McAccountMonitorPrivate *priv = user_data; + const gchar *name; + McAccount *account; - if (slash == NULL) - return g_strdup (base); - else - return g_strndup (base, slash - base); -} - -static const gchar * -key_name (const gchar *path_key) -{ - const gchar *key = 0; + name = MC_ACCOUNT_UNIQUE_NAME_FROM_PATH (object_path); + g_debug ("%s called for account %s", G_STRFUNC, name); - while (*path_key != 0) + account = g_hash_table_lookup (priv->accounts, name); + g_debug ("Account is %sknown", account ? "" : "not "); + if (account) { - if (*path_key == '/') key = path_key + 1; - path_key++; + if (mc_account_is_enabled (account)) + { + _mc_account_set_enabled_priv (account, FALSE); + g_signal_emit (monitor, signals[SIGNAL_DISABLED], 0, name); + } + g_signal_emit (monitor, signals[SIGNAL_DELETED], 0, name); + g_hash_table_remove (priv->accounts, name); } - return key; } static void -_gconf_notify_cb (GConfClient *client, guint conn_id, GConfEntry *entry, - gpointer user_data) +on_account_validity_changed (TpProxy *proxy, const gchar *object_path, + gboolean valid, gpointer user_data, + GObject *weak_object) { - McAccountMonitor *monitor = MC_ACCOUNT_MONITOR (user_data); - McAccountMonitorPrivate *priv = MC_ACCOUNT_MONITOR_PRIV (monitor); - gchar *name = NULL; - McAccount *account; - const gchar *key; - - key = key_name (entry->key); - name = _account_name_from_key (entry->key); - if (!name) return; - account = g_hash_table_lookup (priv->accounts, name); - - /* Was account complete before? */ - if (account == NULL) - { - account = _mc_account_new (name); - - /* Account was not complete before and it just become complete */ - if (mc_account_is_complete (account)) - { - g_hash_table_insert (priv->accounts, g_strdup (name), account); - g_signal_emit (monitor, signals[SIGNAL_CREATED], 0, name); - - /* check if the account is enabled and, in case, emit the respective - * signal */ - if (mc_account_is_enabled (account)) - { - g_signal_emit (monitor, signals[SIGNAL_ENABLED], 0, name); - } - } - else - { - g_object_unref (account); - /* We don't do anything for incomplete accounts */ - } - } - else if (strcmp (key, MC_ACCOUNTS_GCONF_KEY_DELETED) == 0) - { - /* if account is deleted, remove it */ - if (entry->value != NULL && entry->value->type == GCONF_VALUE_BOOL && - gconf_value_get_bool (entry->value)) - { - if (mc_account_is_enabled (account)) - { - _mc_account_set_enabled_priv (account, FALSE); - g_signal_emit (monitor, signals[SIGNAL_DISABLED], 0, name); - } - g_signal_emit (monitor, signals[SIGNAL_DELETED], 0, name); - g_hash_table_remove (priv->accounts, name); - } - } - else if (strcmp (key, MC_ACCOUNTS_GCONF_KEY_ENABLED) == 0) + McAccountMonitor *monitor = MC_ACCOUNT_MONITOR (weak_object); + McAccountMonitorPrivate *priv = user_data; + const gchar *name; + McAccount *account; + + name = MC_ACCOUNT_UNIQUE_NAME_FROM_PATH (object_path); + g_debug ("%s called for account %s (%d)", G_STRFUNC, name, valid); + + account = g_hash_table_lookup (priv->accounts, name); + g_debug ("Account is %sknown", account ? "" : "not "); + if (account) { - if (entry->value != NULL && entry->value->type == GCONF_VALUE_BOOL) - { - if (gconf_value_get_bool (entry->value)) - { - _mc_account_set_enabled_priv (account, TRUE); - g_signal_emit (monitor, signals[SIGNAL_ENABLED], 0, name); - } - else - { - _mc_account_set_enabled_priv (account, FALSE); - g_signal_emit (monitor, signals[SIGNAL_DISABLED], 0, name); - } - } + /* the old implementation didn't report signals for account + * completeness, and for account deletion we have another signal; so, + * we have nothing to do here */ } - else if (strcmp (key, MC_ACCOUNTS_GCONF_KEY_AVATAR_TOKEN) != 0) + else if (valid) { - const gchar *value; - - /* report the changed value to the McAccount, if it's a cached setting */ - if (entry->value != NULL && entry->value->type == GCONF_VALUE_STRING) - value = gconf_value_get_string (entry->value); - else - value = NULL; - - if (strcmp (key, MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME) == 0) - _mc_account_set_normalized_name_priv (account, value); - else if (strcmp (key, MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME) == 0) - _mc_account_set_display_name_priv (account, value); - - /* Emit the rest as value changed signal */ - g_signal_emit (monitor, signals[SIGNAL_CHANGED], 0, name); - - if (strncmp (key, "param-", 6) == 0) - g_signal_emit (monitor, signals[PARAM_CHANGED], 0, - name, key + 6); + account = _mc_account_new (priv->proxy->dbus_daemon, object_path); + g_hash_table_insert (priv->accounts, g_strdup (name), account); + g_signal_emit (monitor, signals[SIGNAL_CREATED], 0, name); + + /* check if the account is enabled and, in case, emit the respective + * signal */ + if (mc_account_is_enabled (account)) + { + g_signal_emit (monitor, signals[SIGNAL_ENABLED], 0, name); + } } - - /* If we are enabling/disabling account */ - g_free (name); } static void mc_account_monitor_init (McAccountMonitor *self) { - GError *error = NULL; - GConfClient *client = gconf_client_get_default (); - GSList *i, *dirs; - McAccountMonitorPrivate *priv; - - self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, - MC_TYPE_ACCOUNT_MONITOR, McAccountMonitorPrivate); - priv = MC_ACCOUNT_MONITOR_PRIV (self); - priv->accounts = NULL; - priv->gconf_client = client; - dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error); - - if (NULL != error) + GError *error = NULL; + McAccountMonitorPrivate *priv; + TpDBusDaemon *dbus_daemon; + DBusGConnection *connection; + GValue *val_accounts; + const gchar **accounts, **name; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + MC_TYPE_ACCOUNT_MONITOR, McAccountMonitorPrivate); + priv = MC_ACCOUNT_MONITOR_PRIV (self); + connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error); + if (error) { - g_print ("Error: %s\n", error->message); - g_assert_not_reached (); + g_printerr ("Failed to open connection to bus: %s", error->message); + g_error_free (error); + return; } - - priv->accounts = g_hash_table_new_full ( - g_str_hash, g_str_equal, (GDestroyNotify) g_free, g_object_unref); - - for (i = dirs; NULL != i; i = i->next) + dbus_daemon = tp_dbus_daemon_new (connection); + priv->proxy = g_object_new (MC_TYPE_ACCOUNT_MANAGER_PROXY, + "dbus-daemon", dbus_daemon, + "bus-name", MC_ACCOUNT_MANAGER_DBUS_SERVICE, + "object-path", MC_ACCOUNT_MANAGER_DBUS_OBJECT, + NULL); + g_assert (priv->proxy != NULL); + priv->accounts = NULL; + + if (NULL != error) { - gchar *name = _account_name_from_key (i->data); - McAccount *account = _mc_account_new (name); - - /* Only pick up accounts which are not yet deleted. */ - if (mc_account_is_complete (account)) - { - g_hash_table_insert (priv->accounts, g_strdup (name), account); - } - else - { - g_object_unref (account); - } - g_free (i->data); - g_free (name); + g_print ("Error: %s\n", error->message); + g_assert_not_reached (); } - g_slist_free (dirs); - - gconf_client_add_dir ( - client, MC_ACCOUNTS_GCONF_BASE, GCONF_CLIENT_PRELOAD_NONE, &error); + priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + g_object_unref); - if (NULL != error) + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT_MANAGER, "ValidAccounts", + &val_accounts, &error); + if (error) { - g_print ("Error: %s\n", error->message); - g_assert_not_reached (); + g_warning ("Error getting accounts: %s", error->message); + g_error_free (error); + error = NULL; } + accounts = g_value_get_boxed (val_accounts); - priv->gconf_connection = gconf_client_notify_add ( - client, MC_ACCOUNTS_GCONF_BASE, _gconf_notify_cb, self, NULL, &error); - - if (NULL != error) + for (name = accounts; *name != NULL; name++) { - g_print ("Error: %s\n", error->message); - g_assert_not_reached (); + McAccount *account; + const gchar *unique_name; + + account = _mc_account_new (dbus_daemon, *name); + unique_name = MC_ACCOUNT_UNIQUE_NAME_FROM_PATH (*name); + g_hash_table_insert (priv->accounts, g_strdup (unique_name), account); } + g_value_unset (val_accounts); + g_free (val_accounts); + + mc_cli_account_manager_connect_to_account_removed (priv->proxy, + on_account_removed, + priv, NULL, + (GObject *)self, NULL); + mc_cli_account_manager_connect_to_account_validity_changed (priv->proxy, + on_account_validity_changed, + priv, NULL, + (GObject *)self, NULL); } McAccount * @@ -485,3 +429,28 @@ mc_account_monitor_get_supported_presences (McAccountMonitor *monitor) return data; } +McAccount * +_mc_account_monitor_create_account (McAccountMonitor *monitor, + const gchar *manager, + const gchar *protocol, + const gchar *display_name, + GHashTable *parameters) +{ + McAccountMonitorPrivate *priv = MC_ACCOUNT_MONITOR_PRIV (monitor); + gchar *object_path; + GError *error = NULL; + + mc_cli_account_manager_do_create_account (priv->proxy, -1, + manager, protocol, + display_name, parameters, + &object_path, &error); + if (error) + { + g_warning ("%s failed: %s", G_STRFUNC, error->message); + g_error_free (error); + return NULL; + } + + return _mc_account_new (priv->proxy->dbus_daemon, object_path); +} + diff --git a/libmissioncontrol/mc-account-priv.h b/libmissioncontrol/mc-account-priv.h index a5c2f4c6..6cc48509 100644 --- a/libmissioncontrol/mc-account-priv.h +++ b/libmissioncontrol/mc-account-priv.h @@ -24,24 +24,34 @@ #ifndef __MC_ACCOUNT_PRIV_H__ #define __MC_ACCOUNT_PRIV_H__ -#define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts" -#define MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME "display_name" -#define MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME "normalized_name" -#define MC_ACCOUNTS_GCONF_KEY_ENABLED "enabled" +#define MC_ACCOUNT_MANAGER_DBUS_SERVICE "org.freedesktop.Telepathy.AccountManager" +#define MC_ACCOUNT_MANAGER_DBUS_OBJECT "/org/freedesktop/Telepathy/AccountManager" +#define MC_ACCOUNT_DBUS_OBJECT_BASE "/org/freedesktop/Telepathy/Account/" + +#define MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME "DisplayName" +#define MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME "NormalizedName" +#define MC_ACCOUNTS_GCONF_KEY_VALID "Valid" +#define MC_ACCOUNTS_GCONF_KEY_ENABLED "Enabled" +#define MC_ACCOUNTS_GCONF_KEY_PARAMETERS "Parameters" #define MC_ACCOUNTS_GCONF_KEY_DELETED "deleted" -#define MC_ACCOUNTS_GCONF_KEY_PROFILE "profile" +#define MC_ACCOUNTS_GCONF_KEY_PROFILE "Profile" #define MC_ACCOUNTS_GCONF_KEY_PARAM_ACCOUNT "account" +#define MC_ACCOUNTS_GCONF_KEY_AVATAR "Avatar" +#define MC_ACCOUNTS_GCONF_KEY_AVATAR_FILE "AvatarFile" #define MC_ACCOUNTS_GCONF_KEY_AVATAR_TOKEN "avatar_token" #define MC_ACCOUNTS_GCONF_KEY_AVATAR_MIME "avatar_mime" #define MC_ACCOUNTS_GCONF_KEY_AVATAR_ID "avatar_id" #define MC_ACCOUNTS_GCONF_KEY_DATA_DIR "data_dir" -#define MC_ACCOUNTS_GCONF_KEY_ALIAS "alias" -#define MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS "secondary_vcard_fields" +#define MC_ACCOUNTS_GCONF_KEY_ALIAS "Nickname" +#define MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS "SecondaryVCardFields" -McAccount * _mc_account_new (const gchar *unique_name); +McAccount *_mc_account_new (TpDBusDaemon *dbus_daemon, + const gchar *object_path); void _mc_account_set_enabled_priv (McAccount *account, gboolean enabled); void _mc_account_set_normalized_name_priv (McAccount *account, const gchar *name); void _mc_account_set_display_name_priv (McAccount *account, const gchar *name); +#define MC_ACCOUNT_UNIQUE_NAME_FROM_PATH(object_path) \ + (object_path + (sizeof (MC_ACCOUNT_DBUS_OBJECT_BASE) - 1)) #endif /* __MC_ACCOUNT_PRIV_H__ */ diff --git a/libmissioncontrol/mc-account-proxy.c b/libmissioncontrol/mc-account-proxy.c new file mode 100644 index 00000000..54fa36bb --- /dev/null +++ b/libmissioncontrol/mc-account-proxy.c @@ -0,0 +1,57 @@ +/* + * mc-account-proxy.c - Subclass of TpProxy + * + * Copyright (C) 2008 Nokia Corporation + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mc-account-proxy.h" +#include <telepathy-glib/proxy-subclass.h> +#include <telepathy-glib/errors.h> +#include "_gen/interfaces.h" +#include "_gen/cli-Account-body.h" + +struct _McAccountProxyClass { + TpProxyClass parent_class; +}; + +struct _McAccountProxy { + TpProxy parent; +}; + +G_DEFINE_TYPE (McAccountProxy, mc_account_proxy, TP_TYPE_PROXY); + +static void +mc_account_proxy_init (McAccountProxy *self) +{ +} + +static void +mc_account_proxy_class_init (McAccountProxyClass *klass) +{ + GType type = MC_TYPE_ACCOUNT_PROXY; + TpProxyClass *proxy_class = (TpProxyClass *) klass; + + /* the API is stateless, so we can keep the same proxy across restarts */ + proxy_class->must_have_unique_name = FALSE; + + proxy_class->interface = MC_IFACE_QUARK_ACCOUNT; + tp_proxy_or_subclass_hook_on_interface_add (type, mc_cli_Account_add_signals); + + tp_proxy_subclass_add_error_mapping (type, TP_ERROR_PREFIX, TP_ERRORS, + TP_TYPE_ERROR); +} + diff --git a/libmissioncontrol/mc-account-proxy.h b/libmissioncontrol/mc-account-proxy.h new file mode 100644 index 00000000..faafa57c --- /dev/null +++ b/libmissioncontrol/mc-account-proxy.h @@ -0,0 +1,56 @@ +/* + * mc-account-proxy.h - Subclass of TpProxy + * + * Copyright (C) 2008 Nokia Corporation + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBMISSIONCONTROL_ACCOUNT_PROXY_H__ +#define __LIBMISSIONCONTROL_ACCOUNT_PROXY_H__ + +#include <telepathy-glib/proxy.h> + +G_BEGIN_DECLS + +typedef struct _McAccountProxy McAccountProxy; +typedef struct _McAccountProxyClass McAccountProxyClass; +typedef struct _McAccountProxyPrivate McAccountProxyPrivate; + +GType mc_account_proxy_get_type (void); + +#define MC_TYPE_ACCOUNT_PROXY \ + (mc_account_proxy_get_type ()) +#define MC_ACCOUNT_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MC_TYPE_ACCOUNT_PROXY, \ + McAccountProxy)) +#define MC_ACCOUNT_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MC_TYPE_ACCOUNT_PROXY, \ + McAccountProxyClass)) +#define MC_IS_ACCOUNT_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MC_TYPE_ACCOUNT_PROXY)) +#define MC_IS_ACCOUNT_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MC_TYPE_ACCOUNT_PROXY)) +#define MC_ACCOUNT_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MC_TYPE_ACCOUNT_PROXY, \ + McAccountProxyClass)) + + +G_END_DECLS + +/* auto-generated stubs */ +#include <libmissioncontrol/_gen/cli-Account.h> + +#endif diff --git a/libmissioncontrol/mc-account.c b/libmissioncontrol/mc-account.c index 8e4634d9..6fce736b 100644 --- a/libmissioncontrol/mc-account.c +++ b/libmissioncontrol/mc-account.c @@ -33,34 +33,53 @@ #include <glib/gstdio.h> #include "mc-account.h" +#include "mc-account-proxy.h" #include "mc-account-priv.h" #include "mc-account-monitor.h" #include "mc-account-monitor-priv.h" #include "mc-profile.h" +#include "mc.h" #include <config.h> #define MC_ACCOUNTS_MAX 1024 #define MC_AVATAR_FILENAME "avatar.bin" -#define MC_ACCOUNT_PRIV(account) ((McAccountPrivate *)account->priv) +#define MC_ACCOUNT_PRIV(account) ((McAccountPrivate *)MC_ACCOUNT (account)->priv) G_DEFINE_TYPE (McAccount, mc_account, G_TYPE_OBJECT); typedef struct { + TpProxy *proxy; + gchar *manager_name; + gchar *protocol_name; gchar *unique_name; gchar *profile_name; GSList *display_names; GSList *normalized_names; + gchar *alias; gboolean enabled; + gboolean valid; + gchar *last_name; + gchar *last_value; + gint avatar_id; } McAccountPrivate; -static gboolean mc_account_set_deleted (McAccount *account, gboolean deleted); -static gboolean mc_account_is_deleted (McAccount *account); -static gboolean _mc_account_gconf_get_boolean (McAccount *account, - const gchar *name, gboolean param, gboolean *value); -static gboolean _mc_account_gconf_get_string (McAccount *account, - const gchar *name, gboolean param, gchar **value); +static GSList *set_first_element (GSList *list, const gchar *value); + +static void +mc_account_dispose (GObject *object) +{ + McAccount *self = MC_ACCOUNT(object); + McAccountPrivate *priv = MC_ACCOUNT_PRIV (self); + + if (priv->proxy) + { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + G_OBJECT_CLASS (mc_account_parent_class)->dispose (object); +} static void mc_account_finalize (GObject *object) @@ -68,12 +87,17 @@ mc_account_finalize (GObject *object) McAccount *self = MC_ACCOUNT(object); McAccountPrivate *priv = MC_ACCOUNT_PRIV (self); + g_free (priv->manager_name); + g_free (priv->protocol_name); g_free (priv->unique_name); g_free (priv->profile_name); g_slist_foreach (priv->display_names, (GFunc)g_free, NULL); g_slist_free (priv->display_names); g_slist_foreach (priv->normalized_names, (GFunc)g_free, NULL); g_slist_free (priv->normalized_names); + g_free (priv->alias); + g_free (priv->last_name); + g_free (priv->last_value); } static void @@ -88,32 +112,157 @@ mc_account_clear_cache (void) { } +static inline gboolean +parse_object_path (McAccountPrivate *priv, const gchar *object_path) +{ + gchar manager[64], protocol[64], unique_name[256]; + gint n; + + n = sscanf (object_path, MC_ACCOUNT_DBUS_OBJECT_BASE "%[^/]/%[^/]/%s", + manager, protocol, unique_name); + if (n != 3) return FALSE; + + priv->manager_name = g_strdup (manager); + priv->protocol_name = g_strdup (protocol); + priv->unique_name = g_strdup (MC_ACCOUNT_UNIQUE_NAME_FROM_PATH (object_path)); + return TRUE; +} + +static void +print_prop (gpointer key, gpointer ht_value, gpointer userdata) +{ + const gchar *name = key; + const GValue *value = ht_value; + + g_debug ("prop: %s (%s)", name, G_VALUE_TYPE_NAME (value)); +} + +static void +on_account_property_changed (TpProxy *proxy, GHashTable *properties, + gpointer user_data, GObject *weak_object) +{ + //McAccount *account = MC_ACCOUNT (weak_object); + McAccountPrivate *priv = user_data; + const GValue *value; + + g_debug ("%s called on %s", G_STRFUNC, priv->unique_name); + + g_hash_table_foreach (properties, print_prop, NULL); + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_VALID); + if (value) + priv->valid = g_value_get_boolean (value); + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME); + if (value) + priv->normalized_names = set_first_element (priv->normalized_names, + g_value_get_string (value)); + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME); + if (value) + priv->display_names = set_first_element (priv->display_names, + g_value_get_string (value)); + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_ALIAS); + if (value) + { + g_free (priv->alias); + priv->alias = g_value_dup_string (value); + } + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_AVATAR); + if (value) + priv->avatar_id = time(0); + + /* FIXME: we should also emit the "param-changed" signal if an account + * parameter changed, but since is was used only be the mission-control + * process, we can skip now. Besides, we wouldn't know which parameter + * actually changed */ + + /* emit the account-changed signal */ + McAccountMonitor *monitor = mc_account_monitor_new (); + g_signal_emit_by_name (monitor, "account-changed", priv->unique_name); + g_object_unref (monitor); +} + McAccount * -_mc_account_new (const gchar *unique_name) +_mc_account_new (TpDBusDaemon *dbus_daemon, const gchar *object_path) { - McAccountPrivate *priv; - McAccount *new; - gboolean enabled; - gchar *name; + McAccountPrivate *priv; + McAccount *new; + GHashTable *properties; + GError *error = NULL; + + new = (McAccount *)g_object_new (MC_TYPE_ACCOUNT, NULL); + priv = MC_ACCOUNT_PRIV (new); + priv->proxy = g_object_new (MC_TYPE_ACCOUNT_PROXY, + "dbus-daemon", dbus_daemon, + "bus-name", MC_ACCOUNT_MANAGER_DBUS_SERVICE, + "object-path", object_path, + NULL); + if (!priv->proxy || + !parse_object_path (priv, object_path)) + return NULL; + + mc_cli_account_connect_to_account_property_changed (priv->proxy, + on_account_property_changed, + priv, NULL, + (GObject *)new, NULL); + + mc_cli_dbus_properties_do_get_all (priv->proxy, -1, + MC_IFACE_ACCOUNT, + &properties, &error); + if (error) + { + g_warning ("Properties error: %s", error->message); + g_error_free (error); + } + else + { + GValue *value; + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_ENABLED); + if (value) + priv->enabled = g_value_get_boolean (value); - new = (McAccount *)g_object_new (MC_TYPE_ACCOUNT, NULL); - priv = MC_ACCOUNT_PRIV (new); - priv->unique_name = g_strdup (unique_name); + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_VALID); + if (value) + priv->valid = g_value_get_boolean (value); - /* get enabledness status */ - if (_mc_account_gconf_get_boolean (new, MC_ACCOUNTS_GCONF_KEY_ENABLED, - FALSE, &enabled) && enabled) - priv->enabled = TRUE; + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME); + if (value) + priv->normalized_names = g_slist_prepend (NULL, g_value_dup_string (value)); - if (_mc_account_gconf_get_string (new, MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME, - FALSE, &name)) - priv->normalized_names = g_slist_prepend (NULL, name); + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME); + if (value) + priv->display_names = g_slist_prepend (NULL, g_value_dup_string (value)); - if (_mc_account_gconf_get_string (new, MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME, - FALSE, &name)) - priv->display_names = g_slist_prepend (NULL, name); + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_ALIAS); + if (value) + priv->alias = g_value_dup_string (value); - return new; + g_hash_table_destroy (properties); + } + + mc_cli_dbus_properties_do_get_all (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + &properties, &error); + if (error) + { + g_warning ("Compat properties error: %s", error->message); + g_error_free (error); + } + else + { + GValue *value; + + value = g_hash_table_lookup (properties, MC_ACCOUNTS_GCONF_KEY_PROFILE); + if (value) + priv->profile_name = g_value_dup_string (value); + + g_hash_table_destroy (properties); + } + + return new; } void @@ -175,200 +324,10 @@ mc_account_class_init (McAccountClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (McAccountPrivate)); + object_class->dispose = mc_account_dispose; object_class->finalize = mc_account_finalize; } -/* Returns the data dir for the given account name. - * Returned string must be freed by caller. */ -static gchar * -get_account_data_path (const gchar *unique_name) -{ - const gchar *base; - - base = g_getenv ("MC_ACCOUNT_DIR"); - if (!base) - base = ACCOUNTS_DIR; - if (!base) - return NULL; - - if (base[0] == '~') - return g_build_filename (g_get_home_dir(), base + 1, unique_name, NULL); - else - return g_build_filename (base, unique_name, NULL); -} - -/* if key is NULL, returns the gconf dir for the given account name, - * otherwise returns the full key. prepends key with param- if - * param is TRUE. returned string must be freed by caller. */ -static gchar * -_mc_account_path (const gchar *unique_name, - const gchar *key, - gboolean param) -{ - if (key != NULL) - { - if (param) - { - return g_strconcat (MC_ACCOUNTS_GCONF_BASE, "/", - unique_name, "/param-", - key, NULL); - } - else - { - return g_strconcat (MC_ACCOUNTS_GCONF_BASE, "/", - unique_name, "/", - key, NULL); - } - } - else - { - return g_strconcat (MC_ACCOUNTS_GCONF_BASE, "/", - unique_name, NULL); - } -} - -static GConfValue * -_mc_account_gconf_get (McAccount *account, - const gchar *name, - gboolean param) -{ - GConfClient *client; - gchar *key; - GConfValue *value; - - g_return_val_if_fail (account != NULL, NULL); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - NULL); - g_return_val_if_fail (name != NULL, NULL); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, NULL); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - name, param); - value = gconf_client_get (client, key, NULL); - - g_object_unref (client); - g_free (key); - - return value; -} - -static gboolean -_mc_account_gconf_get_boolean (McAccount *account, - const gchar *name, - gboolean param, - gboolean *value) -{ - GConfValue *val; - - g_return_val_if_fail (value != NULL, FALSE); - - val = _mc_account_gconf_get (account, name, param); - - if (val == NULL) - { - return FALSE; - } - - if (val->type != GCONF_VALUE_BOOL) - { - gconf_value_free (val); - return FALSE; - } - - *value = gconf_value_get_bool (val); - gconf_value_free (val); - - return TRUE; -} - -static gboolean -_mc_account_gconf_get_int (McAccount *account, - const gchar *name, - gboolean param, - gint *value) -{ - GConfValue *val; - - g_return_val_if_fail (value != NULL, FALSE); - - val = _mc_account_gconf_get (account, name, param); - - if (val == NULL) - { - return FALSE; - } - - if (val->type != GCONF_VALUE_INT) - { - gconf_value_free (val); - return FALSE; - } - - *value = gconf_value_get_int (val); - gconf_value_free (val); - - return TRUE; -} - -static gboolean -_mc_account_gconf_get_string (McAccount *account, - const gchar *name, - gboolean param, - gchar **value) -{ - GConfValue *val; - - g_return_val_if_fail (value != NULL, FALSE); - - val = _mc_account_gconf_get (account, name, param); - - if (val == NULL) - { - return FALSE; - } - - if (val->type != GCONF_VALUE_STRING) - { - gconf_value_free (val); - return FALSE; - } - - *value = g_strdup (gconf_value_get_string (val)); - gconf_value_free (val); - - return TRUE; -} - -static gboolean -_mc_account_gconf_set_string (McAccount *account, const gchar *name, - const gchar *value) -{ - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - name, FALSE); - if (value) - ok = gconf_client_set_string (client, key, value, NULL); - else - ok = gconf_client_unset (client, key, NULL); - - g_free (key); - g_object_unref (client); - - return ok; -} - /** * mc_account_lookup: * @unique_name: The unique name of the account. @@ -391,8 +350,8 @@ mc_account_lookup (const gchar *unique_name) gboolean _filter_account (McAccount *acct, gpointer data) { - const gchar *compare_account; - gchar *gconf_account, *normalized_name; + const gchar *compare_account, *normalized_name; + gchar *gconf_account; gboolean ret; g_return_val_if_fail (acct != NULL, FALSE); @@ -401,10 +360,9 @@ _filter_account (McAccount *acct, gpointer data) compare_account = (const gchar *) data; - if (!_mc_account_gconf_get_string (acct, - MC_ACCOUNTS_GCONF_KEY_PARAM_ACCOUNT, - TRUE, &gconf_account)) - return FALSE; + if (mc_account_get_param_string (acct, "account", &gconf_account) == + MC_ACCOUNT_SETTING_ABSENT) + return FALSE; ret = (0 == strcmp(gconf_account, compare_account)); @@ -412,14 +370,11 @@ _filter_account (McAccount *acct, gpointer data) if (!ret) { - if (!_mc_account_gconf_get_string (acct, - MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME, - FALSE, &normalized_name)) + normalized_name = mc_account_get_normalized_name (acct); + if (!normalized_name) return FALSE; ret = (0 == strcmp(normalized_name, compare_account)); - - g_free (normalized_name); } return ret; @@ -518,163 +473,50 @@ mc_account_free (McAccount* account) McAccount * mc_account_create (McProfile *profile) { - McAccount *ret = NULL; - GConfClient *client; - const gchar *profile_name; - gchar *unique_name, *key, *data_dir = NULL; - guint i = 0; - gboolean ok; - - g_return_val_if_fail (profile != NULL, NULL); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, NULL); - - profile_name = mc_profile_get_unique_name (profile); - - /* find the first free account with this profile */ - unique_name = NULL; - while (unique_name == NULL && i < MC_ACCOUNTS_MAX) - { - gchar *path; - - unique_name = g_strdup_printf ("%s%u", profile_name, i); - - path = _mc_account_path (unique_name, NULL, FALSE); - if (gconf_client_dir_exists (client, path, NULL)) - { - g_free (unique_name); - unique_name = NULL; - i++; - } - g_free (path); - } - - if (unique_name == NULL) - goto OUT; - - key = _mc_account_path (unique_name, MC_ACCOUNTS_GCONF_KEY_PROFILE, FALSE); - ok = gconf_client_set_string (client, key, profile_name, NULL); - g_free (key); - - if (!ok) - goto OUT; - - /* create the directory for storing the binary objects (i.e., avatar) */ - data_dir = get_account_data_path (unique_name); - if (g_mkdir_with_parents (data_dir, 0777) != 0) - goto OUT; - /* and store it in GConf */ - key = _mc_account_path (unique_name, MC_ACCOUNTS_GCONF_KEY_DATA_DIR, FALSE); - ok = gconf_client_set_string (client, key, data_dir, NULL); - g_free (key); - - /* Account is disabled by default, because there is no guarantee - * the account is usable at this point. The one who created the - * account should enable it when its ready. - */ - ret = _mc_account_new (unique_name); - -OUT: - g_free (data_dir); - g_free (unique_name); - g_object_unref (client); - - return ret; -} - -static gchar * -_account_name_from_key (const gchar *key) -{ - guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE); - const gchar *base, *slash; - - g_assert (key == strstr (key, MC_ACCOUNTS_GCONF_BASE)); - g_assert (strlen (key) > base_len + 1); - - base = key + base_len + 1; - slash = strchr (base, '/'); - - if (slash == NULL) - return g_strdup (base); - else - return g_strndup (base, slash - base); -} - -static gboolean -mc_account_expunge_deleted (gpointer user_data) -{ - GConfClient *client; - gchar *key; - GSList *entries, *tmp; - gboolean ok = TRUE; - GError *error = NULL; - GSList *i, *dirs; - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error); + McAccountMonitor *monitor; + McAccount *account; + McAccountPrivate *priv; + McProtocol *protocol; + McManager *manager; + const gchar *manager_name, *protocol_name; + GHashTable *params; + GValue value = { 0 }; + + protocol = mc_profile_get_protocol (profile); + if (!protocol) return NULL; + manager = mc_protocol_get_manager (protocol); + if (!manager) return NULL; + + protocol_name = mc_protocol_get_name (protocol); + manager_name = mc_manager_get_unique_name (manager); + monitor = mc_account_monitor_new (); + params = g_hash_table_new (g_str_hash, g_str_equal); + account = _mc_account_monitor_create_account (monitor, manager_name, + protocol_name, NULL, + params); + g_hash_table_destroy (params); + g_object_unref (protocol); + g_object_unref (monitor); + g_object_unref (manager); - if (NULL != error) - { - g_print ("Error: %s\n", error->message); - g_assert_not_reached (); - } - for (i = dirs; NULL != i; i = i->next) + if (account) { - gchar *unique_name = _account_name_from_key (i->data); - gchar *data_dir_str; - GDir *data_dir; - - McAccount *account = _mc_account_new (unique_name); - - if (!mc_account_is_deleted (account)) - { - g_object_unref (account); - g_free (i->data); - g_free (unique_name); - continue; - } - - key = _mc_account_path (unique_name, NULL, FALSE); - entries = gconf_client_all_entries (client, key, NULL); - g_free (key); - - for (tmp = entries; tmp != NULL; tmp = tmp->next) - { - GConfEntry *entry; - entry = (GConfEntry*) tmp->data; - - if (!gconf_client_unset (client, entry->key, NULL)) - ok = FALSE; - - gconf_entry_free (entry); - } - - data_dir_str = get_account_data_path (unique_name); - data_dir = g_dir_open (data_dir_str, 0, NULL); - if (data_dir) - { - const gchar *filename; - while ((filename = g_dir_read_name (data_dir)) != NULL) - { - gchar *path; - path = g_build_filename (data_dir_str, filename, NULL); - g_remove (path); - g_free (path); - } - g_dir_close (data_dir); - g_rmdir (data_dir_str); - } - g_free (data_dir_str); - - g_free (i->data); - g_free (unique_name); - g_slist_free (entries); + GError *error = NULL; + priv = account->priv; + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, mc_profile_get_unique_name (profile)); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + MC_ACCOUNTS_GCONF_KEY_PROFILE, + &value, &error); + if (error) + { + g_warning ("setting profile on %s failed: %s", + priv->unique_name, error->message); + g_error_free (error); + } } - g_object_unref (client); - return FALSE; + return account; } /** @@ -689,21 +531,21 @@ mc_account_expunge_deleted (gpointer user_data) gboolean mc_account_delete (McAccount *account) { - gboolean ok; + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GError *error = NULL; - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV(account)->unique_name != NULL, - FALSE); - mc_account_set_enabled (account, FALSE); - - ok = mc_account_set_deleted (account, TRUE); + mc_account_set_enabled (account, FALSE); + + mc_cli_account_do_remove (priv->proxy, -1, &error); + if (error) + { + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } - /* Expunge deleted accounts after 5 secs. We can't expunge the accounts - * immediately because there might be other people using the accounts - * and gconf signaling is really async. - */ - g_timeout_add (2000, (GSourceFunc)mc_account_expunge_deleted, NULL); - return ok; + return TRUE; } /** @@ -765,24 +607,10 @@ mc_accounts_list_by_enabled (gboolean enabled) static gboolean _filter_profile (McAccount *acct, gpointer data) { - McProfile *profile; - gchar *profile_name; - gboolean ret; - - g_return_val_if_fail (acct != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (acct)->unique_name != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - profile = (McProfile *) data; - - if (!_mc_account_gconf_get_string (acct, MC_ACCOUNTS_GCONF_KEY_PROFILE, - FALSE, &profile_name)) - return FALSE; - - ret = (0 == strcmp (profile_name, mc_profile_get_unique_name (profile))); - g_free (profile_name); + McAccountPrivate *priv = acct->priv; + gchar *profile_name = data; - return ret; + return strcmp (priv->profile_name, profile_name) == 0; } /** @@ -797,12 +625,15 @@ _filter_profile (McAccount *acct, gpointer data) GList * mc_accounts_list_by_profile (McProfile *profile) { + const gchar *profile_name; GList *ret; g_return_val_if_fail (profile != NULL, NULL); + profile_name = mc_profile_get_unique_name (profile); + g_return_val_if_fail (profile_name != NULL, NULL); ret = mc_accounts_list (); - ret = mc_accounts_filter (ret, _filter_profile, profile); + ret = mc_accounts_filter (ret, _filter_profile, (gchar *)profile_name); return ret; } @@ -840,8 +671,7 @@ static gboolean _filter_secondary_vcard_field (McAccount *acct, gpointer data) { const gchar *vcard_field; - GConfValue *val; - GSList *fields; + GList *fields, *field; gboolean ret; g_return_val_if_fail (acct != NULL, FALSE); @@ -850,18 +680,18 @@ _filter_secondary_vcard_field (McAccount *acct, gpointer data) vcard_field = (const gchar *) data; - val = _mc_account_gconf_get (acct, - MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS, FALSE); - if (val == NULL) return FALSE; + fields = mc_account_get_secondary_vcard_fields (acct); + if (fields == NULL) return FALSE; ret = FALSE; - for (fields = gconf_value_get_list(val); fields; fields = fields->next) { - if (0 == strcmp(vcard_field, gconf_value_get_string(fields->data))) { + for (field = fields; field != NULL; field = field->next) { + if (0 == strcmp(vcard_field, fields->data)) { ret = TRUE; } } - gconf_value_free(val); + g_list_foreach (fields, (GFunc)g_free, NULL); + g_list_free (fields); return ret; } @@ -875,35 +705,34 @@ _filter_secondary_vcard_field (McAccount *acct, gpointer data) gboolean mc_account_set_secondary_vcard_fields (McAccount *account, const GList *fields) { - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS, FALSE); - if (fields) + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue value = { 0 }; + GError *error = NULL; + gchar **v_fields; + guint len, i; + + len = g_list_length ((GList *)fields); + v_fields = g_malloc (sizeof (gchar *) * (len + 1)); + for (i = 0; fields; fields = fields->next, i++) + v_fields[i] = g_strdup (fields->data); + v_fields[i] = NULL; + + g_value_init (&value, G_TYPE_STRV); + g_value_take_boxed (&value, v_fields); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS, + &value, &error); + g_value_unset (&value); + if (error) { - GSList *s_fields = NULL; - - for (; fields != NULL; fields = fields->next) - s_fields = g_slist_prepend (s_fields, fields->data); - - ok = gconf_client_set_list (client, key, GCONF_VALUE_STRING, s_fields, NULL); + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; } else - ok = gconf_client_unset (client, key, NULL); - - g_free (key); - g_object_unref (client); - - return ok; + return TRUE; } /** @@ -916,20 +745,37 @@ mc_account_set_secondary_vcard_fields (McAccount *account, const GList *fields) GList * mc_account_get_secondary_vcard_fields (McAccount * acct) { - GConfValue *val; - GSList *fields; - GList *ret = NULL; - - val = _mc_account_gconf_get (acct, - MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS, FALSE); - if (val == NULL) return NULL; +#ifdef GET_SECONDARY_VCARD_FIELDS + McAccountPrivate *priv = MC_ACCOUNT_PRIV (acct); + GValue *val_fields; + GList *ret = NULL; + gchar **fields, **field; + GError *error = NULL; + + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + MC_ACCOUNTS_GCONF_KEY_SECONDARY_VCARD_FIELDS, + &val_fields, &error); + if (error) + { + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return NULL; + } + fields = g_value_get_boxed (val_fields); + g_free (val_fields); - for (fields = gconf_value_get_list(val); fields; fields = fields->next) { - ret = g_list_prepend(ret, g_strdup(gconf_value_get_string(fields->data))); - } + /* put the fields into a list */ + for (field = fields; *field != NULL; field++) + ret = g_list_append (ret, *field); + g_free (fields); - gconf_value_free(val); - return ret; + return ret; +#else + g_warning ("%s is disabled due to spamming", G_STRFUNC); + return NULL; +#endif } /** @@ -1058,15 +904,9 @@ mc_account_get_normalized_name (McAccount *account) gboolean mc_account_set_normalized_name (McAccount *account, const gchar *name) { - if (_mc_account_gconf_set_string (account, - MC_ACCOUNTS_GCONF_KEY_NORMALIZED_NAME, - name)) - { - _mc_account_set_normalized_name_priv (account, name); - return TRUE; - } - else - return FALSE; + g_warning ("%s: only mission-control should call this function!", + G_STRFUNC); + return FALSE; } /** @@ -1105,9 +945,22 @@ mc_account_get_profile (McAccount *account) priv = MC_ACCOUNT_PRIV (account); if (G_UNLIKELY (!priv->profile_name)) { - if (!_mc_account_gconf_get_string (account, MC_ACCOUNTS_GCONF_KEY_PROFILE, - FALSE, &priv->profile_name)) - return NULL; + GValue *val_profile; + GError *error = NULL; + + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + MC_ACCOUNTS_GCONF_KEY_PROFILE, + &val_profile, &error); + if (error) + { + g_warning ("%s: getting profile for %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return NULL; + } + priv->profile_name = (gchar *)g_value_get_string (val_profile); + g_free (val_profile); } return mc_profile_lookup (priv->profile_name); @@ -1145,15 +998,25 @@ mc_account_get_display_name (McAccount *account) gboolean mc_account_set_display_name (McAccount *account, const gchar *name) { - if (_mc_account_gconf_set_string (account, - MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME, - (name && *name) ? name : NULL)) + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue value = { 0 }; + GError *error = NULL; + + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, name); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_DISPLAY_NAME, + &value, &error); + if (error) { - _mc_account_set_display_name_priv (account, name); - return TRUE; + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; } else - return FALSE; + return TRUE; } /** @@ -1172,44 +1035,6 @@ mc_account_is_enabled (McAccount *account) return MC_ACCOUNT_PRIV (account)->enabled; } -static gboolean -mc_account_is_deleted (McAccount *account) -{ - gboolean deleted; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, FALSE); - - if (!_mc_account_gconf_get_boolean (account, MC_ACCOUNTS_GCONF_KEY_DELETED, - FALSE, &deleted)) - return FALSE; - - return deleted; -} - -static gboolean -mc_account_set_deleted (McAccount *account, gboolean deleted) -{ - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_DELETED, FALSE); - ok = gconf_client_set_bool (client, key, deleted, NULL); - - g_free (key); - g_object_unref (client); - - return ok; -} - /** * mc_account_set_enabled: * @account: The #McAccount. @@ -1220,27 +1045,49 @@ mc_account_set_deleted (McAccount *account, gboolean deleted) * Return value: %TRUE, or %FALSE if some error occurred. */ gboolean -mc_account_set_enabled (McAccount *account, const gboolean enabled) -{ - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - gconf_client_suggest_sync (client, NULL); - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_ENABLED, FALSE); - ok = gconf_client_set_bool (client, key, enabled, NULL); +mc_account_set_enabled (McAccount *account, gboolean enabled) +{ + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue value = { 0 }; + GError *error = NULL; + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, enabled); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_ENABLED, + &value, &error); + if (error) + { + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } + else + return TRUE; +} - g_free (key); - g_object_unref (client); +static gboolean +mc_account_get_param (McAccount *account, const gchar *name, + GValue *dst_value) +{ + GHashTable *parameters; + GValue *value; + gboolean ok = FALSE; - return ok; + g_debug ("%s: %s", G_STRFUNC, name); + parameters = mc_account_get_params (account); + if (!parameters) return FALSE; + value = g_hash_table_lookup (parameters, name); + if (value) + { + g_value_init (dst_value, G_VALUE_TYPE (value)); + g_value_copy (value, dst_value); + ok = TRUE; + } + g_hash_table_destroy (parameters); + return ok; } /** @@ -1259,6 +1106,7 @@ mc_account_get_param_boolean (McAccount *account, gboolean *value) { McAccountSettingState ret; + GValue val = { 0 }; g_return_val_if_fail (account != NULL, MC_ACCOUNT_SETTING_ABSENT); g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, @@ -1270,8 +1118,9 @@ mc_account_get_param_boolean (McAccount *account, ret = MC_ACCOUNT_SETTING_ABSENT; - if (_mc_account_gconf_get_boolean (account, name, TRUE, value)) + if (mc_account_get_param (account, name, &val)) { + *value = g_value_get_boolean (&val); ret = MC_ACCOUNT_SETTING_FROM_ACCOUNT; } else @@ -1485,6 +1334,7 @@ mc_account_get_param_int (McAccount *account, gint int_val; McProfile *profile; const gchar *def; + GValue val = { 0 }; g_return_val_if_fail (account != NULL, MC_ACCOUNT_SETTING_ABSENT); g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, @@ -1494,8 +1344,26 @@ mc_account_get_param_int (McAccount *account, /* TODO: retreive type from protocol and check it matches */ - if (_mc_account_gconf_get_int (account, name, TRUE, value)) + if (mc_account_get_param (account, name, &val)) + { + if (G_VALUE_TYPE (&val) == G_TYPE_INT) + *value = g_value_get_int (&val); + else if (g_value_type_transformable (G_VALUE_TYPE (&val), G_TYPE_INT)) + { + GValue trans = { 0 }; + + g_value_init (&trans, G_TYPE_INT); + g_value_transform (&val, &trans); + *value = g_value_get_int (&trans); + } + else + { + g_warning ("%s: param %s has type %s (expecting integer)", + G_STRFUNC, name, G_VALUE_TYPE_NAME (&val)); + return MC_ACCOUNT_SETTING_ABSENT; + } return MC_ACCOUNT_SETTING_FROM_ACCOUNT; + } profile = mc_account_get_profile (account); def = mc_profile_get_default_setting (profile, name); @@ -1569,6 +1437,8 @@ mc_account_get_param_string (McAccount *account, { McProfile *profile; const gchar *def; + GValue val = { 0 }; + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); g_return_val_if_fail (account != NULL, MC_ACCOUNT_SETTING_ABSENT); g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, @@ -1578,8 +1448,23 @@ mc_account_get_param_string (McAccount *account, /* TODO: retreive type from protocol and check it matches */ - if (_mc_account_gconf_get_string (account, name, TRUE, value)) + if (priv->last_name && strcmp (priv->last_name, name) == 0) + { + g_warning ("%s: you are calling me for the same param (%s), please cache it", + G_STRFUNC, name); + *value = g_strdup (priv->last_value); return MC_ACCOUNT_SETTING_FROM_ACCOUNT; + } + g_free (priv->last_name); + priv->last_name = NULL; + if (mc_account_get_param (account, name, &val)) + { + *value = (gchar *)g_value_get_string (&val); + g_free (priv->last_value); + priv->last_name = g_strdup (name); + priv->last_value = g_strdup (*value); + return MC_ACCOUNT_SETTING_FROM_ACCOUNT; + } profile = mc_account_get_profile (account); def = mc_profile_get_default_setting (profile, name); @@ -1614,6 +1499,35 @@ mc_account_get_param_string (McAccount *account, return MC_ACCOUNT_SETTING_ABSENT; } +static gboolean +mc_account_set_param (McAccount *account, const gchar *name, + const GValue *value) +{ + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + const gchar *unset[] = { NULL, NULL }; + GHashTable *set; + GError *error = NULL; + + set = g_hash_table_new (g_str_hash, g_str_equal); + if (value) + g_hash_table_insert (set, (gpointer)name, (gpointer)value); + else + unset[0] = name; + mc_cli_account_do_update_parameters (priv->proxy, -1, + set, unset, + &error); + g_hash_table_destroy (set); + if (error) + { + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } + else + return TRUE; +} + /** * mc_account_set_param_boolean: * @account: The #McAccount. @@ -1629,26 +1543,53 @@ mc_account_set_param_boolean (McAccount *account, const gchar *name, gboolean value) { - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); + GValue val = { 0 }; - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, name, - TRUE); - ok = gconf_client_set_bool (client, key, value, NULL); + g_value_init (&val, G_TYPE_BOOLEAN); + g_value_set_boolean (&val, value); + return mc_account_set_param (account, name, &val); +} - g_free (key); - g_object_unref (client); +static inline GType +get_param_type (McAccount *account, const gchar *name) +{ + McProfile *profile; + McProtocol *protocol; + GType ret = G_TYPE_INT; - return ok; + profile = mc_account_get_profile (account); + if (profile) + { + protocol = mc_profile_get_protocol (profile); + if (protocol) + { + GSList *params, *param; + + params = mc_protocol_get_params (protocol); + for (param = params; param != NULL; param = param->next) + { + McProtocolParam *p = param->data; + if (strcmp (p->name, name) == 0) + { + switch (p->signature[0]) + { + case DBUS_TYPE_INT16: + case DBUS_TYPE_INT32: + ret = G_TYPE_INT; + break; + case DBUS_TYPE_UINT16: + case DBUS_TYPE_UINT32: + ret = G_TYPE_UINT; + break; + } + break; + } + } + g_object_unref (protocol); + } + g_object_unref (profile); + } + return ret; } /** @@ -1666,26 +1607,16 @@ mc_account_set_param_int (McAccount *account, const gchar *name, gint value) { - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, name, - TRUE); - ok = gconf_client_set_int (client, key, value, NULL); - - g_free (key); - g_object_unref (client); + GValue val = { 0 }; + GType type; - return ok; + type = get_param_type (account, name); + g_value_init (&val, type); + if (type == G_TYPE_INT) + g_value_set_int (&val, value); + else + g_value_set_uint (&val, (guint)value); + return mc_account_set_param (account, name, &val); } /** @@ -1703,26 +1634,11 @@ mc_account_set_param_string (McAccount *account, const gchar *name, const gchar *value) { - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, name, - TRUE); - ok = gconf_client_set_string (client, key, value, NULL); + GValue val = { 0 }; - g_free (key); - g_object_unref (client); - - return ok; + g_value_init (&val, G_TYPE_STRING); + g_value_set_static_string (&val, value); + return mc_account_set_param (account, name, &val); } /** @@ -1737,111 +1653,7 @@ mc_account_set_param_string (McAccount *account, gboolean mc_account_unset_param (McAccount *account, const gchar *name) { - McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != NULL, FALSE); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (priv->unique_name, name, TRUE); - ok = gconf_client_unset (client, key, NULL); - - g_free (key); - g_object_unref (client); - - return ok; -} - -static void -_g_value_free (gpointer data) -{ - GValue *value = (GValue *) data; - g_value_unset (value); - g_free (value); -} - -static void -_add_one_setting (McAccount *account, - McProtocolParam *param, - GHashTable *hash) -{ - GValue *value = NULL; - McAccountSettingState ret = MC_ACCOUNT_SETTING_ABSENT; - - g_return_if_fail (account != NULL); - g_return_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL); - g_return_if_fail (param != NULL); - g_return_if_fail (param->name != NULL); - g_return_if_fail (param->signature != NULL); - - switch (param->signature[0]) - { - case DBUS_TYPE_STRING: - { - char *tmp; - ret = mc_account_get_param_string (account, param->name, &tmp); - if (ret != MC_ACCOUNT_SETTING_ABSENT) - { - value = g_new0(GValue, 1); - g_value_init (value, G_TYPE_STRING); - g_value_take_string (value, tmp); - } - break; - } - case DBUS_TYPE_INT16: - case DBUS_TYPE_INT32: - { - gint tmp; - ret = mc_account_get_param_int (account, param->name, &tmp); - if (ret != MC_ACCOUNT_SETTING_ABSENT) - { - value = g_new0(GValue, 1); - g_value_init (value, G_TYPE_INT); - g_value_set_int (value, tmp); - } - break; - } - case DBUS_TYPE_UINT16: - case DBUS_TYPE_UINT32: - { - gint tmp; - ret = mc_account_get_param_int (account, param->name, &tmp); - if (ret != MC_ACCOUNT_SETTING_ABSENT) - { - value = g_new0(GValue, 1); - g_value_init (value, G_TYPE_UINT); - g_value_set_uint (value, tmp); - } - break; - } - case DBUS_TYPE_BOOLEAN: - { - gboolean tmp; - ret = mc_account_get_param_boolean (account, param->name, &tmp); - if (ret != MC_ACCOUNT_SETTING_ABSENT) - { - value = g_new0(GValue, 1); - g_value_init (value, G_TYPE_BOOLEAN); - g_value_set_boolean (value, tmp); - } - break; - } - default: - g_warning ("%s: skipping parameter %s, unknown type %s", G_STRFUNC, param->name, param->signature); - } - - if (ret != MC_ACCOUNT_SETTING_ABSENT && hash != NULL) - { - g_return_if_fail (value != NULL); - g_hash_table_insert (hash, g_strdup (param->name), value); - } + return mc_account_set_param (account, name, NULL); } /** @@ -1856,48 +1668,33 @@ _add_one_setting (McAccount *account, GHashTable * mc_account_get_params (McAccount *account) { - McProfile *profile = NULL; - McProtocol *protocol = NULL; - GSList *params, *tmp; - GHashTable *ret = NULL; - - g_return_val_if_fail (account != NULL, NULL); - g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, - NULL); + GHashTable *parameters; + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue *val_parameters; + GError *error = NULL; - profile = mc_account_get_profile (account); - if (profile == NULL) - { - g_debug ("%s: getting profile failed", G_STRFUNC); - goto OUT; - } + g_return_val_if_fail (account != NULL, NULL); + g_return_val_if_fail (MC_ACCOUNT_PRIV (account)->unique_name != NULL, + NULL); - protocol = mc_profile_get_protocol (profile); - if (protocol == NULL) + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_PARAMETERS, + &val_parameters, &error); + if (error) { - g_debug ("%s: getting protocol failed", G_STRFUNC); - goto OUT; + g_warning ("%s: getting parameters for %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return NULL; } - ret = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) _g_value_free); - - params = mc_protocol_get_params (protocol); + parameters = g_value_get_boxed (val_parameters); - for (tmp = params; tmp != NULL; tmp = tmp->next) - _add_one_setting (account, (McProtocolParam *) tmp->data, ret); + /* this does not free the hastable */ + g_free (val_parameters); - mc_protocol_free_params_list (params); - -OUT: - if (protocol) - g_object_unref (protocol); - - if (profile) - g_object_unref (profile); - - return ret; + return parameters; } /** @@ -1912,104 +1709,9 @@ OUT: gboolean mc_account_is_complete (McAccount *account) { - McProfile *profile = NULL; - McProtocol *protocol = NULL; - GSList *params = NULL, *tmp; - gboolean ret = TRUE; - - g_return_val_if_fail (account != NULL, FALSE); - - /* Check if account was expunged */ - if (MC_ACCOUNT_PRIV (account)->unique_name == NULL) - return FALSE; - - /* Check if account was deleted */ - if (mc_account_is_deleted (account)) - return FALSE; - - profile = mc_account_get_profile (account); - if (profile == NULL) - { - ret = FALSE; - goto OUT; - } - - protocol = mc_profile_get_protocol (profile); - if (protocol == NULL) - { - ret = FALSE; - goto OUT; - } - - params = mc_protocol_get_params (protocol); - - for (tmp = params; tmp != NULL; tmp = tmp->next) - { - McProtocolParam *param; - const gchar *def; - GConfValue *val; - - param = (McProtocolParam *) tmp->data; - - if (!(param->flags & MC_PROTOCOL_PARAM_REQUIRED)) - continue; - - if (param == NULL || param->name == NULL || param->signature == NULL) - { - ret = FALSE; - break; - } - - /* TODO: check this value can be mapped to the desired type */ - def = mc_profile_get_default_setting (profile, param->name); - if (def) - { - continue; - } - - val = _mc_account_gconf_get (account, param->name, TRUE); - if (val == NULL) - { - ret = FALSE; - break; - } - - /* TODO: unduplicate this type mapping */ - switch (param->signature[0]) - { - case DBUS_TYPE_BOOLEAN: - if (val->type != GCONF_VALUE_BOOL) - ret = FALSE; - break; - case DBUS_TYPE_INT16: - case DBUS_TYPE_UINT16: - if (val->type != GCONF_VALUE_INT) - ret = FALSE; - break; - case DBUS_TYPE_STRING: - if (val->type != GCONF_VALUE_STRING) - ret = FALSE; - break; - default: - ret = FALSE; - } - - gconf_value_free (val); - - if (ret == FALSE) - break; - } - - mc_protocol_free_params_list (params); - -OUT: - if (profile != NULL) - g_object_unref (profile); - - if (protocol != NULL) - g_object_unref (protocol); + g_return_val_if_fail (account != NULL, FALSE); - return ret; + return MC_ACCOUNT_PRIV (account)->valid; } /** @@ -2107,67 +1809,37 @@ gboolean mc_account_set_avatar_from_data (McAccount *account, const gchar *data, gsize len, const gchar *mime_type) { - gchar *data_dir, *filename_out; - GConfClient *client; - gboolean ret = TRUE; - gchar *key; - - g_return_val_if_fail (account != NULL, FALSE); - - data_dir = get_account_data_path (MC_ACCOUNT_PRIV(account)->unique_name); - filename_out = g_build_filename (data_dir, MC_AVATAR_FILENAME, NULL); - if (!g_file_test (data_dir, G_FILE_TEST_EXISTS)) - g_mkdir_with_parents (data_dir, 0777); - g_free (data_dir); - - if (data) + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue value = { 0 }; + GError *error = NULL; + GArray avatar; + GType type; + + avatar.data = (gchar *)data; + avatar.len = len; + type = dbus_g_type_get_struct ("GValueArray", + dbus_g_type_get_collection ("GArray", + G_TYPE_UCHAR), + G_TYPE_STRING, + G_TYPE_INVALID); + g_value_init (&value, type); + g_value_set_static_boxed (&value, dbus_g_type_specialized_construct (type)); + GValueArray *va = (GValueArray *) g_value_get_boxed (&value); + g_value_take_boxed (va->values, &avatar); + g_value_set_static_string (va->values + 1, mime_type); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_AVATAR, + &value, &error); + if (error) { - if (!g_file_set_contents (filename_out, data, (gssize)len, NULL)) - { - g_warning ("%s: writing to file %s failed", G_STRLOC, - filename_out); - g_free (filename_out); - return FALSE; - } + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; } else - { - /* create an empty file; this will cause MC to clear the current - * avatar */ - FILE *f_out = fopen (filename_out, "w"); - fclose (f_out); - } - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_TOKEN, FALSE); - ret = gconf_client_unset(client, key, NULL); - g_free (key); - if (!ret) goto error; - - /* put an ID for the avatar, so that listeners of the "account-changed" - * signal will be able to determine whether the avatar has changed without - * having to load the file */ - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_ID, FALSE); - ret = gconf_client_set_int(client, key, time(0), NULL); - g_free (key); - - if (mime_type) - { - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_MIME, FALSE); - ret = gconf_client_set_string (client, key, mime_type, NULL); - g_free (key); - } - -error: - g_object_unref (client); - g_free (filename_out); - - return ret; + return TRUE; } /** @@ -2183,9 +1855,9 @@ error: gboolean mc_account_set_avatar_token (McAccount *account, const gchar *token) { - return _mc_account_gconf_set_string (account, - MC_ACCOUNTS_GCONF_KEY_AVATAR_TOKEN, - token); + g_warning ("%s: only mission-control should call this function!", + G_STRFUNC); + return FALSE; } /** @@ -2201,9 +1873,9 @@ mc_account_set_avatar_token (McAccount *account, const gchar *token) gboolean mc_account_set_avatar_mime_type (McAccount *account, const gchar *mime_type) { - return _mc_account_gconf_set_string (account, - MC_ACCOUNTS_GCONF_KEY_AVATAR_MIME, - mime_type); + g_warning ("%s: only mission-control should call this function!", + G_STRFUNC); + return FALSE; } /** @@ -2223,43 +1895,54 @@ gboolean mc_account_get_avatar (McAccount *account, gchar **filename, gchar **mime_type, gchar **token) { - gchar *data_dir; - GConfClient *client; - gchar *key; - - g_return_val_if_fail (account != NULL, FALSE); + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue *val_avatar; + GError *error = NULL; if (filename) { - data_dir = - get_account_data_path (MC_ACCOUNT_PRIV (account)->unique_name); - *filename = g_build_filename (data_dir, MC_AVATAR_FILENAME, NULL); - if (!g_file_test (data_dir, G_FILE_TEST_EXISTS)) - g_mkdir_with_parents (data_dir, 0777); - g_free (data_dir); + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + MC_ACCOUNTS_GCONF_KEY_AVATAR_FILE, + &val_avatar, &error); + if (error) + { + g_warning ("%s: getting avatar file for %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } + *filename = (gchar *)g_value_get_string (val_avatar); + g_free (val_avatar); } - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, FALSE); - - if (token) + if (mime_type) { - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_TOKEN, FALSE); - *token = gconf_client_get_string (client, key, NULL); - g_free (key); + mc_cli_dbus_properties_do_get (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_AVATAR, + &val_avatar, &error); + if (error) + { + g_warning ("%s: getting avatar for %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } + GValueArray *va = (GValueArray *) g_value_get_boxed (val_avatar); + g_debug ("value array at %p, type %s, %d elems", va, G_VALUE_TYPE_NAME (val_avatar), va->n_values); + *mime_type = g_value_dup_string (va->values + 1); + g_value_unset (val_avatar); + g_free (val_avatar); } - if (mime_type) + /* we cannot know the token, but it was used only for mission-control */ + if (token) { - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_MIME, FALSE); - *mime_type = gconf_client_get_string (client, key, NULL); - g_free (key); + g_warning ("%s: only mission-control should retrieve the token!", + G_STRFUNC); } - g_object_unref (client); - return TRUE; } @@ -2275,22 +1958,9 @@ mc_account_get_avatar (McAccount *account, gchar **filename, gint mc_account_get_avatar_id (McAccount *account) { - GConfClient *client; - gchar *key; - gint ret; + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); - g_return_val_if_fail (account != NULL, 0); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != NULL, 0); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_ID, FALSE); - ret = gconf_client_get_int (client, key, NULL); - g_free (key); - - g_object_unref (client); - return ret; + return priv->avatar_id; } /** @@ -2306,22 +1976,8 @@ mc_account_get_avatar_id (McAccount *account) gboolean mc_account_reset_avatar_id (McAccount *account) { - GConfClient *client; - gchar *key; - gboolean ok; - - g_return_val_if_fail (account != FALSE, 0); - - client = gconf_client_get_default (); - g_return_val_if_fail (client != FALSE, 0); - - key = _mc_account_path (MC_ACCOUNT_PRIV (account)->unique_name, - MC_ACCOUNTS_GCONF_KEY_AVATAR_ID, FALSE); - ok = gconf_client_set_int (client, key, time(0), NULL); - g_free (key); - - g_object_unref (client); - return ok; + /* does nothing */ + return TRUE; } /** @@ -2335,16 +1991,9 @@ mc_account_reset_avatar_id (McAccount *account) gchar * mc_account_get_alias (McAccount *account) { - gchar *name; - g_return_val_if_fail (account != NULL, NULL); - if (!_mc_account_gconf_get_string (account, - MC_ACCOUNTS_GCONF_KEY_ALIAS, - FALSE, &name)) - return NULL; - - return name; + return g_strdup (MC_ACCOUNT_PRIV (account)->alias); } /** @@ -2359,7 +2008,24 @@ mc_account_get_alias (McAccount *account) gboolean mc_account_set_alias (McAccount *account, const gchar *alias) { - return _mc_account_gconf_set_string (account, - MC_ACCOUNTS_GCONF_KEY_ALIAS, - alias); + McAccountPrivate *priv = MC_ACCOUNT_PRIV (account); + GValue value = { 0 }; + GError *error = NULL; + + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, alias); + mc_cli_dbus_properties_do_set (priv->proxy, -1, + MC_IFACE_ACCOUNT, + MC_ACCOUNTS_GCONF_KEY_ALIAS, + &value, &error); + if (error) + { + g_warning ("%s on %s failed: %s", + G_STRFUNC, priv->unique_name, error->message); + g_error_free (error); + return FALSE; + } + else + return TRUE; } + diff --git a/libmissioncontrol/mc.c b/libmissioncontrol/mc.c index f78a44e8..e8a19d14 100644 --- a/libmissioncontrol/mc.c +++ b/libmissioncontrol/mc.c @@ -22,6 +22,10 @@ */ #include <gmodule.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> +#include <telepathy-glib/proxy-subclass.h> + #include "mc.h" @@ -48,3 +52,111 @@ mc_make_resident (void) g_module_make_resident (module); } +gboolean +mc_cli_dbus_properties_do_get (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + const gchar *in_Property_Name, + GValue **out_Value, + GError **error) +{ + DBusGProxy *iface; + GQuark interface = TP_IFACE_QUARK_DBUS_PROPERTIES; + GValue *o_Value = g_new0 (GValue, 1); + + g_return_val_if_fail (TP_IS_PROXY (proxy), FALSE); + + iface = tp_proxy_borrow_interface_by_id + ((TpProxy *) proxy, interface, error); + + if (iface == NULL) + return FALSE; + + if(dbus_g_proxy_call_with_timeout (iface, + "Get", + timeout_ms, + error, + G_TYPE_STRING, in_Interface_Name, + G_TYPE_STRING, in_Property_Name, + G_TYPE_INVALID, + G_TYPE_VALUE, o_Value, + G_TYPE_INVALID)) + { + *out_Value = o_Value; + return TRUE; + } + else + { + g_free (o_Value); + return FALSE; + } +} + + +gboolean +mc_cli_dbus_properties_do_get_all (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + GHashTable **out_Properties, + GError **error) +{ + DBusGProxy *iface; + GQuark interface = TP_IFACE_QUARK_DBUS_PROPERTIES; + GHashTable *o_Properties; + + g_return_val_if_fail (TP_IS_PROXY (proxy), FALSE); + + iface = tp_proxy_borrow_interface_by_id + ((TpProxy *) proxy, interface, error); + + if (iface == NULL) + return FALSE; + + if (dbus_g_proxy_call_with_timeout (iface, + "GetAll", + timeout_ms, + error, + G_TYPE_STRING, in_Interface_Name, + G_TYPE_INVALID, + (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)), &o_Properties, + G_TYPE_INVALID)) + { + *out_Properties = o_Properties; + + return TRUE; + } + else + return FALSE; +} + + +gboolean +mc_cli_dbus_properties_do_set (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + const gchar *in_Property_Name, + const GValue *in_Value, + GError **error) +{ + DBusGProxy *iface; + GQuark interface = TP_IFACE_QUARK_DBUS_PROPERTIES; + + g_return_val_if_fail (TP_IS_PROXY (proxy), FALSE); + + iface = tp_proxy_borrow_interface_by_id + ((TpProxy *) proxy, interface, error); + + if (iface == NULL) + return FALSE; + + return dbus_g_proxy_call_with_timeout (iface, + "Set", + timeout_ms, + error, + G_TYPE_STRING, in_Interface_Name, + G_TYPE_STRING, in_Property_Name, + G_TYPE_VALUE, in_Value, + G_TYPE_INVALID); +} + + diff --git a/libmissioncontrol/mc.h b/libmissioncontrol/mc.h index 0dc16017..260f52d1 100644 --- a/libmissioncontrol/mc.h +++ b/libmissioncontrol/mc.h @@ -21,9 +21,35 @@ * */ +#ifndef __MC_H__ +#define __MC_H__ + +#include <glib-object.h> + G_BEGIN_DECLS void mc_make_resident (void); +gboolean mc_cli_dbus_properties_do_get (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + const gchar *in_Property_Name, + GValue **out_Value, + GError **error); + +gboolean mc_cli_dbus_properties_do_get_all (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + GHashTable **out_Properties, + GError **error); + +gboolean mc_cli_dbus_properties_do_set (gpointer proxy, + gint timeout_ms, + const gchar *in_Interface_Name, + const gchar *in_Property_Name, + const GValue *in_Value, + GError **error); + G_END_DECLS +#endif diff --git a/src/Makefile.am b/src/Makefile.am index e93a3002..4eaa0434 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,7 @@ INCLUDES = $(GCONF_CFLAGS) $(TELEPATHY_CFLAGS) \ mission_control_includedir = $(includedir)/mission-control mission_control_include = \ mcd-account.h \ + mcd-account-compat.h \ mcd-account-manager.h \ mcd-dbusprop.h \ mcd-debug.h \ @@ -31,6 +32,7 @@ nodist_geninclude_HEADERS = \ _gen/interfaces.h \ _gen/gtypes.h \ _gen/svc-Account.h \ + _gen/svc-Account_Interface_Compat.h \ _gen/svc-Account_Manager.h nodist_libmissioncontrol_server_la_SOURCES = \ @@ -41,6 +43,7 @@ nodist_libmissioncontrol_server_la_SOURCES = \ _gen/signals-marshal.h \ _gen/signals-marshal.list \ _gen/svc-Account.c \ + _gen/svc-Account_Interface_Compat.c \ _gen/svc-Account_Manager.c @@ -73,6 +76,7 @@ libmissioncontrol_server_la_LDFLAGS = -export-dynamic \ libmissioncontrol_server_la_SOURCES = \ mcd-account.c \ + mcd-account-compat.c \ mcd-account-manager.c \ mcd-dbusprop.c \ mcd-debug.c \ diff --git a/src/mcd-account-compat.c b/src/mcd-account-compat.c new file mode 100644 index 00000000..fa64240f --- /dev/null +++ b/src/mcd-account-compat.c @@ -0,0 +1,153 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 8 -*- */ +/* + * This file is part of mission-control + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Alberto Mardegan <alberto.mardegan@nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <stdio.h> +#include <string.h> +#include <glib/gstdio.h> +#include <glib/gi18n.h> +#include <config.h> + +#include <telepathy-glib/svc-generic.h> +#include <telepathy-glib/gtypes.h> +#include <telepathy-glib/util.h> +#include "mcd-account.h" +#include "mcd-account-priv.h" +#include "mcd-account-compat.h" +#include "mcd-account-manager.h" +#include "_gen/interfaces.h" + + +static void +set_profile (TpSvcDBusProperties *self, const gchar *name, + const GValue *value) +{ + McdAccount *account = MCD_ACCOUNT (self); + const gchar *string, *unique_name; + GKeyFile *keyfile; + + keyfile = mcd_account_get_keyfile (account); + unique_name = mcd_account_get_unique_name (account); + string = g_value_get_string (value); + if (string && string[0] != 0) + g_key_file_set_string (keyfile, unique_name, + name, string); + else + { + g_key_file_remove_key (keyfile, unique_name, + name, NULL); + } + mcd_account_manager_write_conf (keyfile); +} + +static void +get_profile (TpSvcDBusProperties *self, const gchar *name, GValue *value) +{ + McdAccount *account = MCD_ACCOUNT (self); + const gchar *unique_name; + GKeyFile *keyfile; + gchar *string; + + keyfile = mcd_account_get_keyfile (account); + unique_name = mcd_account_get_unique_name (account); + string = g_key_file_get_string (keyfile, unique_name, + name, NULL); + g_value_init (value, G_TYPE_STRING); + g_value_take_string (value, string); +} + +static void +get_avatar_file (TpSvcDBusProperties *self, const gchar *name, GValue *value) +{ + McdAccount *account = MCD_ACCOUNT (self); + gchar *string; + + string = mcd_account_get_avatar_filename (account); + g_value_init (value, G_TYPE_STRING); + g_value_take_string (value, string); +} + +static void +set_secondary_vcard_fields (TpSvcDBusProperties *self, const gchar *name, + const GValue *value) +{ + McdAccount *account = MCD_ACCOUNT (self); + const gchar *unique_name, **fields, **field; + GKeyFile *keyfile; + + keyfile = mcd_account_get_keyfile (account); + unique_name = mcd_account_get_unique_name (account); + fields = g_value_get_boxed (value); + if (fields) + { + gsize len; + + for (field = fields, len = 0; *field; field++, len++); + g_key_file_set_string_list (keyfile, unique_name, + name, fields, len); + } + else + { + g_key_file_remove_key (keyfile, unique_name, + name, NULL); + } + mcd_account_manager_write_conf (keyfile); +} + +static void +get_secondary_vcard_fields (TpSvcDBusProperties *self, const gchar *name, + GValue *value) +{ + McdAccount *account = MCD_ACCOUNT (self); + GKeyFile *keyfile; + const gchar *unique_name; + gchar **fields; + + keyfile = mcd_account_get_keyfile (account); + unique_name = mcd_account_get_unique_name (account); + fields = g_key_file_get_string_list (keyfile, unique_name, + name, NULL, NULL); + g_value_init (value, G_TYPE_STRV); + g_value_take_boxed (value, fields); +} + + +McdDBusProp account_compat_properties[] = { + { "Profile", set_profile, get_profile }, + { "AvatarFile", NULL, get_avatar_file }, + { "SecondaryVCardFields", set_secondary_vcard_fields, get_secondary_vcard_fields }, + { 0 }, +}; + +const McdDBusProp * +_mcd_account_compat_get_properties (void) +{ + return account_compat_properties; +} + +void +_mcd_account_compat_iface_init (McSvcAccountInterfaceCompatClass *iface, + gpointer iface_data) +{ +} + diff --git a/src/mcd-account-compat.h b/src/mcd-account-compat.h new file mode 100644 index 00000000..44fd04a0 --- /dev/null +++ b/src/mcd-account-compat.h @@ -0,0 +1,39 @@ +/* + * mcd-account.h - the Telepathy Account D-Bus interface (service side) + * + * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2008 Nokia Corporation + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MCD_ACCOUNT_COMPAT_H__ +#define __MCD_ACCOUNT_COMPAT_H__ + +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/enums.h> +/* auto-generated stubs */ +#include "_gen/svc-Account_Interface_Compat.h" + +#include "mcd-dbusprop.h" + +G_BEGIN_DECLS + +const McdDBusProp *_mcd_account_compat_get_properties (void); +void _mcd_account_compat_iface_init (McSvcAccountInterfaceCompatClass *iface, + gpointer iface_data); + +G_END_DECLS +#endif diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c index 7fd2c860..0087a6ee 100644 --- a/src/mcd-account-manager.c +++ b/src/mcd-account-manager.c @@ -30,6 +30,7 @@ #include <dbus/dbus.h> #include <telepathy-glib/svc-generic.h> +#include <telepathy-glib/util.h> #include <telepathy-glib/errors.h> #include "mcd-account-manager.h" #include "mcd-account.h" @@ -185,10 +186,12 @@ complete_account_creation (McdAccountManager *account_manager, } static gchar * -create_unique_name (McdAccountManagerPrivate *priv, GHashTable *params) +create_unique_name (McdAccountManagerPrivate *priv, const gchar *manager, + const gchar *protocol, GHashTable *params) { gchar *path, *seq, *unique_name = NULL; const gchar *base = NULL; + gchar *esc_manager, *esc_protocol, *esc_base; GValue *value; gint i, len; @@ -199,9 +202,16 @@ create_unique_name (McdAccountManagerPrivate *priv, GHashTable *params) if (!base) base = "account"; - len = strlen (base); + esc_manager = tp_escape_as_identifier (manager); + esc_protocol = tp_escape_as_identifier (protocol); + esc_base = tp_escape_as_identifier (base); + /* add two chars for the "/" */ + len = strlen (esc_manager) + strlen (esc_protocol) + strlen (esc_base) + 2; path = g_malloc (len + 5); - strcpy (path, base); + sprintf (path, "%s/%s/%s", esc_manager, esc_protocol, esc_base); + g_free (esc_manager); + g_free (esc_protocol); + g_free (esc_base); seq = path + len; for (i = 0; i < 1024; i++) { @@ -237,7 +247,7 @@ mcd_account_manager_create_account (McdAccountManager *account_manager, return FALSE; } - unique_name = create_unique_name (priv, params); + unique_name = create_unique_name (priv, manager, protocol, params); if (G_UNLIKELY (unique_name == NULL)) { g_warning ("Couldn't create a unique name"); @@ -620,3 +630,26 @@ mcd_account_manager_lookup_account (McdAccountManager *account_manager, return g_hash_table_lookup (priv->accounts, name); } +static gboolean +find_by_path (gpointer key, gpointer value, gpointer user_data) +{ + McdAccount *account = value; + const gchar *object_path = user_data; + + if (strcmp (object_path, + mcd_account_get_object_path (account)) == 0) + return TRUE; + return FALSE; +} + +/* NOTE: this might become unused when the presence-frame gets removed */ +McdAccount * +mcd_account_manager_lookup_account_by_path (McdAccountManager *account_manager, + const gchar *object_path) +{ + McdAccountManagerPrivate *priv = account_manager->priv; + + return g_hash_table_find (priv->accounts, find_by_path, + (gpointer)object_path); +} + diff --git a/src/mcd-account-manager.h b/src/mcd-account-manager.h index 097dffe9..be1feda3 100644 --- a/src/mcd-account-manager.h +++ b/src/mcd-account-manager.h @@ -69,5 +69,7 @@ GHashTable *mcd_account_manager_get_valid_accounts (McdAccountManager *account_m McdAccount *mcd_account_manager_lookup_account (McdAccountManager *account_manager, const gchar *name); +McdAccount *mcd_account_manager_lookup_account_by_path (McdAccountManager *account_manager, + const gchar *object_path); #endif diff --git a/src/mcd-account.c b/src/mcd-account.c index 960a3980..028a51a0 100644 --- a/src/mcd-account.c +++ b/src/mcd-account.c @@ -29,10 +29,11 @@ #include <config.h> #include <telepathy-glib/svc-generic.h> -#include <telepathy-glib/gtypes.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/gtypes.h> #include "mcd-account.h" #include "mcd-account-priv.h" +#include "mcd-account-compat.h" #include "mcd-account-manager.h" #include "mcd-signals-marshal.h" #include "mcd-manager.h" @@ -57,6 +58,8 @@ G_DEFINE_TYPE_WITH_CODE (McdAccount, mcd_account, G_TYPE_OBJECT, account_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, properties_iface_init); + G_IMPLEMENT_INTERFACE (MC_TYPE_SVC_ACCOUNT_INTERFACE_COMPAT, + _mcd_account_compat_iface_init); ) struct _McdAccountPrivate @@ -239,6 +242,7 @@ mcd_account_request_presence_int (McdAccount *account, return TRUE; } +#ifdef DELAY_PROPERTY_CHANGED static gboolean emit_property_changed (gpointer userdata) { @@ -257,6 +261,7 @@ emit_property_changed (gpointer userdata) priv->properties_source = 0; return FALSE; } +#endif /* * This function is responsible of emitting the AccountPropertyChanged signal. @@ -268,6 +273,7 @@ static void mcd_account_changed_property (McdAccount *account, const gchar *key, const GValue *value) { +#ifdef DELAY_PROPERTY_CHANGED McdAccountPrivate *priv = account->priv; GValue *val; @@ -305,6 +311,17 @@ mcd_account_changed_property (McdAccount *account, const gchar *key, g_value_init (val, G_VALUE_TYPE (value)); g_value_copy (value, val); g_hash_table_insert (priv->changed_properties, (gpointer)key, val); +#else + GHashTable *properties; + + g_debug ("%s called: %s", G_STRFUNC, key); + properties = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (properties, (gpointer)key, (gpointer)value); + mc_svc_account_emit_account_property_changed (account, + properties); + + g_hash_table_destroy (properties); +#endif } static gboolean @@ -1043,6 +1060,8 @@ account_update_parameters (McSvcAccount *self, GHashTable *set, { McdAccount *account = MCD_ACCOUNT (self); McdAccountPrivate *priv = account->priv; + GHashTable *parameters; + GValue value = { 0 }; GError *error = NULL; g_debug ("%s called for %s", G_STRFUNC, priv->unique_name); @@ -1059,6 +1078,13 @@ account_update_parameters (McSvcAccount *self, GHashTable *set, mcd_account_unset_parameters (account, unset); + /* emit the PropertiesChanged signal */ + parameters = mcd_account_get_parameters (account); + g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP); + g_value_take_boxed (&value, parameters); + mcd_account_changed_property (account, "Parameters", &value); + g_value_unset (&value); + mcd_account_check_validity (account); mcd_account_manager_write_conf (priv->keyfile); mc_svc_account_return_from_update_parameters (context); @@ -1095,7 +1121,6 @@ mcd_account_setup (McdAccount *account) { McdAccountPrivate *priv = account->priv; gboolean valid; - gchar *ch, *name; if (!priv->keyfile || !priv->unique_name) return FALSE; @@ -1109,17 +1134,8 @@ mcd_account_setup (McdAccount *account) MC_ACCOUNTS_KEY_PROTOCOL, NULL); if (!priv->protocol_name) return FALSE; - name = tp_escape_as_identifier (priv->unique_name); priv->object_path = g_strconcat (MC_ACCOUNT_DBUS_OBJECT_BASE, - priv->manager_name, "/", - priv->protocol_name, "/", - name, NULL); - g_free (name); - /* seems that the dash is an invalid character... */ - for (ch = priv->object_path + sizeof(MC_ACCOUNT_DBUS_OBJECT_BASE); - *ch != 0; - ch++) - if (*ch == '-') *ch = '_'; + priv->unique_name, NULL); priv->enabled = g_key_file_get_boolean (priv->keyfile, priv->unique_name, @@ -1378,6 +1394,9 @@ mcd_account_init (McdAccount *account) /* add the interface properties */ dbusprop_add_interface (TP_SVC_DBUS_PROPERTIES (account), MC_IFACE_ACCOUNT, account_properties); + dbusprop_add_interface (TP_SVC_DBUS_PROPERTIES (account), + MC_IFACE_ACCOUNT_INTERFACE_COMPAT, + _mcd_account_compat_get_properties()); priv->conn_status = TP_CONNECTION_STATUS_DISCONNECTED; } @@ -1676,6 +1695,15 @@ mcd_account_set_normalized_name (McdAccount *account, const gchar *name) mcd_account_manager_write_conf (priv->keyfile); } +gchar * +mcd_account_get_normalized_name (McdAccount *account) +{ + McdAccountPrivate *priv = account->priv; + + return g_key_file_get_string (priv->keyfile, priv->unique_name, + MC_ACCOUNTS_KEY_NORMALIZED_NAME, NULL); +} + void mcd_account_set_avatar_token (McdAccount *account, const gchar *token) { @@ -1755,16 +1783,13 @@ mcd_account_get_avatar (McdAccount *account, GArray **avatar, gchar **mime_type) { McdAccountPrivate *priv = MCD_ACCOUNT_PRIV (account); - gchar *data_dir, *filename; + gchar *filename; *mime_type = g_key_file_get_string (priv->keyfile, priv->unique_name, MC_ACCOUNTS_KEY_AVATAR_MIME, NULL); if (avatar) *avatar = NULL; - data_dir = get_account_data_path (priv); - g_debug("data dir: %s", data_dir); - filename = g_build_filename (data_dir, MC_AVATAR_FILENAME, NULL); - g_free (data_dir); + filename = mcd_account_get_avatar_filename (account); if (filename && g_file_test (filename, G_FILE_TEST_EXISTS)) { @@ -1915,10 +1940,14 @@ mcd_account_check_validity (McdAccount *account) valid = mcd_account_check_parameters (account); if (valid != priv->valid) { + GValue value = { 0 }; g_debug ("Account validity changed (old: %d, new: %d)", priv->valid, valid); priv->valid = valid; g_signal_emit (account, signals[VALIDITY_CHANGED], 0, valid); + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, valid); + mcd_account_changed_property (account, "Valid", &value); } return valid; } @@ -2030,3 +2059,23 @@ mcd_account_request_channel_nmc4 (McdAccount *account, error); } +GKeyFile * +mcd_account_get_keyfile (McdAccount *account) +{ + McdAccountPrivate *priv = MCD_ACCOUNT_PRIV (account); + return priv->keyfile; +} + +/* this is public because of mcd-account-compat */ +gchar * +mcd_account_get_avatar_filename (McdAccount *account) +{ + McdAccountPrivate *priv = account->priv; + gchar *data_dir, *filename; + + data_dir = get_account_data_path (priv); + g_debug("data dir: %s", data_dir); + filename = g_build_filename (data_dir, MC_AVATAR_FILENAME, NULL); + g_free (data_dir); + return filename; +} diff --git a/src/mcd-account.h b/src/mcd-account.h index 90c06532..5fcde941 100644 --- a/src/mcd-account.h +++ b/src/mcd-account.h @@ -64,6 +64,8 @@ gboolean mcd_account_delete (McdAccount *account, GError **error); const gchar *mcd_account_get_unique_name (McdAccount *account); const gchar *mcd_account_get_object_path (McdAccount *account); +GKeyFile *mcd_account_get_keyfile (McdAccount *account); + gboolean mcd_account_is_valid (McdAccount *account); gboolean mcd_account_check_validity (McdAccount *account); @@ -91,6 +93,7 @@ void mcd_account_get_requested_presence (McdAccount *account, const gchar **message); void mcd_account_set_normalized_name (McdAccount *account, const gchar *name); +gchar *mcd_account_get_normalized_name (McdAccount *account); gboolean mcd_account_set_avatar (McdAccount *account, const GArray *avatar, const gchar *mime_type, const gchar *token, @@ -115,4 +118,7 @@ McdConnection *mcd_account_get_connection (McdAccount *account); gboolean mcd_account_request_channel_nmc4 (McdAccount *account, const struct mcd_channel_request *req, GError **error); + +gchar *mcd_account_get_avatar_filename (McdAccount *account); + #endif diff --git a/src/mcd-master.c b/src/mcd-master.c index 848c471c..761cf648 100644 --- a/src/mcd-master.c +++ b/src/mcd-master.c @@ -867,15 +867,14 @@ mcd_master_get_account_for_connection (McdMaster *master, GError **error) { McdConnection *connection; + McdAccount *account; connection = mcd_master_get_connection (master, object_path, error); - if (connection) + if (connection && + (account = mcd_connection_get_account (connection))) { - McAccount *account; - - g_object_get (G_OBJECT (connection), "account", &account, NULL); - *ret_unique_name = g_strdup (mc_account_get_unique_name (account)); - g_object_unref (G_OBJECT (account)); + + *ret_unique_name = g_strdup (mcd_account_get_unique_name (account)); return TRUE; } return FALSE; diff --git a/src/mcd-presence-frame.c b/src/mcd-presence-frame.c index 866428e8..d49abf55 100644 --- a/src/mcd-presence-frame.c +++ b/src/mcd-presence-frame.c @@ -603,9 +603,13 @@ add_account (gpointer key, gpointer value, gpointer userdata) static void on_account_validity_changed (McdAccountManager *account_manager, - McdAccount *account, gboolean valid, + const gchar *object_path, gboolean valid, McdPresenceFrame *presence_frame) { + McdAccount *account; + + account = mcd_account_manager_lookup_account_by_path (account_manager, + object_path); if (valid) mcd_presence_frame_add_account (presence_frame, account); else @@ -630,3 +634,10 @@ mcd_presence_frame_set_account_manager (McdPresenceFrame *presence_frame, presence_frame); } +GList * +mcd_presence_frame_get_accounts (McdPresenceFrame *presence_frame) +{ + McdPresenceFramePrivate *priv = MCD_PRESENCE_FRAME_PRIV (presence_frame); + return priv->accounts; +} + diff --git a/src/mcd-presence-frame.h b/src/mcd-presence-frame.h index bcbe627c..707375c5 100644 --- a/src/mcd-presence-frame.h +++ b/src/mcd-presence-frame.h @@ -102,6 +102,7 @@ gboolean mcd_presence_frame_is_stable (McdPresenceFrame *presence_frame); void mcd_presence_frame_set_account_manager (McdPresenceFrame *presence_frame, McdAccountManager *account_manager); +GList *mcd_presence_frame_get_accounts (McdPresenceFrame *presence_frame); G_END_DECLS #endif /* MCD_PRESENCE_FRAME_H */ diff --git a/src/mcd-service.c b/src/mcd-service.c index d33a5019..a784b628 100644 --- a/src/mcd-service.c +++ b/src/mcd-service.c @@ -308,7 +308,6 @@ mcd_service_get_current_status(GObject *obj, McPresence *requested_presence, GPtrArray **accounts, GError **error) { -#if 0 McdServicePrivate *priv = MCD_OBJECT_PRIV (obj); GList *account_list, *account_node; GType type; @@ -320,23 +319,22 @@ mcd_service_get_current_status(GObject *obj, type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID); - account_list = mc_accounts_list_by_enabled (TRUE); + account_list = mcd_presence_frame_get_accounts (priv->presence_frame); for (account_node = account_list; account_node != NULL; account_node = g_list_next (account_node)) { - McAccount *account = account_node->data; + McdAccount *account = account_node->data; GValue account_data = { 0, }; - const gchar *name; + const gchar *name, *p_status, *p_message; TpConnectionStatus status; TpConnectionStatusReason reason; - McPresence presence; + TpConnectionPresenceType presence; - name = mc_account_get_unique_name (account); + name = mcd_account_get_unique_name (account); + mcd_account_get_current_presence (account, &presence, + &p_status, &p_message); status = mcd_presence_frame_get_account_status (priv->presence_frame, account); - presence = - mcd_presence_frame_get_account_presence (priv->presence_frame, - account); reason = mcd_presence_frame_get_account_status_reason (priv->presence_frame, account); @@ -353,12 +351,7 @@ mcd_service_get_current_status(GObject *obj, g_ptr_array_add (*accounts, g_value_get_boxed (&account_data)); } - mc_accounts_list_free (account_list); return TRUE; -#else - g_warning ("%s not implemented", G_STRFUNC); - return FALSE; -#endif } static void diff --git a/tools/Makefile.am b/tools/Makefile.am index 1e9fe2ed..c6051d58 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -3,6 +3,7 @@ EXTRA_DIST = \ c-interfaces-generator.xsl \ doc-generator.xsl \ glib-client-gen.py \ + glib-blocking-client-gen.py \ glib-client-marshaller-gen.py \ glib-interfaces-generator.xsl \ glib-interfaces-body-generator.xsl \ diff --git a/tools/glib-blocking-client-gen.py b/tools/glib-blocking-client-gen.py new file mode 100644 index 00000000..c20dcd4a --- /dev/null +++ b/tools/glib-blocking-client-gen.py @@ -0,0 +1,1014 @@ +#!/usr/bin/python + +# glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool" +# +# Generate GLib client wrappers from the Telepathy specification. +# The master copy of this program is in the telepathy-glib repository - +# please make any changes there. +# +# Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/> +# +# 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import sys +import os.path +import xml.dom.minidom +from getopt import gnu_getopt + +from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ + camelcase_to_lower, get_docstring + + +NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + +class Generator(object): + + def __init__(self, dom, prefix, basename, opts): + self.dom = dom + self.__header = [] + self.__body = [] + + self.prefix_lc = prefix.lower() + self.prefix_uc = prefix.upper() + self.prefix_mc = prefix.replace('_', '') + self.basename = basename + self.group = opts.get('--group', None) + self.iface_quark_prefix = opts.get('--iface-quark-prefix', None) + self.proxy_cls = opts.get('--subclass', 'TpProxy') + ' *' + self.proxy_arg = opts.get('--subclass', 'void') + ' *' + self.proxy_assert = opts.get('--subclass-assert', 'TP_IS_PROXY') + self.proxy_doc = ('A #%s or subclass' + % opts.get('--subclass', 'TpProxy')) + if self.proxy_arg == 'void *': + self.proxy_arg = 'gpointer ' + + def h(self, s): + self.__header.append(s) + + def b(self, s): + self.__body.append(s) + + def get_iface_quark(self): + assert self.iface_dbus is not None + assert self.iface_uc is not None + if self.iface_quark_prefix is None: + return 'g_quark_from_static_string (\"%s\")' % self.iface_dbus + else: + return '%s_%s' % (self.iface_quark_prefix, self.iface_uc) + + def do_signal(self, iface, signal): + iface_lc = iface.lower() + + member = signal.getAttribute('name') + member_lc = camelcase_to_lower(member) + member_uc = member_lc.upper() + + arg_count = 0 + args = [] + out_args = [] + + for arg in signal.getElementsByTagName('arg'): + name = arg.getAttribute('name') + type = arg.getAttribute('type') + tp_type = arg.getAttribute('tp:type') + + if not name: + name = 'arg%u' % arg_count + arg_count += 1 + else: + name = 'arg_%s' % name + + info = type_to_gtype(type) + args.append((name, info, tp_type, arg)) + + callback_name = ('%s_%s_signal_callback_%s' + % (self.prefix_lc, iface_lc, member_lc)) + collect_name = ('_%s_%s_collect_args_of_%s' + % (self.prefix_lc, iface_lc, member_lc)) + invoke_name = ('_%s_%s_invoke_callback_for_%s' + % (self.prefix_lc, iface_lc, member_lc)) + + # Example: + # + # typedef void (*tp_cli_connection_signal_callback_new_channel) + # (TpConnection *proxy, const gchar *arg_object_path, + # const gchar *arg_channel_type, guint arg_handle_type, + # guint arg_handle, gboolean arg_suppress_handler, + # gpointer user_data, GObject *weak_object); + + self.b('/**') + self.b(' * %s:' % callback_name) + self.b(' * @proxy: The proxy on which %s_%s_connect_to_%s ()' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * was called') + + for arg in args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: <![CDATA[%s]]>' % (name, + get_docstring(elt) or '(Undocumented)')) + + self.b(' * @user_data: User-supplied data') + self.b(' * @weak_object: User-supplied weakly referenced object') + self.b(' *') + self.b(' * Represents the signature of a callback for the signal %s.' + % member) + self.b(' */') + self.h('typedef void (*%s) (%sproxy,' + % (callback_name, self.proxy_cls)) + + for arg in args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + + self.h(' gpointer user_data, GObject *weak_object);') + + if args: + self.b('static void') + self.b('%s (DBusGProxy *proxy,' % collect_name) + + for arg in args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s%s%s,' % (const, ctype, name)) + + self.b(' TpProxySignalConnection *sc)') + self.b('{') + self.b(' GValueArray *args = g_value_array_new (%d);' % len(args)) + self.b(' GValue blank = { 0 };') + self.b(' guint i;') + self.b('') + self.b(' g_value_init (&blank, G_TYPE_INT);') + self.b('') + self.b(' for (i = 0; i < %d; i++)' % len(args)) + self.b(' g_value_array_append (args, &blank);') + self.b('') + + for i, arg in enumerate(args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' g_value_unset (args->values + %d);' % i) + self.b(' g_value_init (args->values + %d, %s);' % (i, gtype)) + + if gtype == 'G_TYPE_STRING': + self.b(' g_value_set_string (args->values + %d, %s);' + % (i, name)) + elif marshaller == 'BOXED': + self.b(' g_value_set_boxed (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UCHAR': + self.b(' g_value_set_uchar (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_BOOLEAN': + self.b(' g_value_set_boolean (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_INT': + self.b(' g_value_set_int (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UINT': + self.b(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_INT64': + self.b(' g_value_set_int (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UINT64': + self.b(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_DOUBLE': + self.b(' g_value_set_double (args->values + %d, %s);' + % (i, name)) + else: + assert False, ("Don't know how to put %s in a GValue" + % gtype) + self.b('') + + self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);') + self.b('}') + + self.b('static void') + self.b('%s (TpProxy *tpproxy,' % invoke_name) + self.b(' GError *error,') + self.b(' GValueArray *args,') + self.b(' GCallback generic_callback,') + self.b(' gpointer user_data,') + self.b(' GObject *weak_object)') + self.b('{') + self.b(' %s callback =' % callback_name) + self.b(' (%s) generic_callback;' % callback_name) + self.b('') + self.b(' if (callback != NULL)') + self.b(' callback (g_object_ref (tpproxy),') + + # FIXME: factor out into a function + for i, arg in enumerate(args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + if marshaller == 'BOXED': + self.b(' g_value_get_boxed (args->values + %d),' % i) + elif gtype == 'G_TYPE_STRING': + self.b(' g_value_get_string (args->values + %d),' % i) + elif gtype == 'G_TYPE_UCHAR': + self.b(' g_value_get_uchar (args->values + %d),' % i) + elif gtype == 'G_TYPE_BOOLEAN': + self.b(' g_value_get_boolean (args->values + %d),' % i) + elif gtype == 'G_TYPE_UINT': + self.b(' g_value_get_uint (args->values + %d),' % i) + elif gtype == 'G_TYPE_INT': + self.b(' g_value_get_int (args->values + %d),' % i) + elif gtype == 'G_TYPE_UINT64': + self.b(' g_value_get_uint64 (args->values + %d),' % i) + elif gtype == 'G_TYPE_INT64': + self.b(' g_value_get_int64 (args->values + %d),' % i) + elif gtype == 'G_TYPE_DOUBLE': + self.b(' g_value_get_double (args->values + %d),' % i) + else: + assert False, "Don't know how to get %s from a GValue" % gtype + + self.b(' user_data,') + self.b(' weak_object);') + self.b('') + + if len(args) > 0: + self.b(' g_value_array_free (args);') + else: + self.b(' if (args != NULL)') + self.b(' g_value_array_free (args);') + self.b('') + + self.b(' g_object_unref (tpproxy);') + self.b('}') + + # Example: + # + # TpProxySignalConnection * + # tp_cli_connection_connect_to_new_channel + # (TpConnection *proxy, + # tp_cli_connection_signal_callback_new_channel callback, + # gpointer user_data, + # GDestroyNotify destroy); + # + # destroy is invoked when the signal becomes disconnected. This + # is either because the signal has been disconnected explicitly + # by the user, because the TpProxy has become invalid and + # emitted the 'invalidated' signal, or because the weakly referenced + # object has gone away. + + self.b('/**') + self.b(' * %s_%s_connect_to_%s:' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: %s' % self.proxy_doc) + self.b(' * @callback: Callback to be called when the signal is') + self.b(' * received') + self.b(' * @user_data: User-supplied data for the callback') + self.b(' * @destroy: Destructor for the user-supplied data, which') + self.b(' * will be called when this signal is disconnected, or') + self.b(' * before this function returns %NULL') + self.b(' * @weak_object: A #GObject which will be weakly referenced; ') + self.b(' * if it is destroyed, this callback will automatically be') + self.b(' * disconnected') + self.b(' * @error: If not %NULL, used to raise an error if %NULL is') + self.b(' * returned') + self.b(' *') + self.b(' * Connect a handler to the signal %s.' % member) + self.b(' *') + self.b(' * <![CDATA[%s]]>' + % (get_docstring(signal) or '(Undocumented)')) + self.b(' *') + self.b(' * Returns: a #TpProxySignalConnection containing all of the') + self.b(' * above, which can be used to disconnect the signal; or') + self.b(' * %NULL if the proxy does not have the desired interface') + self.b(' * or has become invalid.') + self.b(' */') + self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h(' %s callback,' % callback_name) + self.h(' gpointer user_data,') + self.h(' GDestroyNotify destroy,') + self.h(' GObject *weak_object,') + self.h(' GError **error);') + + self.b('TpProxySignalConnection *') + self.b('%s_%s_connect_to_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' %s callback,' % callback_name) + self.b(' gpointer user_data,') + self.b(' GDestroyNotify destroy,') + self.b(' GObject *weak_object,') + self.b(' GError **error)') + self.b('{') + self.b(' GType expected_types[%d] = {' % (len(args) + 1)) + + for arg in args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s,' % gtype) + + self.b(' G_TYPE_INVALID };') + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), NULL);' + % self.proxy_assert) + self.b(' g_return_val_if_fail (callback != NULL, NULL);') + self.b('') + self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,') + self.b(' %s, \"%s\",' % (self.get_iface_quark(), member)) + self.b(' expected_types,') + + if args: + self.b(' G_CALLBACK (%s),' % collect_name) + else: + self.b(' NULL, /* no args => no collector function */') + + self.b(' %s,' % invoke_name) + self.b(' G_CALLBACK (callback), user_data, destroy,') + self.b(' weak_object, error);') + self.b('}') + self.b('') + + self.h('') + + def do_method(self, iface, method): + iface_lc = iface.lower() + + member = method.getAttribute('name') + member_lc = camelcase_to_lower(member) + member_uc = member_lc.upper() + + in_count = 0 + ret_count = 0 + in_args = [] + out_args = [] + + for arg in method.getElementsByTagName('arg'): + name = arg.getAttribute('name') + direction = arg.getAttribute('direction') + type = arg.getAttribute('type') + tp_type = arg.getAttribute('tp:type') + + if direction != 'out': + if not name: + name = 'in%u' % in_count + in_count += 1 + else: + name = 'in_%s' % name + else: + if not name: + name = 'out%u' % ret_count + ret_count += 1 + else: + name = 'out_%s' % name + + info = type_to_gtype(type) + if direction != 'out': + in_args.append((name, info, tp_type, arg)) + else: + out_args.append((name, info, tp_type, arg)) + + # Async reply callback type + + # Example: + # void (*tp_cli_properties_interface_callback_for_get_properties) + # (TpProxy *proxy, + # const GPtrArray *out0, + # const GError *error, + # gpointer user_data, + # GObject *weak_object); + + self.b('/**') + self.b(' * %s_%s_callback_for_%s:' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: the proxy on which the call was made') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to return an \'out\' argument if @error is ' + '%%NULL: <![CDATA[%s]]>' + % (name, get_docstring(elt) or '(Undocumented)')) + + self.b(' * @error: %NULL on success, or an error on failure') + self.b(' * @user_data: user-supplied data') + self.b(' * @weak_object: user-supplied object') + self.b(' *') + self.b(' * Signature of the callback called when a %s method call' + % member) + self.b(' * succeeds or fails.') + self.b(' */') + + callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc, + member_lc) + + self.h('typedef void (*%s) (%sproxy,' + % (callback_name, self.proxy_cls)) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + + self.h(' const GError *error, gpointer user_data,') + self.h(' GObject *weak_object);') + self.h('') + + # Async callback implementation + + invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc, + iface_lc, + member_lc) + + collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc, + iface_lc, + member_lc) + + # The callback called by dbus-glib; this ends the call and collects + # the results into a GValueArray. + self.b('static void') + self.b('%s (DBusGProxy *proxy,' % collect_callback) + self.b(' DBusGProxyCall *call,') + self.b(' gpointer user_data)') + self.b('{') + self.b(' GError *error = NULL;') + + if len(out_args) > 0: + self.b(' GValueArray *args;') + self.b(' GValue blank = { 0 };') + self.b(' guint i;') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s%s;' % (ctype, name)) + + self.b('') + self.b(' dbus_g_proxy_end_call (proxy, call, &error,') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s, &%s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID);') + + if len(out_args) == 0: + self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,' + 'NULL);') + else: + self.b('') + self.b(' if (error != NULL)') + self.b(' {') + self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,') + self.b(' NULL);') + self.b(' return;') + self.b(' }') + self.b('') + self.b(' args = g_value_array_new (%d);' % len(out_args)) + self.b(' g_value_init (&blank, G_TYPE_INT);') + self.b('') + self.b(' for (i = 0; i < %d; i++)' % len(out_args)) + self.b(' g_value_array_append (args, &blank);') + + for i, arg in enumerate(out_args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b('') + self.b(' g_value_unset (args->values + %d);' % i) + self.b(' g_value_init (args->values + %d, %s);' % (i, gtype)) + + if gtype == 'G_TYPE_STRING': + self.b(' g_value_take_string (args->values + %d, %s);' + % (i, name)) + elif marshaller == 'BOXED': + self.b(' g_value_take_boxed (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UCHAR': + self.b(' g_value_set_uchar (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_BOOLEAN': + self.b(' g_value_set_boolean (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_INT': + self.b(' g_value_set_int (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UINT': + self.b(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_INT64': + self.b(' g_value_set_int (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_UINT64': + self.b(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) + elif gtype == 'G_TYPE_DOUBLE': + self.b(' g_value_set_double (args->values + %d, %s);' + % (i, name)) + else: + assert False, ("Don't know how to put %s in a GValue" + % gtype) + + self.b(' tp_proxy_pending_call_v0_take_results (user_data, ' + 'NULL, args);') + + self.b('}') + + self.b('static void') + self.b('%s (TpProxy *self,' % invoke_callback) + self.b(' GError *error,') + self.b(' GValueArray *args,') + self.b(' GCallback generic_callback,') + self.b(' gpointer user_data,') + self.b(' GObject *weak_object)') + self.b('{') + self.b(' %s callback = (%s) generic_callback;' + % (callback_name, callback_name)) + self.b('') + self.b(' if (error != NULL)') + self.b(' {') + self.b(' callback ((%s) self,' % self.proxy_cls) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + if marshaller == 'BOXED' or pointer: + self.b(' NULL,') + elif gtype == 'G_TYPE_DOUBLE': + self.b(' 0.0,') + else: + self.b(' 0,') + + self.b(' error, user_data, weak_object);') + self.b(' g_error_free (error);') + self.b(' return;') + self.b(' }') + + self.b(' callback ((%s) self,' % self.proxy_cls) + + # FIXME: factor out into a function + for i, arg in enumerate(out_args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + if marshaller == 'BOXED': + self.b(' g_value_get_boxed (args->values + %d),' % i) + elif gtype == 'G_TYPE_STRING': + self.b(' g_value_get_string (args->values + %d),' % i) + elif gtype == 'G_TYPE_UCHAR': + self.b(' g_value_get_uchar (args->values + %d),' % i) + elif gtype == 'G_TYPE_BOOLEAN': + self.b(' g_value_get_boolean (args->values + %d),' % i) + elif gtype == 'G_TYPE_UINT': + self.b(' g_value_get_uint (args->values + %d),' % i) + elif gtype == 'G_TYPE_INT': + self.b(' g_value_get_int (args->values + %d),' % i) + elif gtype == 'G_TYPE_UINT64': + self.b(' g_value_get_uint64 (args->values + %d),' % i) + elif gtype == 'G_TYPE_INT64': + self.b(' g_value_get_int64 (args->values + %d),' % i) + elif gtype == 'G_TYPE_DOUBLE': + self.b(' g_value_get_double (args->values + %d),' % i) + else: + assert False, "Don't know how to get %s from a GValue" % gtype + + self.b(' error, user_data, weak_object);') + self.b('') + + if len(out_args) > 0: + self.b(' g_value_array_free (args);') + else: + self.b(' if (args != NULL)') + self.b(' g_value_array_free (args);') + + self.b('}') + self.b('') + + # Async stub + + # Example: + # TpProxyPendingCall * + # tp_cli_properties_interface_call_get_properties + # (gpointer proxy, + # gint timeout_ms, + # const GArray *in_properties, + # tp_cli_properties_interface_callback_for_get_properties callback, + # gpointer user_data, + # GDestroyNotify *destructor); + + self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h(' gint timeout_ms,') + + self.b('/**') + self.b(' * %s_%s_call_%s:' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: the #TpProxy') + self.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the') + self.b(' * default') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>' + % (name, get_docstring(elt) or '(Undocumented)')) + + self.b(' * @callback: called when the method call succeeds or fails') + self.b(' * @user_data: user-supplied data passed to the callback') + self.b(' * @destroy: called with the user_data as argument, after the') + self.b(' * call has succeeded, failed or been cancelled') + self.b(' * @weak_object: A #GObject which will be weakly referenced; ') + self.b(' * if it is destroyed, this callback will automatically be') + self.b(' * disconnected') + self.b(' *') + self.b(' * Start a %s method call.' % member) + self.b(' *') + self.b(' * <![CDATA[%s]]>' + % (get_docstring(method) or '(Undocumented)')) + self.b(' *') + self.b(' * Returns: a #TpProxyPendingCall representing the call in') + self.b(' * progress. It is borrowed from the object, and will become') + self.b(' * invalid when the callback is called, the call is') + self.b(' * cancelled or the #TpProxy becomes invalid.') + self.b(' */') + self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' gint timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + self.b(' %s%s%s,' % (const, ctype, name)) + + self.h(' %s callback,' % callback_name) + self.h(' gpointer user_data,') + self.h(' GDestroyNotify destroy,') + self.h(' GObject *weak_object);') + self.h('') + + self.b(' %s callback,' % callback_name) + self.b(' gpointer user_data,') + self.b(' GDestroyNotify destroy,') + self.b(' GObject *weak_object)') + self.b('{') + self.b(' GError *error = NULL;') + self.b(' GQuark interface = %s;' % self.get_iface_quark()) + self.b(' DBusGProxy *iface;') + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), NULL);' + % self.proxy_assert) + self.b('') + self.b(' iface = tp_proxy_borrow_interface_by_id (') + self.b(' (TpProxy *) proxy,') + self.b(' interface, &error);') + self.b('') + self.b(' if (iface == NULL)') + self.b(' {') + self.b(' if (callback != NULL)') + self.b(' callback (proxy,') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + if pointer: + self.b(' NULL,') + else: + self.b(' 0,') + + self.b(' error, user_data, weak_object);') + self.b(' g_error_free (error);') + self.b(' return NULL;') + self.b(' }') + self.b('') + self.b(' if (callback == NULL)') + self.b(' {') + self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member) + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID);') + self.b(' return NULL;') + self.b(' }') + self.b(' else') + self.b(' {') + self.b(' TpProxyPendingCall *data;') + self.b('') + self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') + self.b(' interface, "%s", iface,' % member) + self.b(' %s,' % invoke_callback) + self.b(' G_CALLBACK (callback), user_data, destroy,') + self.b(' weak_object, FALSE);') + self.b(' tp_proxy_pending_call_v0_take_pending_call (data,') + self.b(' dbus_g_proxy_begin_call_with_timeout (iface,') + self.b(' "%s",' % member) + self.b(' %s,' % collect_callback) + self.b(' data,') + self.b(' tp_proxy_pending_call_v0_completed,') + self.b(' timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID));') + self.b('') + self.b(' return data;') + self.b(' }') + self.b('}') + self.b('') + + # Non reentrant blocking calls + # Example: + # gboolean tp_cli_properties_interface_do_get_properties + # (gpointer proxy, + # gint timeout_ms, + # const GArray *in_properties, + # GPtrArray **out0, + # GError **error); + + self.h('gboolean %s_%s_do_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h(' gint timeout_ms,') + + self.b('/**') + self.b(' * %s_%s_do_%s:' % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: %s' % self.proxy_doc) + self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>' + % (name, get_docstring(elt) or '(Undocumented)')) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is ' + 'returned: <![CDATA[%s]]>' + % (name, get_docstring(elt) or '(Undocumented)')) + + self.b(' * @error: If not %NULL, used to return errors if %FALSE ') + self.b(' * is returned') + self.b(' *') + self.b(' * Call the method %s and block' % member) + self.b(' * until it returns.') + self.b(' *') + self.b(' * <![CDATA[%s]]>' + % (get_docstring(method) or '(Undocumented)')) + self.b(' *') + self.b(' * Returns: TRUE on success, FALSE and sets @error on error') + self.b(' */') + self.b('gboolean\n%s_%s_do_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' gint timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + self.b(' %s%s%s,' % (const, ctype, name)) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.h(' %s*%s,' % (ctype, name)) + self.b(' %s*%s,' % (ctype, name)) + + self.h(' GError **error);') + self.h('') + + self.b(' GError **error)') + self.b('{') + self.b(' DBusGProxy *iface;') + self.b(' GQuark interface = %s;' % self.get_iface_quark()) + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %si_%s;' % (ctype, name)) + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), FALSE);' + % self.proxy_assert) + self.b('') + self.b(' iface = tp_proxy_borrow_interface_by_id') + self.b(' ((TpProxy *) proxy, interface, error);') + self.b('') + self.b(' if (iface == NULL)') + self.b(' return FALSE;') + self.b('') + self.b(' if (dbus_g_proxy_call_with_timeout (iface,') + self.b(' "%s",' % member) + self.b(' timeout_ms,') + self.b(' error,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID,') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s, &i_%s,' % (gtype, name)) + self.b(' G_TYPE_INVALID))') + self.b(' {') + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' *%s = i_%s;' % (name, name)) + self.b(' return TRUE;') + self.b(' }') + self.b(' else') + self.b(' return FALSE;') + self.b('}') + self.b('') + + # leave a gap for the end of the method + self.b('') + self.h('') + + def do_signal_add(self, signal): + marshaller_items = [] + gtypes = [] + + for i in signal.getElementsByTagName('arg'): + name = i.getAttribute('name') + type = i.getAttribute('type') + info = type_to_gtype(type) + # type, GType, STRING, is a pointer + gtypes.append(info[1]) + + self.b(' dbus_g_proxy_add_signal (proxy, "%s",' + % signal.getAttribute('name')) + for gtype in gtypes: + self.b(' %s,' % gtype) + self.b(' G_TYPE_INVALID);') + + def do_interface(self, node): + ifaces = node.getElementsByTagName('interface') + assert len(ifaces) == 1 + iface = ifaces[0] + name = node.getAttribute('name').replace('/', '') + + self.iface = name + self.iface_lc = name.lower() + self.iface_uc = name.upper() + self.iface_mc = name.replace('_', '') + self.iface_dbus = iface.getAttribute('name') + + signals = node.getElementsByTagName('signal') + methods = node.getElementsByTagName('method') + + self.b('static inline void') + self.b('%s_add_signals_for_%s (DBusGProxy *proxy)' + % (self.prefix_lc, name.lower())) + self.b('{') + + for signal in signals: + self.do_signal_add(signal) + + self.b('}') + self.b('') + self.b('') + + for signal in signals: + self.do_signal(name, signal) + + for method in methods: + self.do_method(name, method) + + self.iface_dbus = None + + def __call__(self): + + self.h('G_BEGIN_DECLS') + self.h('') + + self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get') + self.b(' * confused by seeing function definitions, so mark it as: */') + self.b('/*<private_header>*/') + self.b('') + + nodes = self.dom.getElementsByTagName('node') + nodes.sort(cmp_by_name) + + for node in nodes: + self.do_interface(node) + + if self.group is not None: + + self.b('/*') + self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group)) + self.b(' * @self: the #TpProxy') + self.b(' * @quark: a quark whose string value is the interface') + self.b(' * name whose signals should be added') + self.b(' * @proxy: the D-Bus proxy to which to add the signals') + self.b(' * @unused: not used for anything') + self.b(' *') + self.b(' * Tell dbus-glib that @proxy has the signatures of all') + self.b(' * signals on the given interface, if it\'s one we') + self.b(' * support.') + self.b(' *') + self.b(' * This function should be used as a signal handler for') + self.b(' * #TpProxy::interface-added.') + self.b(' */') + self.b('static void') + self.b('%s_%s_add_signals (TpProxy *self,' + % (self.prefix_lc, self.group)) + self.b(' guint quark,') + self.b(' DBusGProxy *proxy,') + self.b(' gpointer unused)') + + self.b('{') + + for node in nodes: + iface = node.getElementsByTagName('interface')[0] + self.iface_dbus = iface.getAttribute('name') + name = node.getAttribute('name').replace('/', '').lower() + self.iface_uc = name.upper() + self.b(' if (quark == %s)' % self.get_iface_quark()) + self.b(' %s_add_signals_for_%s (proxy);' + % (self.prefix_lc, name)) + + self.b('}') + self.b('') + + self.h('G_END_DECLS') + self.h('') + + open(self.basename + '.h', 'w').write('\n'.join(self.__header)) + open(self.basename + '-body.h', 'w').write('\n'.join(self.__body)) + + +def types_to_gtypes(types): + return [type_to_gtype(t)[1] for t in types] + + +if __name__ == '__main__': + options, argv = gnu_getopt(sys.argv[1:], '', + ['group=', 'subclass=', 'subclass-assert=', + 'iface-quark-prefix=']) + + opts = {} + + for option, value in options: + opts[option] = value + + dom = xml.dom.minidom.parse(argv[0]) + + Generator(dom, argv[1], argv[2], opts)() diff --git a/xml/Account.xml b/xml/Account.xml index 303b9079..ddc09017 100644 --- a/xml/Account.xml +++ b/xml/Account.xml @@ -192,7 +192,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. </tp:docstring> </property> - <property name="enabled" type="b" access="readwrite"> + <property name="Enabled" type="b" access="readwrite"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>This property gives the users the possibility to prevent an account from being used; account editor UIs should let the user modify this diff --git a/xml/Account_Interface_Compat.xml b/xml/Account_Interface_Compat.xml new file mode 100644 index 00000000..af68a5b1 --- /dev/null +++ b/xml/Account_Interface_Compat.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" ?> +<node name="/Account_Interface_Compat" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright> + <tp:license xmlns="http://www.w3.org/1999/xhtml"> + <p>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.1 of the License, or (at your option) any later version.</p> + +<p>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.</p> + +<p>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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> + </tp:license> + <interface name="org.freedesktop.Telepathy.Account.Interface.Compat"> + <tp:requires interface="org.freedesktop.Telepathy.Account"/> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The Compat interface holds properties necessary for maintaining the + libmissioncontrol compatible layer.</p> + </tp:docstring> + + <property name="Profile" type="s" access="readwrite"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The name of the profile.</p> + </tp:docstring> + </property> + + <property name="AvatarFile" type="s" access="read"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The location of the avatar.</p> + </tp:docstring> + </property> + + <property name="SecondaryVCardFields" type="as" access="readwrite"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>List of secondary VCard fields.</p> + </tp:docstring> + </property> + + </interface> +</node> +<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/xml/Makefile.am b/xml/Makefile.am index 005b4ce8..965a272d 100644 --- a/xml/Makefile.am +++ b/xml/Makefile.am @@ -5,7 +5,9 @@ DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/Dbu SPECS = MissionControl.xml \ Account_Manager.xml \ - Account.xml + Account.xml \ + Account_Interface_Compat.xml + SPECS_GEN = ${SPECS:.xml=-gen.xml} diff --git a/xml/nmc5.xml b/xml/nmc5.xml index 062535f2..fc3d30c6 100644 --- a/xml/nmc5.xml +++ b/xml/nmc5.xml @@ -5,6 +5,7 @@ <tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright> <xi:include href="Account.xml"/> +<xi:include href="Account_Interface_Compat.xml"/> <xi:include href="Account_Manager.xml"/> </tp:spec> |