diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:18:05 +0800 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:35:05 +0800 |
commit | 2e6d8132394680ea42a3ebdc1daad33ff5e07b86 (patch) | |
tree | 0bf9179a649dad69089a44270fcf49514a9c80e4 /libempathy | |
parent | 7cfb268c7d96f929646c5eb093e6f07aa8b1abea (diff) | |
parent | d7f82b00ea09c62be272ed2d0c98e9120a722ca9 (diff) | |
download | gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.gz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.bz2 gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.lz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.xz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.zst gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.zip |
Merge branch 'mc5', fixes bug #590165
Diffstat (limited to 'libempathy')
31 files changed, 3425 insertions, 782 deletions
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 0250a63d8..5fe4a9df7 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -26,7 +26,7 @@ lib_LTLIBRARIES = libempathy.la libempathy_la_SOURCES = \ empathy-account.c \ - empathy-account-priv.h \ + empathy-account-settings.c \ empathy-account-manager.c \ empathy-chatroom.c \ empathy-chatroom-manager.c \ @@ -38,6 +38,7 @@ libempathy_la_SOURCES = \ empathy-contact-list.c \ empathy-contact-manager.c \ empathy-contact-monitor.c \ + empathy-connection-managers.c \ empathy-debug.c \ empathy-debugger.c \ empathy-dispatcher.c \ @@ -79,6 +80,7 @@ libempathy_la_LDFLAGS = \ -export-symbols-regex ^empathy_ libempathy_headers = \ + empathy-account-settings.h \ empathy-account.h \ empathy-account-manager.h \ empathy-chatroom.h \ @@ -91,6 +93,7 @@ libempathy_headers = \ empathy-contact-list.h \ empathy-contact-manager.h \ empathy-contact-monitor.h \ + empathy-connection-managers.h \ empathy-debug.h \ empathy-debugger.h \ empathy-dispatcher.h \ diff --git a/libempathy/empathy-account-manager.c b/libempathy/empathy-account-manager.c index fd8a21b1d..75de6f193 100644 --- a/libempathy/empathy-account-manager.c +++ b/libempathy/empathy-account-manager.c @@ -21,10 +21,14 @@ #include "config.h" -#include <libmissioncontrol/mc-account-monitor.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/account-manager.h> +#include <telepathy-glib/enums.h> +#include <telepathy-glib/defs.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-account-manager.h" -#include "empathy-account-priv.h" #include "empathy-marshal.h" #include "empathy-utils.h" @@ -33,15 +37,33 @@ #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager) -typedef struct { - McAccountMonitor *monitor; - MissionControl *mc; +#define MC5_BUS_NAME "org.freedesktop.Telepathy.MissionControl5" +typedef struct { /* (owned) unique name -> (reffed) EmpathyAccount */ GHashTable *accounts; int connected; int connecting; gboolean dispose_run; + gboolean ready; + TpAccountManager *tp_manager; + TpDBusDaemon *dbus; + + /* global presence */ + EmpathyAccount *global_account; + + TpConnectionPresenceType global_presence; + gchar *global_status; + gchar *global_status_message; + + /* requested global presence, could be different + * from the actual global one. + */ + TpConnectionPresenceType requested_presence; + gchar *requested_status; + gchar *requested_status_message; + + GHashTable *create_results; } EmpathyAccountManagerPriv; enum { @@ -51,38 +73,20 @@ enum { ACCOUNT_DISABLED, ACCOUNT_CHANGED, ACCOUNT_CONNECTION_CHANGED, - ACCOUNT_PRESENCE_CHANGED, + GLOBAL_PRESENCE_CHANGED, NEW_CONNECTION, LAST_SIGNAL }; +enum { + PROP_READY = 1, +}; + static guint signals[LAST_SIGNAL]; static EmpathyAccountManager *manager_singleton = NULL; G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT); -static TpConnectionPresenceType -mc_presence_to_tp_presence (McPresence presence) -{ - switch (presence) - { - case MC_PRESENCE_OFFLINE: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - case MC_PRESENCE_AVAILABLE: - return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE; - case MC_PRESENCE_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_AWAY; - case MC_PRESENCE_EXTENDED_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY; - case MC_PRESENCE_HIDDEN: - return TP_CONNECTION_PRESENCE_TYPE_HIDDEN; - case MC_PRESENCE_DO_NOT_DISTURB: - return TP_CONNECTION_PRESENCE_TYPE_BUSY; - default: - return TP_CONNECTION_PRESENCE_TYPE_UNSET; - } -} - static void emp_account_connection_cb (EmpathyAccount *account, GParamSpec *spec, @@ -98,6 +102,17 @@ emp_account_connection_cb (EmpathyAccount *account, } static void +emp_account_enabled_cb (EmpathyAccount *account, + GParamSpec *spec, + gpointer manager) +{ + if (empathy_account_is_enabled (account)) + g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account); + else + g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account); +} + +static void emp_account_status_changed_cb (EmpathyAccount *account, TpConnectionStatus old, TpConnectionStatus new, @@ -136,270 +151,333 @@ emp_account_status_changed_cb (EmpathyAccount *account, } static void -emp_account_presence_changed_cb (EmpathyAccount *account, - TpConnectionPresenceType old, - TpConnectionPresenceType new, - gpointer user_data) -{ - EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); - g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0, - account, new, old); -} - -static EmpathyAccount * -create_account (EmpathyAccountManager *manager, - const gchar *account_name, - McAccount *mc_account) +emp_account_manager_update_global_presence (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - TpConnectionStatus status; - TpConnectionPresenceType presence; - McPresence mc_presence; - TpConnection *connection; - GError *error = NULL; - - if ((account = g_hash_table_lookup (priv->accounts, account_name)) != NULL) - return account; - - account = _empathy_account_new (mc_account); - g_hash_table_insert (priv->accounts, g_strdup (account_name), - account); + TpConnectionPresenceType presence = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; + EmpathyAccount *account = NULL; + GHashTableIter iter; + gpointer value; - _empathy_account_set_enabled (account, - mc_account_is_enabled (mc_account)); + /* Make the global presence is equal to the presence of the account with the + * highest availability */ - g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account); + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + EmpathyAccount *a = EMPATHY_ACCOUNT (value); + TpConnectionPresenceType p; - g_signal_connect (account, "notify::connection", - G_CALLBACK (emp_account_connection_cb), manager); + g_object_get (a, "presence", &p, NULL); - connection = mission_control_get_tpconnection (priv->mc, - mc_account, NULL); - _empathy_account_set_connection (account, connection); + if (tp_connection_presence_type_cmp_availability (p, presence) > 0) + { + account = a; + presence = p; + } + } - status = mission_control_get_connection_status (priv->mc, - mc_account, &error); + priv->global_account = account; + g_free (priv->global_status); + g_free (priv->global_status_message); - if (error != NULL) + if (account == NULL) { - status = TP_CONNECTION_STATUS_DISCONNECTED; - g_clear_error (&error); + priv->global_presence = presence; + priv->global_status = NULL; + priv->global_status_message = NULL; + return; } - mc_presence = mission_control_get_presence_actual (priv->mc, &error); - if (error != NULL) - { - presence = TP_CONNECTION_PRESENCE_TYPE_UNSET; - g_clear_error (&error); - } - else + g_object_get (account, + "presence", &priv->global_presence, + "status", &priv->global_status, + "status-message", &priv->global_status_message, + NULL); + + DEBUG ("Updated global presence to: %s (%d) \"%s\"", + priv->global_status, priv->global_presence, priv->global_status_message); +} + +static void +emp_account_presence_changed_cb (EmpathyAccount *account, + TpConnectionPresenceType presence, + const gchar *status, + const gchar *status_message, + gpointer user_data) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (tp_connection_presence_type_cmp_availability (presence, + priv->global_presence) > 0) { - presence = mc_presence_to_tp_presence (mc_presence); - } + priv->global_account = account; - g_signal_connect (account, "status-changed", - G_CALLBACK (emp_account_status_changed_cb), manager); + priv->global_presence = presence; - g_signal_connect (account, "presence-changed", - G_CALLBACK (emp_account_presence_changed_cb), manager); + g_free (priv->global_status); + priv->global_status = g_strdup (status); - _empathy_account_set_status (account, status, - TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, - presence); + g_free (priv->global_status_message); + priv->global_status_message = g_strdup (status_message); - return account; + goto signal; + } + else if (priv->global_account == account) + { + emp_account_manager_update_global_presence (manager); + goto signal; + } + + return; +signal: + g_signal_emit (manager, signals[GLOBAL_PRESENCE_CHANGED], 0, + priv->global_presence, priv->global_status, priv->global_status_message); } static void -account_created_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +emp_account_removed_cb (EmpathyAccount *account, gpointer user_data) { - McAccount *mc_account = mc_account_lookup (account_name); + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - if (mc_account != NULL) - create_account (manager, account_name, mc_account); + g_object_ref (account); + g_hash_table_remove (priv->accounts, + empathy_account_get_unique_name (account)); + + g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account); + g_object_unref (account); } static void -account_deleted_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +empathy_account_manager_check_ready (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; + GHashTableIter iter; + gpointer value; - account = g_hash_table_lookup (priv->accounts, account_name); + if (priv->ready) + return; - if (account) + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) { - g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account); - g_hash_table_remove (priv->accounts, account_name); + EmpathyAccount *account = EMPATHY_ACCOUNT (value); + gboolean ready; + + g_object_get (account, "ready", &ready, NULL); + + if (!ready) + return; } + + /* Rerequest global presence on the initial set of accounts for cases where a + * global presence was requested before the manager was ready */ + if (priv->requested_presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) + empathy_account_manager_request_global_presence (manager, + priv->requested_presence, + priv->requested_status, + priv->requested_status_message); + + priv->ready = TRUE; + g_object_notify (G_OBJECT (manager), "ready"); } static void -account_changed_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +account_manager_account_ready_cb (GObject *obj, + GParamSpec *spec, + gpointer user_data) { + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; + EmpathyAccount *account = EMPATHY_ACCOUNT (obj); + GSimpleAsyncResult *result; + gboolean ready; - account = g_hash_table_lookup (priv->accounts, account_name); + g_object_get (account, "ready", &ready, NULL); - if (account != NULL) - g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account); + if (!ready) + return; + + /* see if there's any pending callbacks for this account */ + result = g_hash_table_lookup (priv->create_results, account); + if (result != NULL) + { + g_simple_async_result_set_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (result), account, NULL); + + g_simple_async_result_complete (result); + + g_hash_table_remove (priv->create_results, account); + g_object_unref (result); + } + + g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account); + + g_signal_connect (account, "notify::connection", + G_CALLBACK (emp_account_connection_cb), manager); + + g_signal_connect (account, "notify::enabled", + G_CALLBACK (emp_account_enabled_cb), manager); + + g_signal_connect (account, "status-changed", + G_CALLBACK (emp_account_status_changed_cb), manager); + + g_signal_connect (account, "presence-changed", + G_CALLBACK (emp_account_presence_changed_cb), manager); + + g_signal_connect (account, "removed", + G_CALLBACK (emp_account_removed_cb), manager); + + empathy_account_manager_check_ready (manager); } -static void -account_disabled_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +EmpathyAccount * +empathy_account_manager_get_account (EmpathyAccountManager *manager, + const gchar *path) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - account = g_hash_table_lookup (priv->accounts, account_name); - - if (account) - { - _empathy_account_set_enabled (account, FALSE); - g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account); - } + return g_hash_table_lookup (priv->accounts, path); } -static void -account_enabled_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +EmpathyAccount * +empathy_account_manager_ensure_account (EmpathyAccountManager *manager, + const gchar *path) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); EmpathyAccount *account; - account = g_hash_table_lookup (priv->accounts, account_name); + account = g_hash_table_lookup (priv->accounts, path); + if (account != NULL) + return account; + + account = empathy_account_new (priv->dbus, path); + g_hash_table_insert (priv->accounts, g_strdup (path), account); - if (account) - { - _empathy_account_set_enabled (account, TRUE); - g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account); - } + g_signal_connect (account, "notify::ready", + G_CALLBACK (account_manager_account_ready_cb), manager); + + return account; } -typedef struct { - TpConnectionStatus status; - TpConnectionPresenceType presence; - TpConnectionStatusReason reason; - gchar *unique_name; - EmpathyAccountManager *manager; - McAccount *mc_account; -} ChangedSignalData; -static gboolean -account_status_changed_idle_cb (ChangedSignalData *signal_data) +static void +account_manager_got_all_cb (TpProxy *proxy, + GHashTable *properties, + const GError *error, + gpointer user_data, + GObject *weak_object) { - EmpathyAccount *account; - EmpathyAccountManager *manager = signal_data->manager; - EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + GPtrArray *accounts; + int i; - account = g_hash_table_lookup (priv->accounts, - signal_data->unique_name); + if (error != NULL) + { + DEBUG ("Failed to get account manager properties: %s", error->message); + return; + } - if (account) + accounts = tp_asv_get_boxed (properties, "ValidAccounts", + EMPATHY_ARRAY_TYPE_OBJECT); + + if (accounts != NULL) { - if (empathy_account_get_connection (account) == NULL) + for (i = 0; i < accounts->len; i++) { - TpConnection *connection; - - connection = mission_control_get_tpconnection (priv->mc, - signal_data->mc_account, NULL); + gchar *name = g_ptr_array_index (accounts, i); - if (connection != NULL) - { - _empathy_account_set_connection (account, connection); - g_object_unref (connection); - } + empathy_account_manager_ensure_account (manager, name); } - - _empathy_account_set_status (account, signal_data->status, - signal_data->reason, - signal_data->presence); } - g_object_unref (signal_data->manager); - g_object_unref (signal_data->mc_account); - g_free (signal_data->unique_name); - g_slice_free (ChangedSignalData, signal_data); - - return FALSE; + empathy_account_manager_check_ready (manager); } static void -account_status_changed_cb (MissionControl *mc, - TpConnectionStatus status, - McPresence presence, - TpConnectionStatusReason reason, - const gchar *unique_name, - EmpathyAccountManager *manager) +account_validity_changed_cb (TpAccountManager *proxy, + const gchar *path, + gboolean valid, + gpointer user_data, + GObject *weak_object) { - ChangedSignalData *data; + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + + if (!valid) + return; - DEBUG ("Status of account %s became " - "status: %d presence: %d reason: %d", unique_name, status, - presence, reason); + empathy_account_manager_ensure_account (manager, path); +} - data = g_slice_new0 (ChangedSignalData); - data->status = status; - data->presence = mc_presence_to_tp_presence (presence); - data->reason = reason; - data->unique_name = g_strdup (unique_name); - data->manager = g_object_ref (manager); - data->mc_account = mc_account_lookup (unique_name); +static void +account_manager_name_owner_cb (TpDBusDaemon *proxy, + const gchar *name, + const gchar *new_owner, + gpointer user_data) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - g_idle_add ((GSourceFunc) account_status_changed_idle_cb, data); + tp_dbus_daemon_cancel_name_owner_watch (proxy, name, + account_manager_name_owner_cb, user_data); + + priv->tp_manager = tp_account_manager_new (priv->dbus); + + tp_cli_account_manager_connect_to_account_validity_changed ( + priv->tp_manager, + account_validity_changed_cb, + NULL, + NULL, + G_OBJECT (manager), + NULL); + + tp_cli_dbus_properties_call_get_all (priv->tp_manager, -1, + TP_IFACE_ACCOUNT_MANAGER, + account_manager_got_all_cb, + NULL, + NULL, + G_OBJECT (manager)); } static void empathy_account_manager_init (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv; - GList *mc_accounts, *l; + TpProxy *mc5_proxy; priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv); manager->priv = priv; - priv->monitor = mc_account_monitor_new (); - priv->mc = empathy_mission_control_dup_singleton (); priv->connected = priv->connecting = 0; - priv->dispose_run = FALSE; + priv->global_presence = TP_CONNECTION_PRESENCE_TYPE_UNSET; priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); - mc_accounts = mc_accounts_list (); + priv->create_results = g_hash_table_new (g_direct_hash, g_direct_equal); + + priv->dbus = tp_dbus_daemon_dup (NULL); - for (l = mc_accounts; l; l = l->next) - account_created_cb (priv->monitor, - (char *) mc_account_get_unique_name (l->data), manager); + tp_dbus_daemon_watch_name_owner (priv->dbus, + TP_ACCOUNT_MANAGER_BUS_NAME, + account_manager_name_owner_cb, + manager, + NULL); - g_signal_connect (priv->monitor, "account-created", - G_CALLBACK (account_created_cb), manager); - g_signal_connect (priv->monitor, "account-deleted", - G_CALLBACK (account_deleted_cb), manager); - g_signal_connect (priv->monitor, "account-disabled", - G_CALLBACK (account_disabled_cb), manager); - g_signal_connect (priv->monitor, "account-enabled", - G_CALLBACK (account_enabled_cb), manager); - g_signal_connect (priv->monitor, "account-changed", - G_CALLBACK (account_changed_cb), manager); + /* trigger MC5 starting */ + mc5_proxy = g_object_new (TP_TYPE_PROXY, + "dbus-daemon", priv->dbus, + "dbus-connection", tp_proxy_get_dbus_connection (TP_PROXY (priv->dbus)), + "bus-name", MC5_BUS_NAME, + "object-path", "/", + NULL); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged", - G_CALLBACK (account_status_changed_cb), - manager, NULL); + tp_cli_dbus_peer_call_ping (mc5_proxy, -1, NULL, NULL, NULL, NULL); - mc_accounts_list_free (mc_accounts); + g_object_unref (mc5_proxy); } static void @@ -408,8 +486,15 @@ do_finalize (GObject *obj) EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + g_hash_table_destroy (priv->create_results); g_hash_table_destroy (priv->accounts); + g_free (priv->global_status); + g_free (priv->global_status_message); + + g_free (priv->requested_status); + g_free (priv->requested_status_message); + G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj); } @@ -418,37 +503,37 @@ do_dispose (GObject *obj) { EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GHashTableIter iter; + GSimpleAsyncResult *result; if (priv->dispose_run) return; priv->dispose_run = TRUE; - dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc), - "AccountStatusChanged", - G_CALLBACK (account_status_changed_cb), - obj); - - if (priv->monitor) + /* the manager is being destroyed while there are account creation + * processes pending; this should not happen, but emit the callbacks + * with an error anyway. + */ + g_hash_table_iter_init (&iter, priv->create_results); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &result)) { - g_signal_handlers_disconnect_by_func (priv->monitor, - account_created_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_deleted_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_disabled_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_enabled_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_changed_cb, obj); - g_object_unref (priv->monitor); - priv->monitor = NULL; + g_simple_async_result_set_error (result, G_IO_ERROR, + G_IO_ERROR_CANCELLED, "The account manager was disposed while " + "creating the account"); + g_simple_async_result_complete (result); + g_object_unref (result); } + g_hash_table_remove_all (priv->create_results); - if (priv->mc) - g_object_unref (priv->mc); + if (priv->dbus != NULL) + { + tp_dbus_daemon_cancel_name_owner_watch (priv->dbus, + TP_ACCOUNT_MANAGER_BUS_NAME, account_manager_name_owner_cb, manager); - g_hash_table_remove_all (priv->accounts); + g_object_unref (priv->dbus); + priv->dbus = NULL; + } G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj); } @@ -477,6 +562,26 @@ do_constructor (GType type, } static void +do_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (object); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + switch (prop_id) + { + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); @@ -484,6 +589,14 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) oclass->finalize = do_finalize; oclass->dispose = do_dispose; oclass->constructor = do_constructor; + oclass->get_property = do_get_property; + + g_object_class_install_property (oclass, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether the initial state dump from the account manager is finished", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); signals[ACCOUNT_CREATED] = g_signal_new ("account-created", @@ -548,17 +661,17 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) G_TYPE_UINT, /* actual connection */ G_TYPE_UINT); /* previous connection */ - signals[ACCOUNT_PRESENCE_CHANGED] = - g_signal_new ("account-presence-changed", + signals[GLOBAL_PRESENCE_CHANGED] = + g_signal_new ("global-presence-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_marshal_VOID__OBJECT_INT_INT, + _empathy_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, - 3, EMPATHY_TYPE_ACCOUNT, - G_TYPE_INT, /* actual presence */ - G_TYPE_INT); /* previous presence */ + 3, G_TYPE_UINT, /* Presence type */ + G_TYPE_STRING, /* status */ + G_TYPE_STRING); /* stauts message*/ signals[NEW_CONNECTION] = g_signal_new ("new-connection", @@ -581,14 +694,12 @@ empathy_account_manager_dup_singleton (void) return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL); } -EmpathyAccount * -empathy_account_manager_create (EmpathyAccountManager *manager, - McProfile *profile) +gboolean +empathy_account_manager_is_ready (EmpathyAccountManager *manager) { - McAccount *mc_account = mc_account_create (profile); - return g_object_ref (create_account (manager, - mc_account_get_unique_name (mc_account), - mc_account)); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + return priv->ready; } int @@ -636,8 +747,9 @@ empathy_account_manager_get_count (EmpathyAccountManager *manager) } EmpathyAccount * -empathy_account_manager_get_account (EmpathyAccountManager *manager, - TpConnection *connection) +empathy_account_manager_get_account_for_connection ( + EmpathyAccountManager *manager, + TpConnection *connection) { EmpathyAccountManagerPriv *priv; GHashTableIter iter; @@ -659,21 +771,6 @@ empathy_account_manager_get_account (EmpathyAccountManager *manager, return NULL; } -EmpathyAccount * -empathy_account_manager_lookup (EmpathyAccountManager *manager, - const gchar *unique_name) -{ - EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - - account = g_hash_table_lookup (priv->accounts, unique_name); - - if (account != NULL) - g_object_ref (account); - - return account; -} - GList * empathy_account_manager_dup_accounts (EmpathyAccountManager *manager) { @@ -726,8 +823,154 @@ empathy_account_manager_dup_connections (EmpathyAccountManager *manager) } void -empathy_account_manager_remove (EmpathyAccountManager *manager, - EmpathyAccount *account) +empathy_account_manager_request_global_presence ( + EmpathyAccountManager *manager, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GHashTableIter iter; + gpointer value; + + DEBUG ("request global presence, type: %d, status: %s, message: %s", + type, status, message); + + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (value); + gboolean ready; + + g_object_get (account, "ready", &ready, NULL); + + if (ready) + empathy_account_request_presence (account, type, status, message); + } + + /* save the requested global presence, to use it in case we create + * new accounts or some accounts become ready. + */ + priv->requested_presence = type; + + if (tp_strdiff (priv->requested_status, status)) + { + g_free (priv->requested_status); + priv->requested_status = g_strdup (status); + } + + if (tp_strdiff (priv->requested_status_message, message)) + { + g_free (priv->requested_status_message); + priv->requested_status_message = g_strdup (message); + } +} + +TpConnectionPresenceType +empathy_account_manager_get_requested_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (status != NULL) + *status = g_strdup (priv->requested_status); + if (message != NULL) + *message = g_strdup (priv->requested_status_message); + + return priv->requested_presence; +} + +TpConnectionPresenceType +empathy_account_manager_get_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (status != NULL) + *status = g_strdup (priv->global_status); + if (message != NULL) + *message = g_strdup (priv->global_status_message); + + return priv->global_presence; +} + +static void +empathy_account_manager_created_cb (TpAccountManager *proxy, + const gchar *account_path, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GSimpleAsyncResult *my_res = user_data; + EmpathyAccount *account; + + if (error != NULL) + { + g_simple_async_result_set_from_error (my_res, + (GError *) error); + g_simple_async_result_complete (my_res); + g_object_unref (my_res); + + return; + } + + account = empathy_account_manager_ensure_account (manager, account_path); + + g_hash_table_insert (priv->create_results, account, my_res); +} + +void +empathy_account_manager_create_account_async (EmpathyAccountManager *manager, + const gchar *connection_manager, + const gchar *protocol, + const gchar *display_name, + GHashTable *parameters, + GHashTable *properties, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GSimpleAsyncResult *res; + + res = g_simple_async_result_new + (G_OBJECT (manager), callback, user_data, + empathy_account_manager_create_account_finish); + + tp_cli_account_manager_call_create_account (priv->tp_manager, + -1, + connection_manager, + protocol, + display_name, + parameters, + properties, + empathy_account_manager_created_cb, + res, + NULL, + G_OBJECT (manager)); +} + +EmpathyAccount * +empathy_account_manager_create_account_finish ( + EmpathyAccountManager *manager, GAsyncResult *result, GError **error) { - mc_account_delete (_empathy_account_get_mc_account (account)); + EmpathyAccount *retval; + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return NULL; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (manager), empathy_account_manager_create_account_finish), NULL); + + retval = EMPATHY_ACCOUNT (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (result))); + + return retval; } + diff --git a/libempathy/empathy-account-manager.h b/libempathy/empathy-account-manager.h index b04571ff8..25adfdbeb 100644 --- a/libempathy/empathy-account-manager.h +++ b/libempathy/empathy-account-manager.h @@ -28,12 +28,17 @@ G_BEGIN_DECLS -#define EMPATHY_TYPE_ACCOUNT_MANAGER (empathy_account_manager_get_type ()) -#define EMPATHY_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManager)) -#define EMPATHY_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) -#define EMPATHY_IS_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_ACCOUNT_MANAGER)) -#define EMPATHY_IS_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_ACCOUNT_MANAGER)) -#define EMPATHY_ACCOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) +#define EMPATHY_TYPE_ACCOUNT_MANAGER (empathy_account_manager_get_type ()) +#define EMPATHY_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManager)) +#define EMPATHY_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) +#define EMPATHY_IS_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER)) +#define EMPATHY_IS_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ + EMPATHY_TYPE_ACCOUNT_MANAGER)) +#define EMPATHY_ACCOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) typedef struct _EmpathyAccountManager EmpathyAccountManager; typedef struct _EmpathyAccountManagerClass EmpathyAccountManagerClass; @@ -52,19 +57,22 @@ GType empathy_account_manager_get_type (void); /* public methods */ EmpathyAccountManager * empathy_account_manager_dup_singleton (void); -EmpathyAccount * empathy_account_manager_create - (EmpathyAccountManager *manager, - McProfile *profile); + +gboolean empathy_account_manager_is_ready (EmpathyAccountManager *manager); + int empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager); int empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager); int empathy_account_manager_get_count (EmpathyAccountManager *manager); -EmpathyAccount * empathy_account_manager_get_account +EmpathyAccount * empathy_account_manager_get_account_for_connection (EmpathyAccountManager *manager, TpConnection *connection); -EmpathyAccount * empathy_account_manager_lookup +EmpathyAccount * empathy_account_manager_ensure_account + (EmpathyAccountManager *manager, + const gchar *unique_name); +EmpathyAccount * empathy_account_manager_get_account (EmpathyAccountManager *manager, const gchar *unique_name); GList * empathy_account_manager_dup_accounts @@ -75,6 +83,31 @@ void empathy_account_manager_remove ( EmpathyAccountManager *manager, EmpathyAccount *account); +void empathy_account_manager_request_global_presence ( + EmpathyAccountManager *manager, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message); + +TpConnectionPresenceType empathy_account_manager_get_requested_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message); + +TpConnectionPresenceType empathy_account_manager_get_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message); + +void empathy_account_manager_create_account_async ( + EmpathyAccountManager *manager, const gchar *connection_manager, + const gchar *protocol, const gchar *display_name, + GHashTable *parameters, GHashTable *properties, + GAsyncReadyCallback callback, gpointer user_data); + +EmpathyAccount * empathy_account_manager_create_account_finish ( + EmpathyAccountManager *settings, GAsyncResult *result, GError **error); + G_END_DECLS #endif /* __EMPATHY_ACCOUNT_MANAGER_H__ */ diff --git a/libempathy/empathy-account-priv.h b/libempathy/empathy-account-priv.h deleted file mode 100644 index 8b656b4d8..000000000 --- a/libempathy/empathy-account-priv.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * empathy-account-priv.h - Private Header for EmpathyAccount - * Copyright (C) 2009 Collabora Ltd. - * @author Sjoerd Simons <sjoerd.simons@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 - */ - -#ifndef __EMPATHY_ACCOUNT_PRIV_H__ -#define __EMPATHY_ACCOUNT_PRIV_H__ - -#include <glib.h> - -#include <libmissioncontrol/mc-account.h> -#include "empathy-account.h" - -G_BEGIN_DECLS - -EmpathyAccount *_empathy_account_new (McAccount *account); -void _empathy_account_set_status (EmpathyAccount *account, - TpConnectionStatus status, - TpConnectionStatusReason reason, - TpConnectionPresenceType presence); -void _empathy_account_set_connection (EmpathyAccount *account, - TpConnection *connection); -void _empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled); -McAccount *_empathy_account_get_mc_account (EmpathyAccount *account); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_ACCOUNT_PRIV_H__*/ diff --git a/libempathy/empathy-account-settings.c b/libempathy/empathy-account-settings.c new file mode 100644 index 000000000..81a7a948e --- /dev/null +++ b/libempathy/empathy-account-settings.c @@ -0,0 +1,1179 @@ +/* + * empathy-account-settings.c - Source for EmpathyAccountSettings + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@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 + */ + + +#include <stdio.h> +#include <stdlib.h> + +#include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> +#include <telepathy-glib/gtypes.h> + +#include "empathy-account-settings.h" +#include "empathy-account-manager.h" +#include "empathy-connection-managers.h" +#include "empathy-utils.h" + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountSettings) + +G_DEFINE_TYPE(EmpathyAccountSettings, empathy_account_settings, G_TYPE_OBJECT) + +enum { + PROP_ACCOUNT = 1, + PROP_CM_NAME, + PROP_PROTOCOL, + PROP_DISPLAY_NAME, + PROP_DISPLAY_NAME_OVERRIDDEN, + PROP_READY +}; + +/* private structure */ +typedef struct _EmpathyAccountSettingsPriv EmpathyAccountSettingsPriv; + +struct _EmpathyAccountSettingsPriv +{ + gboolean dispose_has_run; + EmpathyConnectionManagers *managers; + EmpathyAccountManager *account_manager; + gulong account_manager_ready_id; + + TpConnectionManager *manager; + const TpConnectionManagerProtocol *tp_protocol; + + EmpathyAccount *account; + gchar *cm_name; + gchar *protocol; + gchar *display_name; + gchar *icon_name; + gboolean display_name_overridden; + gboolean ready; + + GHashTable *parameters; + GArray *unset_parameters; + GArray *required_params; + + gulong managers_ready_id; + gulong account_ready_id; + + GSimpleAsyncResult *apply_result; +}; + +static void +empathy_account_settings_init (EmpathyAccountSettings *obj) +{ + EmpathyAccountSettingsPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE ((obj), + EMPATHY_TYPE_ACCOUNT_SETTINGS, EmpathyAccountSettingsPriv); + + obj->priv = priv; + + /* allocate any data required by the object here */ + priv->managers = empathy_connection_managers_dup_singleton (); + priv->account_manager = empathy_account_manager_dup_singleton (); + + priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) tp_g_value_slice_free); + + priv->unset_parameters = g_array_new (TRUE, FALSE, sizeof (gchar *)); +} + +static void empathy_account_settings_dispose (GObject *object); +static void empathy_account_settings_finalize (GObject *object); +static void empathy_account_settings_ready_cb (GObject *obj, + GParamSpec *spec, gpointer user_data); +static void empathy_account_settings_check_readyness ( + EmpathyAccountSettings *self); + +static void +empathy_account_settings_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + switch (prop_id) + { + case PROP_ACCOUNT: + priv->account = g_value_dup_object (value); + break; + case PROP_CM_NAME: + priv->cm_name = g_value_dup_string (value); + break; + case PROP_PROTOCOL: + priv->protocol = g_value_dup_string (value); + break; + case PROP_DISPLAY_NAME: + priv->display_name = g_value_dup_string (value); + break; + case PROP_DISPLAY_NAME_OVERRIDDEN: + priv->display_name_overridden = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_account_settings_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + switch (prop_id) + { + case PROP_ACCOUNT: + g_value_set_object (value, priv->account); + break; + case PROP_CM_NAME: + g_value_set_string (value, priv->cm_name); + break; + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; + case PROP_DISPLAY_NAME: + g_value_set_string (value, priv->display_name); + break; + case PROP_DISPLAY_NAME_OVERRIDDEN: + g_value_set_boolean (value, priv->display_name_overridden); + break; + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_account_settings_constructed (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->account != NULL) + { + g_free (priv->cm_name); + g_free (priv->protocol); + + priv->cm_name = + g_strdup (empathy_account_get_connection_manager (priv->account)); + priv->protocol = + g_strdup (empathy_account_get_protocol (priv->account)); + } + + priv->icon_name = g_strdup_printf ("im-%s", priv->protocol); + + g_assert (priv->cm_name != NULL && priv->protocol != NULL); + + empathy_account_settings_check_readyness (self); + + if (!priv->ready) + { + g_signal_connect (priv->account, "notify::ready", + G_CALLBACK (empathy_account_settings_ready_cb), self); + g_signal_connect (priv->managers, "notify::ready", + G_CALLBACK (empathy_account_settings_ready_cb), self); + } + + if (G_OBJECT_CLASS ( + empathy_account_settings_parent_class)->constructed != NULL) + G_OBJECT_CLASS ( + empathy_account_settings_parent_class)->constructed (object); +} + + +static void +empathy_account_settings_class_init ( + EmpathyAccountSettingsClass *empathy_account_settings_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_account_settings_class); + + g_type_class_add_private (empathy_account_settings_class, sizeof + (EmpathyAccountSettingsPriv)); + + object_class->dispose = empathy_account_settings_dispose; + object_class->finalize = empathy_account_settings_finalize; + object_class->set_property = empathy_account_settings_set_property; + object_class->get_property = empathy_account_settings_get_property; + object_class->constructed = empathy_account_settings_constructed; + + g_object_class_install_property (object_class, PROP_ACCOUNT, + g_param_spec_object ("account", + "Account", + "The EmpathyAccount backing these settings", + EMPATHY_TYPE_ACCOUNT, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_CM_NAME, + g_param_spec_string ("connection-manager", + "connection-manager", + "The name of the connection manager this account uses", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_PROTOCOL, + g_param_spec_string ("protocol", + "Protocol", + "The name of the protocol this account uses", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME, + g_param_spec_string ("display-name", + "display-name", + "The display name account these settings belong to", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME_OVERRIDDEN, + g_param_spec_boolean ("display-name-overridden", + "display-name-overridden", + "Whether the display name for this account has been manually overridden", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether this account is ready to be used", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); +} + +static void +empathy_account_settings_dispose (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->managers_ready_id != 0) + g_signal_handler_disconnect (priv->managers, priv->managers_ready_id); + priv->managers_ready_id = 0; + + if (priv->managers != NULL) + g_object_unref (priv->managers); + priv->managers = NULL; + + if (priv->manager != NULL) + g_object_unref (priv->manager); + priv->manager = NULL; + + if (priv->account_manager_ready_id != 0) + g_signal_handler_disconnect (priv->account_manager, + priv->account_manager_ready_id); + priv->account_manager_ready_id = 0; + + if (priv->account_manager != NULL) + g_object_unref (priv->account_manager); + priv->account_manager = NULL; + + if (priv->account_ready_id != 0) + g_signal_handler_disconnect (priv->account, priv->account_ready_id); + priv->account_ready_id = 0; + + if (priv->account != NULL) + g_object_unref (priv->account); + priv->account = NULL; + + /* release any references held by the object here */ + if (G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose) + G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose (object); +} + +static void +empathy_account_settings_free_unset_parameters ( + EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + int i; + + for (i = 0 ; i < priv->unset_parameters->len; i++) + g_free (g_array_index (priv->unset_parameters, gchar *, i)); + + g_array_set_size (priv->unset_parameters, 0); +} + +static void +empathy_account_settings_finalize (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + /* free any data held directly by the object here */ + g_free (priv->cm_name); + g_free (priv->protocol); + g_free (priv->display_name); + g_free (priv->icon_name); + + g_hash_table_destroy (priv->parameters); + + empathy_account_settings_free_unset_parameters (self); + g_array_free (priv->unset_parameters, TRUE); + + G_OBJECT_CLASS (empathy_account_settings_parent_class)->finalize (object); +} + +static void +empathy_account_settings_check_readyness (EmpathyAccountSettings *self) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->ready) + return; + + if (priv->account != NULL && !empathy_account_is_ready (priv->account)) + return; + + if (!empathy_connection_managers_is_ready (priv->managers)) + return; + + priv->manager = empathy_connection_managers_get_cm ( + priv->managers, priv->cm_name); + + if (priv->manager == NULL) + return; + + if (priv->account != NULL) + { + g_free (priv->display_name); + priv->display_name = + g_strdup (empathy_account_get_display_name (priv->account)); + + g_free (priv->icon_name); + priv->icon_name = + g_strdup (empathy_account_get_icon_name (priv->account)); + } + + priv->tp_protocol = tp_connection_manager_get_protocol (priv->manager, + priv->protocol); + + if (priv->tp_protocol == NULL) + { + priv->manager = NULL; + return; + } + + if (priv->required_params == NULL) + { + TpConnectionManagerParam *cur; + char *val; + + priv->required_params = g_array_new (TRUE, FALSE, sizeof (gchar *)); + + for (cur = priv->tp_protocol->params; cur->name != NULL; cur++) + { + if (tp_connection_manager_param_is_required (cur)) + { + val = g_strdup (cur->name); + g_array_append_val (priv->required_params, val); + } + } + } + + g_object_ref (priv->manager); + + priv->ready = TRUE; + g_object_notify (G_OBJECT (self), "ready"); +} + +static void +empathy_account_settings_ready_cb (GObject *obj, + GParamSpec *spec, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + + empathy_account_settings_check_readyness (settings); +} + +EmpathyAccountSettings * +empathy_account_settings_new (const gchar *connection_manager, + const gchar *protocol, + const char *display_name) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS, + "connection-manager", connection_manager, + "protocol", protocol, + "display-name", display_name, + NULL); +} + +EmpathyAccountSettings * +empathy_account_settings_new_for_account (EmpathyAccount *account) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS, + "account", account, + NULL); +} + +TpConnectionManagerParam * +empathy_account_settings_get_tp_params (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + g_return_val_if_fail (priv->tp_protocol != NULL, NULL); + + return priv->tp_protocol->params; +} + +gboolean +empathy_account_settings_is_ready (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->ready; +} + +const gchar * +empathy_account_settings_get_cm (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->cm_name; +} + +const gchar * +empathy_account_settings_get_protocol (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->protocol; +} + +gchar * +empathy_account_settings_get_icon_name (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->icon_name; +} + +const gchar * +empathy_account_settings_get_display_name (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->display_name; +} + +EmpathyAccount * +empathy_account_settings_get_account (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->account; +} + +static gboolean +empathy_account_settings_is_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GArray *a; + int i; + + a = priv->unset_parameters; + + for (i = 0; i < a->len; i++) + { + if (!tp_strdiff (g_array_index (a, gchar *, i), param)) + return TRUE; + } + + return FALSE; +} + +static TpConnectionManagerParam * +empathy_account_settings_get_tp_param (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *tp_params = + empathy_account_settings_get_tp_params (settings); + TpConnectionManagerParam *p; + + for (p = tp_params; p != NULL && p->name != NULL; p++) + { + if (tp_strdiff (p->name, param)) + continue; + + return p; + } + + return NULL; +} + +static void +account_settings_remove_from_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + int idx; + gchar *val; + + for (idx = 0; idx < priv->unset_parameters->len; idx++) + { + val = g_array_index (priv->unset_parameters, gchar *, idx); + + if (!tp_strdiff (val, param)) + { + priv->unset_parameters = + g_array_remove_index (priv->unset_parameters, idx); + g_free (val); + + break; + } + } +} + +const GValue * +empathy_account_settings_get_default (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *p; + + p = empathy_account_settings_get_tp_param (settings, param); + + if (p == NULL || !(p->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT)) + return NULL; + + return &(p->default_value); +} + +const gchar * +empathy_account_settings_get_dbus_signature (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *p; + + p = empathy_account_settings_get_tp_param (settings, param); + + if (p == NULL) + return NULL; + + return p->dbus_signature; +} + +const GValue * +empathy_account_settings_get (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + const GValue *result = NULL; + + /* Lookup the update parameters we set */ + result = tp_asv_lookup (priv->parameters, param); + if (result != NULL) + return result; + + /* If the parameters isn't unset use the accounts setting if any */ + if (priv->account != NULL + && !empathy_account_settings_is_unset (settings, param)) + { + const GHashTable *parameters; + + parameters = empathy_account_get_parameters (priv->account); + result = tp_asv_lookup (parameters, param); + + if (result != NULL) + return result; + } + + /* fallback to the default */ + return empathy_account_settings_get_default (settings, param); +} + +void +empathy_account_settings_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + gchar *v; + if (empathy_account_settings_is_unset (settings, param)) + return; + + v = g_strdup (param); + + g_array_append_val (priv->unset_parameters, v); + g_hash_table_remove (priv->parameters, param); +} + +void +empathy_account_settings_discard_changes (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + g_hash_table_remove_all (priv->parameters); + empathy_account_settings_free_unset_parameters (settings); +} + +const gchar * +empathy_account_settings_get_string (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_STRING (v)) + return NULL; + + return g_value_get_string (v); +} + +gint32 +empathy_account_settings_get_int32 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + gint32 ret = 0; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = g_value_get_int (v); + break; + case G_TYPE_UINT: + ret = CLAMP (G_MININT32, g_value_get_uint (v), G_MAXINT32); + break; + case G_TYPE_INT64: + ret = CLAMP (G_MININT32, g_value_get_int64 (v), G_MAXINT32); + break; + case G_TYPE_UINT64: + ret = CLAMP (G_MININT32, g_value_get_uint64 (v), G_MAXINT32); + break; + default: + ret = 0; + break; + } + + return ret; +} + +gint64 +empathy_account_settings_get_int64 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + gint64 ret = 0; + + v = empathy_account_settings_get (settings, param); + if (v == NULL) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = g_value_get_int (v); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = g_value_get_int64 (v); + break; + case G_TYPE_UINT64: + ret = CLAMP (G_MININT64, g_value_get_uint64 (v), G_MAXINT64); + break; + default: + ret = 0; + break; + } + + return ret; +} + +guint32 +empathy_account_settings_get_uint32 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + guint32 ret; + + v = empathy_account_settings_get (settings, param); + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = MAX (0, g_value_get_int (v)); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = CLAMP (0, g_value_get_int64 (v), G_MAXUINT32); + break; + case G_TYPE_UINT64: + ret = CLAMP (0, g_value_get_uint64 (v), G_MAXUINT32); + break; + default: + ret = 0; + break; + } + + return ret; +} + +guint64 +empathy_account_settings_get_uint64 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + guint64 ret = 0; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_INT (v)) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = MAX (0, g_value_get_int (v)); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = MAX (0, g_value_get_int64 (v)); + break; + case G_TYPE_UINT64: + ret = CLAMP (0, g_value_get_uint64 (v), G_MAXUINT64); + break; + default: + ret = 0; + break; + } + + return ret; +} + +gboolean +empathy_account_settings_get_boolean (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_BOOLEAN (v)) + return FALSE; + + return g_value_get_boolean (v); +} + +void +empathy_account_settings_set_string (EmpathyAccountSettings *settings, + const gchar *param, + const gchar *value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_string (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_int32 (EmpathyAccountSettings *settings, + const gchar *param, + gint32 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_int32 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_int64 (EmpathyAccountSettings *settings, + const gchar *param, + gint64 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_int64 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_uint32 (EmpathyAccountSettings *settings, + const gchar *param, + guint32 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_uint32 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_uint64 (EmpathyAccountSettings *settings, + const gchar *param, + guint64 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_uint64 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_boolean (EmpathyAccountSettings *settings, + const gchar *param, + gboolean value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_boolean (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +static void +account_settings_display_name_set_cb (GObject *src, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccount *account = EMPATHY_ACCOUNT (src); + GSimpleAsyncResult *set_result = user_data; + + empathy_account_set_display_name_finish (account, res, &error); + + if (error != NULL) + { + g_simple_async_result_set_from_error (set_result, error); + g_error_free (error); + } + + g_simple_async_result_complete (set_result); + g_object_unref (set_result); +} + +void +empathy_account_settings_set_display_name_async ( + EmpathyAccountSettings *settings, + const gchar *name, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (settings), + callback, user_data, empathy_account_settings_set_display_name_finish); + + if (priv->account == NULL) + { + if (priv->display_name != NULL) + g_free (priv->display_name); + + priv->display_name = g_strdup (name); + + g_simple_async_result_complete_in_idle (result); + + return; + } + + empathy_account_set_display_name_async (priv->account, name, + account_settings_display_name_set_cb, result); +} + +gboolean +empathy_account_settings_set_display_name_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (settings), empathy_account_settings_set_display_name_finish), + FALSE); + + return TRUE; +} + +static void +empathy_account_settings_account_updated (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GSimpleAsyncResult *r; + GError *error = NULL; + + if (!empathy_account_update_settings_finish (EMPATHY_ACCOUNT (source), + result, &error)) + { + g_simple_async_result_set_from_error (priv->apply_result, error); + g_error_free (error); + } + else + { + empathy_account_settings_discard_changes (settings); + } + + r = priv->apply_result; + priv->apply_result = NULL; + + g_simple_async_result_complete (r); + g_object_unref (r); +} + +static void +empathy_account_settings_created_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + EmpathyAccount *account; + GError *error = NULL; + GSimpleAsyncResult *r; + + account = empathy_account_manager_create_account_finish ( + EMPATHY_ACCOUNT_MANAGER (source), result, &error); + + if (account == NULL) + { + g_simple_async_result_set_from_error (priv->apply_result, error); + } + else + { + priv->account = g_object_ref (account); + empathy_account_settings_discard_changes (settings); + } + + r = priv->apply_result; + priv->apply_result = NULL; + + g_simple_async_result_complete (r); + g_object_unref (r); +} + + +static void +empathy_account_settings_do_create_account (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GHashTable *properties; + TpConnectionPresenceType type; + gchar *status; + gchar *message; + + properties = tp_asv_new (NULL, NULL); + + type = empathy_account_manager_get_requested_global_presence + (priv->account_manager, &status, &message); + + if (type != TP_CONNECTION_PRESENCE_TYPE_UNSET) + { + /* Create the account with the requested presence the same as the current + * global requested presence, but don't enable it */ + GValueArray *presence; + GValue vtype = { 0, }; + GValue vstatus = { 0, }; + GValue vmessage = { 0, }; + + presence = g_value_array_new (3); + + g_value_init (&vtype, G_TYPE_UINT); + g_value_set_uint (&vtype, type); + g_value_array_append (presence, &vtype); + + g_value_init (&vstatus, G_TYPE_STRING); + g_value_take_string (&vstatus, status); + g_value_array_append (presence, &vstatus); + + g_value_init (&vmessage, G_TYPE_STRING); + g_value_take_string (&vmessage, message); + g_value_array_append (presence, &vmessage); + + tp_asv_take_boxed (properties, TP_IFACE_ACCOUNT ".RequestedPresence", + TP_STRUCT_TYPE_SIMPLE_PRESENCE, presence); + } + + empathy_account_manager_create_account_async (priv->account_manager, + priv->cm_name, priv->protocol, priv->display_name, + priv->parameters, properties, + empathy_account_settings_created_cb, + settings); + + g_hash_table_unref (properties); +} + +static void +empathy_account_settings_manager_ready_cb (EmpathyAccountManager *manager, + GParamSpec *spec, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + if (empathy_account_manager_is_ready (manager)) + { + g_assert (priv->apply_result != NULL && priv->account == NULL); + g_signal_handler_disconnect (priv->account_manager, + priv->account_manager_ready_id); + priv->account_manager_ready_id = 0; + + empathy_account_settings_do_create_account (settings); + } +} + +void +empathy_account_settings_apply_async (EmpathyAccountSettings *settings, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + if (priv->apply_result != NULL) + { + g_simple_async_report_error_in_idle (G_OBJECT (settings), + callback, user_data, + G_IO_ERROR, G_IO_ERROR_PENDING, "Applying already in progress"); + return; + } + + priv->apply_result = g_simple_async_result_new (G_OBJECT (settings), + callback, user_data, empathy_account_settings_apply_finish); + + if (priv->account == NULL) + { + if (empathy_account_manager_is_ready (priv->account_manager)) + empathy_account_settings_do_create_account (settings); + else + priv->account_manager_ready_id = g_signal_connect ( + priv->account_manager, + "notify::ready", + G_CALLBACK (empathy_account_settings_manager_ready_cb), + settings); + } + else + { + empathy_account_update_settings_async (priv->account, + priv->parameters, (const gchar **)priv->unset_parameters->data, + empathy_account_settings_account_updated, settings); + } +} + +gboolean +empathy_account_settings_apply_finish (EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (settings), empathy_account_settings_apply_finish), FALSE); + + return TRUE; +} + +gboolean +empathy_account_settings_has_account (EmpathyAccountSettings *settings, + EmpathyAccount *account) +{ + EmpathyAccountSettingsPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE); + g_return_val_if_fail (EMPATHY_IS_ACCOUNT (account), FALSE); + + priv = GET_PRIV (settings); + + return (account == priv->account); +} + +gboolean +empathy_account_settings_is_valid (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv; + int idx; + gchar *current; + gboolean missed = FALSE; + + g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE); + + priv = GET_PRIV (settings); + + for (idx = 0; idx < priv->required_params->len; idx++) + { + current = g_array_index (priv->required_params, gchar *, idx); + + /* first, look if it's set in our own parameters */ + if (tp_asv_lookup (priv->parameters, current)) + continue; + + /* if we did not unset the parameter, look if it's in the account */ + if (priv->account != NULL && + !empathy_account_settings_is_unset (settings, current)) + { + const GHashTable *account_params; + + account_params = empathy_account_get_parameters (priv->account); + if (tp_asv_lookup (account_params, current)) + continue; + } + + missed = TRUE; + break; + } + + return !missed; +} diff --git a/libempathy/empathy-account-settings.h b/libempathy/empathy-account-settings.h new file mode 100644 index 000000000..476bfb397 --- /dev/null +++ b/libempathy/empathy-account-settings.h @@ -0,0 +1,163 @@ +/* + * empathy-account-settings.h - Header for EmpathyAccountSettings + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@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 + */ + +#ifndef __EMPATHY_ACCOUNT_SETTINGS_H__ +#define __EMPATHY_ACCOUNT_SETTINGS_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +#include <libempathy/empathy-account.h> +#include <telepathy-glib/connection-manager.h> + +G_BEGIN_DECLS + +typedef struct _EmpathyAccountSettings EmpathyAccountSettings; +typedef struct _EmpathyAccountSettingsClass EmpathyAccountSettingsClass; + +struct _EmpathyAccountSettingsClass { + GObjectClass parent_class; +}; + +struct _EmpathyAccountSettings { + GObject parent; + gpointer priv; +}; + +GType empathy_account_settings_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_ACCOUNT_SETTINGS \ + (empathy_account_settings_get_type ()) +#define EMPATHY_ACCOUNT_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + EMPATHY_TYPE_ACCOUNT_SETTINGS, EmpathyAccountSettings)) +#define EMPATHY_ACCOUNT_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_ACCOUNT_SETTINGS, \ + EmpathyAccountSettingsClass)) +#define EMPATHY_IS_ACCOUNT_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_ACCOUNT_SETTINGS)) +#define EMPATHY_IS_ACCOUNT_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_ACCOUNT_SETTINGS)) +#define EMPATHY_ACCOUNT_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_SETTINGS, \ + EmpathyAccountSettingsClass)) + +EmpathyAccountSettings * empathy_account_settings_new ( + const gchar *connection_manager, + const gchar *protocol, + const char *display_name); + +EmpathyAccountSettings * empathy_account_settings_new_for_account ( + EmpathyAccount *account); + +gboolean empathy_account_settings_is_ready (EmpathyAccountSettings *settings); + +const gchar *empathy_account_settings_get_cm (EmpathyAccountSettings *settings); +const gchar *empathy_account_settings_get_protocol ( + EmpathyAccountSettings *settings); + +EmpathyAccount *empathy_account_settings_get_account ( + EmpathyAccountSettings *settings); + +gboolean empathy_account_settings_has_account ( + EmpathyAccountSettings *settings, EmpathyAccount *account); + +TpConnectionManagerParam *empathy_account_settings_get_tp_params ( + EmpathyAccountSettings *settings); + +void empathy_account_settings_unset (EmpathyAccountSettings *settings, + const gchar *param); + +void empathy_account_settings_discard_changes ( + EmpathyAccountSettings *settings); + +const GValue *empathy_account_settings_get (EmpathyAccountSettings *settings, + const gchar *param); + +const gchar * +empathy_account_settings_get_dbus_signature (EmpathyAccountSettings *setting, + const gchar *param); + +const GValue * +empathy_account_settings_get_default (EmpathyAccountSettings *settings, + const gchar *param); + +const gchar *empathy_account_settings_get_string ( + EmpathyAccountSettings *settings, + const gchar *param); + +gint32 empathy_account_settings_get_int32 (EmpathyAccountSettings *settings, + const gchar *param); +gint64 empathy_account_settings_get_int64 (EmpathyAccountSettings *settings, + const gchar *param); +guint32 empathy_account_settings_get_uint32 (EmpathyAccountSettings *settings, + const gchar *param); +guint64 empathy_account_settings_get_uint64 (EmpathyAccountSettings *settings, + const gchar *param); +gboolean empathy_account_settings_get_boolean (EmpathyAccountSettings *settings, + const gchar *param); + +void empathy_account_settings_set_string (EmpathyAccountSettings *settings, + const gchar *param, const gchar *value); + +void empathy_account_settings_set_int32 (EmpathyAccountSettings *settings, + const gchar *param, gint32 value); +void empathy_account_settings_set_int64 (EmpathyAccountSettings *settings, + const gchar *param, gint64 value); +void empathy_account_settings_set_uint32 (EmpathyAccountSettings *settings, + const gchar *param, guint32 value); +void empathy_account_settings_set_uint64 (EmpathyAccountSettings *settings, + const gchar *param, guint64 value); + +void empathy_account_settings_set_boolean (EmpathyAccountSettings *settings, + const gchar *param, gboolean value); + +gchar *empathy_account_settings_get_icon_name ( + EmpathyAccountSettings *settings); + +const gchar *empathy_account_settings_get_display_name ( + EmpathyAccountSettings *settings); + +void empathy_account_settings_set_display_name_async ( + EmpathyAccountSettings *settings, + const gchar *name, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean empathy_account_settings_set_display_name_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error); + +void empathy_account_settings_apply_async (EmpathyAccountSettings *settings, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean empathy_account_settings_apply_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error); + +gboolean empathy_account_settings_is_valid (EmpathyAccountSettings *settings); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_ACCOUNT_SETTINGS_H__*/ diff --git a/libempathy/empathy-account.c b/libempathy/empathy-account.c index e0a8e756b..091950880 100644 --- a/libempathy/empathy-account.c +++ b/libempathy/empathy-account.c @@ -18,17 +18,24 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <telepathy-glib/enums.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/account.h> +#include <telepathy-glib/gtypes.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> +#include <telepathy-glib/defs.h> #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> +#include <glib/gi18n-lib.h> + #include "empathy-account.h" -#include "empathy-account-priv.h" #include "empathy-utils.h" #include "empathy-marshal.h" @@ -36,6 +43,7 @@ enum { STATUS_CHANGED, PRESENCE_CHANGED, + REMOVED, LAST_SIGNAL }; @@ -45,10 +53,14 @@ static guint signals[LAST_SIGNAL]; enum { PROP_ENABLED = 1, PROP_PRESENCE, + PROP_STATUS, + PROP_STATUS_MESSAGE, + PROP_READY, PROP_CONNECTION_STATUS, PROP_CONNECTION_STATUS_REASON, PROP_CONNECTION, PROP_UNIQUE_NAME, + PROP_DBUS_DAEMON, PROP_DISPLAY_NAME }; @@ -64,19 +76,37 @@ struct _EmpathyAccountPriv TpConnection *connection; guint connection_invalidated_id; - TpConnectionStatus status; + TpConnectionStatus connection_status; TpConnectionStatusReason reason; + TpConnectionPresenceType presence; + gchar *status; + gchar *message; gboolean enabled; + gboolean valid; + gboolean ready; + gboolean removed; /* Timestamp when the connection got connected in seconds since the epoch */ glong connect_time; - McAccount *mc_account; + gchar *cm_name; + gchar *proto_name; + gchar *icon_name; + + gchar *unique_name; + gchar *display_name; + TpDBusDaemon *dbus; + + TpAccount *account; + GHashTable *parameters; }; #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccount) +static void _empathy_account_set_connection (EmpathyAccount *account, + const gchar *path); + static void empathy_account_init (EmpathyAccount *obj) { @@ -87,7 +117,34 @@ empathy_account_init (EmpathyAccount *obj) obj->priv = priv; - priv->status = TP_CONNECTION_STATUS_DISCONNECTED; + priv->connection_status = TP_CONNECTION_STATUS_DISCONNECTED; +} + +static void +empathy_account_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + switch (prop_id) + { + case PROP_ENABLED: + empathy_account_set_enabled_async (account, + g_value_get_boolean (value), NULL, NULL); + break; + case PROP_UNIQUE_NAME: + priv->unique_name = g_value_dup_string (value); + break; + case PROP_DBUS_DAEMON: + priv->dbus = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -104,11 +161,20 @@ empathy_account_get_property (GObject *object, case PROP_ENABLED: g_value_set_boolean (value, priv->enabled); break; + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; case PROP_PRESENCE: g_value_set_uint (value, priv->presence); break; + case PROP_STATUS: + g_value_set_string (value, priv->status); + break; + case PROP_STATUS_MESSAGE: + g_value_set_string (value, priv->message); + break; case PROP_CONNECTION_STATUS: - g_value_set_uint (value, priv->status); + g_value_set_uint (value, priv->connection_status); break; case PROP_CONNECTION_STATUS_REASON: g_value_set_uint (value, priv->reason); @@ -125,12 +191,297 @@ empathy_account_get_property (GObject *object, g_value_set_string (value, empathy_account_get_display_name (account)); break; + case PROP_DBUS_DAEMON: + g_value_set_object (value, priv->dbus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +empathy_account_update (EmpathyAccount *account, + GHashTable *properties) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GValueArray *arr; + TpConnectionStatus old_s = priv->connection_status; + gboolean presence_changed = FALSE; + + if (g_hash_table_lookup (properties, "ConnectionStatus") != NULL) + priv->connection_status = + tp_asv_get_int32 (properties, "ConnectionStatus", NULL); + + if (g_hash_table_lookup (properties, "ConnectionStatusReason") != NULL) + priv->reason = tp_asv_get_int32 (properties, + "ConnectionStatusReason", NULL); + + if (g_hash_table_lookup (properties, "CurrentPresence") != NULL) + { + presence_changed = TRUE; + arr = tp_asv_get_boxed (properties, "CurrentPresence", + TP_STRUCT_TYPE_SIMPLE_PRESENCE); + priv->presence = g_value_get_uint (g_value_array_get_nth (arr, 0)); + + g_free (priv->status); + priv->status = g_value_dup_string (g_value_array_get_nth (arr, 1)); + + g_free (priv->message); + priv->message = g_value_dup_string (g_value_array_get_nth (arr, 2)); + } + + if (g_hash_table_lookup (properties, "DisplayName") != NULL) + { + g_free (priv->display_name); + priv->display_name = + g_strdup (tp_asv_get_string (properties, "DisplayName")); + g_object_notify (G_OBJECT (account), "display-name"); + } + + if (g_hash_table_lookup (properties, "Enabled") != NULL) + { + gboolean enabled = tp_asv_get_boolean (properties, "Enabled", NULL); + if (priv->enabled != enabled) + { + priv->enabled = enabled; + g_object_notify (G_OBJECT (account), "enabled"); + } + } + + if (g_hash_table_lookup (properties, "Valid") != NULL) + priv->valid = tp_asv_get_boolean (properties, "Valid", NULL); + + if (g_hash_table_lookup (properties, "Parameters") != NULL) + { + GHashTable *parameters; + + parameters = tp_asv_get_boxed (properties, "Parameters", + TP_HASH_TYPE_STRING_VARIANT_MAP); + + if (priv->parameters != NULL) + g_hash_table_unref (priv->parameters); + + priv->parameters = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, + parameters); + } + + if (!priv->ready) + { + priv->ready = TRUE; + g_object_notify (G_OBJECT (account), "ready"); + } + + if (priv->connection_status != old_s) + { + if (priv->connection_status == TP_CONNECTION_STATUS_CONNECTED) + { + GTimeVal val; + g_get_current_time (&val); + + priv->connect_time = val.tv_sec; + } + + g_signal_emit (account, signals[STATUS_CHANGED], 0, + old_s, priv->connection_status, priv->reason); + + g_object_notify (G_OBJECT (account), "connection-status"); + g_object_notify (G_OBJECT (account), "connection-status-reason"); + } + + if (presence_changed) + { + g_signal_emit (account, signals[PRESENCE_CHANGED], 0, + priv->presence, priv->status, priv->message); + g_object_notify (G_OBJECT (account), "presence"); + g_object_notify (G_OBJECT (account), "status"); + g_object_notify (G_OBJECT (account), "status-message"); + } + + if (g_hash_table_lookup (properties, "Connection") != NULL) + { + const gchar *conn_path = + tp_asv_get_object_path (properties, "Connection"); + + _empathy_account_set_connection (account, conn_path); + } +} + +static void +empathy_account_properties_changed (TpAccount *proxy, + GHashTable *properties, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (!priv->ready) + return; + + empathy_account_update (account, properties); +} + +static void +empathy_account_removed_cb (TpAccount *proxy, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->removed) + return; + + priv->removed = TRUE; + + g_signal_emit (account, signals[REMOVED], 0); +} + +static void +empathy_account_got_all_cb (TpProxy *proxy, + GHashTable *properties, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + + DEBUG ("Got initial set of properties for %s", + empathy_account_get_unique_name (account)); + + if (error != NULL) + { + DEBUG ("Failed to get the initial set of account properties: %s", + error->message); + return; + } + + empathy_account_update (account, properties); +} + +static gchar * +empathy_account_unescape_protocol (const gchar *protocol, gssize len) +{ + gchar *result, *escape; + /* Bad implementation might accidentally use tp_escape_as_identifier, + * which escapes - in the wrong way... */ + if ((escape = g_strstr_len (protocol, len, "_2d")) != NULL) + { + GString *str; + const gchar *input; + + str = g_string_new (""); + input = protocol; + do { + g_string_append_len (str, input, escape - input); + g_string_append_c (str, '-'); + + len -= escape - input + 3; + input = escape + 3; + } while ((escape = g_strstr_len (input, len, "_2d")) != NULL); + + g_string_append_len (str, input, len); + + result = g_string_free (str, FALSE); + } + else + { + result = g_strndup (protocol, len); + } + + g_strdelimit (result, "_", '-'); + + return result; +} + +static gboolean +empathy_account_parse_unique_name (const gchar *bus_name, + gchar **protocol, gchar **manager) +{ + const gchar *proto, *proto_end; + const gchar *cm, *cm_end; + + g_return_val_if_fail ( + g_str_has_prefix (bus_name, TP_ACCOUNT_OBJECT_PATH_BASE), FALSE); + + cm = bus_name + strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + for (cm_end = cm; *cm_end != '/' && *cm_end != '\0'; cm_end++) + /* pass */; + + if (*cm_end == '\0') + return FALSE; + + if (cm_end == '\0') + return FALSE; + + proto = cm_end + 1; + + for (proto_end = proto; *proto_end != '/' && *proto_end != '\0'; proto_end++) + /* pass */; + + if (*proto_end == '\0') + return FALSE; + + if (protocol != NULL) + { + *protocol = empathy_account_unescape_protocol (proto, proto_end - proto); + } + + if (manager != NULL) + *manager = g_strndup (cm, cm_end - cm); + + return TRUE; +} + +static void +account_invalidated_cb (TpProxy *proxy, guint domain, gint code, + gchar *message, gpointer user_data) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (user_data); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->removed) + return; + + priv->removed = TRUE; + + g_signal_emit (account, signals[REMOVED], 0); +} + +static void +empathy_account_constructed (GObject *object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + priv->account = tp_account_new (priv->dbus, priv->unique_name, NULL); + + g_signal_connect (priv->account, "invalidated", + G_CALLBACK (account_invalidated_cb), object); + + empathy_account_parse_unique_name (priv->unique_name, + &(priv->proto_name), &(priv->cm_name)); + + priv->icon_name = empathy_protocol_icon_name (priv->proto_name); + + tp_cli_account_connect_to_account_property_changed (priv->account, + empathy_account_properties_changed, + NULL, NULL, object, NULL); + + tp_cli_account_connect_to_removed (priv->account, + empathy_account_removed_cb, + NULL, NULL, object, NULL); + + tp_cli_dbus_properties_call_get_all (priv->account, -1, + TP_IFACE_ACCOUNT, + empathy_account_got_all_cb, + NULL, + NULL, + G_OBJECT (account)); +} + static void empathy_account_dispose (GObject *object); static void empathy_account_finalize (GObject *object); @@ -142,15 +493,24 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) g_type_class_add_private (empathy_account_class, sizeof (EmpathyAccountPriv)); + object_class->set_property = empathy_account_set_property; object_class->get_property = empathy_account_get_property; object_class->dispose = empathy_account_dispose; object_class->finalize = empathy_account_finalize; + object_class->constructed = empathy_account_constructed; g_object_class_install_property (object_class, PROP_ENABLED, g_param_spec_boolean ("enabled", "Enabled", "Whether this account is enabled or not", FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether this account is ready to be used", + FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_PRESENCE, @@ -162,8 +522,22 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) TP_CONNECTION_PRESENCE_TYPE_UNSET, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_STATUS, + g_param_spec_string ("status", + "Status", + "The Status string of the account", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_STATUS_MESSAGE, + g_param_spec_string ("status-message", + "status-message", + "The Status message string of the account", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_CONNECTION_STATUS, - g_param_spec_uint ("status", + g_param_spec_uint ("connection-status", "ConnectionStatus", "The accounts connections status type", 0, @@ -172,7 +546,7 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON, - g_param_spec_uint ("status-reason", + g_param_spec_uint ("connection-status-reason", "ConnectionStatusReason", "The account connections status reason", 0, @@ -192,7 +566,14 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) "UniqueName", "The accounts unique name", NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DBUS_DAEMON, + g_param_spec_object ("dbus-daemon", + "dbus-daemon", + "The Tp Dbus daemon on which this account exists", + TP_TYPE_DBUS_DAEMON, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_DISPLAY_NAME, g_param_spec_string ("display-name", @@ -212,8 +593,30 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + _empathy_marshal_VOID__UINT_STRING_STRING, + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); + + signals[REMOVED] = g_signal_new ("removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +empathy_account_free_connection (EmpathyAccount *account) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->connection_invalidated_id != 0) + g_signal_handler_disconnect (priv->connection, + priv->connection_invalidated_id); + priv->connection_invalidated_id = 0; + + if (priv->connection != NULL) + g_object_unref (priv->connection); + priv->connection = NULL; } void @@ -227,14 +630,7 @@ empathy_account_dispose (GObject *object) priv->dispose_has_run = TRUE; - if (priv->connection_invalidated_id != 0) - g_signal_handler_disconnect (priv->connection, - priv->connection_invalidated_id); - priv->connection_invalidated_id = 0; - - if (priv->connection != NULL) - g_object_unref (priv->connection); - priv->connection = NULL; + empathy_account_free_connection (self); /* release any references held by the object here */ if (G_OBJECT_CLASS (empathy_account_parent_class)->dispose != NULL) @@ -244,6 +640,16 @@ empathy_account_dispose (GObject *object) void empathy_account_finalize (GObject *object) { + EmpathyAccountPriv *priv = GET_PRIV (object); + + g_free (priv->status); + g_free (priv->message); + + g_free (priv->cm_name); + g_free (priv->proto_name); + g_free (priv->icon_name); + g_free (priv->display_name); + /* free any data held directly by the object here */ if (G_OBJECT_CLASS (empathy_account_parent_class)->finalize != NULL) G_OBJECT_CLASS (empathy_account_parent_class)->finalize (object); @@ -255,7 +661,7 @@ empathy_account_is_just_connected (EmpathyAccount *account) EmpathyAccountPriv *priv = GET_PRIV (account); GTimeVal val; - if (priv->status != TP_CONNECTION_STATUS_CONNECTED) + if (priv->connection_status != TP_CONNECTION_STATUS_CONNECTED) return FALSE; g_get_current_time (&val); @@ -285,6 +691,35 @@ empathy_account_get_connection (EmpathyAccount *account) } /** + * empathy_account_get_connection_for_path: + * @account: a #EmpathyAccount + * @patch: the path to connection object for #EmpathyAccount + * + * Get the connection of the account on path. This function does not return a + * new ref. It is not guaranteed that the returned connection object is ready + * + * Returns: the connection of the account. + **/ +TpConnection * +empathy_account_get_connection_for_path (EmpathyAccount *account, + const gchar *path) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + + /* double-check that the object path is valid */ + if (!tp_dbus_check_valid_object_path (path, NULL)) + return NULL; + + /* Should be a full object path, not the special "/" value */ + if (strlen (path) == 1) + return NULL; + + _empathy_account_set_connection (account, path); + + return priv->connection; +} + +/** * empathy_account_get_unique_name: * @account: a #EmpathyAccount * @@ -295,7 +730,7 @@ empathy_account_get_unique_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_unique_name (priv->mc_account); + return priv->unique_name; } /** @@ -309,7 +744,7 @@ empathy_account_get_display_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_display_name (priv->mc_account); + return priv->display_name; } gboolean @@ -317,154 +752,66 @@ empathy_account_is_valid (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_is_complete (priv->mc_account); -} - -void -empathy_account_set_enabled (EmpathyAccount *account, gboolean enabled) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - - mc_account_set_enabled (priv->mc_account, enabled); + return priv->valid; } -gboolean -empathy_account_is_enabled (EmpathyAccount *account) +const gchar * +empathy_account_get_connection_manager (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return priv->enabled; + return priv->cm_name; } -void -empathy_account_unset_param (EmpathyAccount *account, const gchar *param) +const gchar * +empathy_account_get_protocol (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_unset_param (priv->mc_account, param); + return priv->proto_name; } -gchar * -empathy_account_get_param_string (EmpathyAccount *account, const gchar *param) +const gchar * +empathy_account_get_icon_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - gchar *value = NULL; - mc_account_get_param_string (priv->mc_account, param, &value); - return value; + return priv->icon_name; } -gint -empathy_account_get_param_int (EmpathyAccount *account, const gchar *param) +const GHashTable * +empathy_account_get_parameters (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - int value; - mc_account_get_param_int (priv->mc_account, param, &value); - return value; + return priv->parameters; } gboolean -empathy_account_get_param_boolean (EmpathyAccount *account, const gchar *param) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - gboolean value; - - mc_account_get_param_boolean (priv->mc_account, param, &value); - return value; -} - -void -empathy_account_set_param_string (EmpathyAccount *account, - const gchar *param, - const gchar *value) +empathy_account_is_enabled (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_string (priv->mc_account, param, value); -} -void -empathy_account_set_param_int (EmpathyAccount *account, - const gchar *param, - gint value) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_int (priv->mc_account, param, value); + return priv->enabled; } -void -empathy_account_set_param_boolean (EmpathyAccount *account, - const gchar *param, - gboolean value) +gboolean +empathy_account_is_ready (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_boolean (priv->mc_account, param, value); -} -void -empathy_account_set_display_name (EmpathyAccount *account, - const gchar *display_name) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_display_name (priv->mc_account, display_name); + return priv->ready; } -McProfile * -empathy_account_get_profile (EmpathyAccount *account) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_profile (priv->mc_account); -} EmpathyAccount * -_empathy_account_new (McAccount *mc_account) +empathy_account_new (TpDBusDaemon *dbus, + const gchar *unique_name) { - EmpathyAccount *account; - EmpathyAccountPriv *priv; - - account = g_object_new (EMPATHY_TYPE_ACCOUNT, NULL); - priv = GET_PRIV (account); - priv->mc_account = mc_account; - - return account; -} - -void -_empathy_account_set_status (EmpathyAccount *account, - TpConnectionStatus status, - TpConnectionStatusReason reason, - TpConnectionPresenceType presence) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - TpConnectionStatus old_s = priv->status; - TpConnectionPresenceType old_p = priv->presence; - - priv->status = status; - priv->presence = presence; - - if (priv->status != old_s) - { - if (priv->status == TP_CONNECTION_STATUS_CONNECTED) - { - GTimeVal val; - g_get_current_time (&val); - - priv->connect_time = val.tv_sec; - } - - priv->reason = reason; - g_signal_emit (account, signals[STATUS_CHANGED], 0, - old_s, priv->status, reason); - - g_object_notify (G_OBJECT (account), "status"); - } - - if (priv->presence != old_p) - { - g_signal_emit (account, signals[PRESENCE_CHANGED], 0, - old_p, priv->presence); - g_object_notify (G_OBJECT (account), "presence"); - } + return EMPATHY_ACCOUNT (g_object_new (EMPATHY_TYPE_ACCOUNT, + "dbus-daemon", dbus, + "unique-name", unique_name, + NULL)); } static void @@ -473,13 +820,12 @@ empathy_account_connection_ready_cb (TpConnection *connection, gpointer user_data) { EmpathyAccount *account = EMPATHY_ACCOUNT (user_data); - EmpathyAccountPriv *priv = GET_PRIV (account); if (error != NULL) { DEBUG ("(%s) Connection failed to become ready: %s", empathy_account_get_unique_name (account), error->message); - priv->connection = NULL; + empathy_account_free_connection (account); } else { @@ -517,20 +863,22 @@ _empathy_account_connection_invalidated_cb (TpProxy *self, g_object_notify (G_OBJECT (account), "connection"); } -void +static void _empathy_account_set_connection (EmpathyAccount *account, - TpConnection *connection) + const gchar *path) { EmpathyAccountPriv *priv = GET_PRIV (account); - if (priv->connection == connection) - return; + if (priv->connection != NULL) + { + const gchar *current; - /* Connection already set, don't set the new one */ - if (connection != NULL && priv->connection != NULL) - return; + current = tp_proxy_get_object_path (priv->connection); + if (!tp_strdiff (current, path)) + return; + } - if (connection == NULL) + if (priv->connection != NULL) { g_signal_handler_disconnect (priv->connection, priv->connection_invalidated_id); @@ -538,38 +886,284 @@ _empathy_account_set_connection (EmpathyAccount *account, g_object_unref (priv->connection); priv->connection = NULL; - g_object_notify (G_OBJECT (account), "connection"); } - else + + if (tp_strdiff ("/", path)) { - priv->connection = g_object_ref (connection); - priv->connection_invalidated_id = g_signal_connect (priv->connection, - "invalidated", - G_CALLBACK (_empathy_account_connection_invalidated_cb), - account); - - /* notify a change in the connection property when it's ready */ - tp_connection_call_when_ready (priv->connection, - empathy_account_connection_ready_cb, account); + GError *error = NULL; + priv->connection = tp_connection_new (priv->dbus, NULL, path, &error); + + if (priv->connection == NULL) + { + DEBUG ("Failed to create a new TpConnection: %s", + error->message); + g_error_free (error); + } + else + { + priv->connection_invalidated_id = g_signal_connect (priv->connection, + "invalidated", + G_CALLBACK (_empathy_account_connection_invalidated_cb), account); + + DEBUG ("Readying connection for %s", priv->unique_name); + /* notify a change in the connection property when it's ready */ + tp_connection_call_when_ready (priv->connection, + empathy_account_connection_ready_cb, account); + } } + + g_object_notify (G_OBJECT (account), "connection"); +} + +static void +account_enabled_set_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = user_data; + + if (error != NULL) + g_simple_async_result_set_from_error (result, (GError *) error); + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +gboolean +empathy_account_set_enabled_finish (EmpathyAccount *account, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error) || + !g_simple_async_result_is_valid (result, G_OBJECT (account), + empathy_account_set_enabled_finish)) + return FALSE; + + return TRUE; } void -_empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled) +empathy_account_set_enabled_async (EmpathyAccount *account, + gboolean enabled, + GAsyncReadyCallback callback, + gpointer user_data) { EmpathyAccountPriv *priv = GET_PRIV (account); + GValue value = {0, }; + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_set_enabled_finish); if (priv->enabled == enabled) - return; + { + g_simple_async_result_complete_in_idle (result); + return; + } + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, enabled); + + tp_cli_dbus_properties_call_set (TP_PROXY (priv->account), + -1, TP_IFACE_ACCOUNT, "Enabled", &value, + account_enabled_set_cb, result, NULL, G_OBJECT (account)); +} + +static void +empathy_account_requested_presence_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + if (error) + DEBUG ("Failed to set the requested presence: %s", error->message); +} + + +void +empathy_account_request_presence (EmpathyAccount *account, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GValue value = {0, }; + GValueArray *arr; + + g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE); + g_value_take_boxed (&value, dbus_g_type_specialized_construct + (TP_STRUCT_TYPE_SIMPLE_PRESENCE)); + arr = (GValueArray *) g_value_get_boxed (&value); + + g_value_set_uint (arr->values, type); + g_value_set_static_string (arr->values + 1, status); + g_value_set_static_string (arr->values + 2, message); + + tp_cli_dbus_properties_call_set (TP_PROXY (priv->account), + -1, + TP_IFACE_ACCOUNT, + "RequestedPresence", + &value, + empathy_account_requested_presence_cb, + NULL, + NULL, + G_OBJECT (account)); + + g_value_unset (&value); +} + +static void +empathy_account_updated_cb (TpAccount *proxy, + const gchar **reconnect_required, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + + if (error != NULL) + { + g_simple_async_result_set_from_error (result, (GError *) error); + } + + g_simple_async_result_complete (result); + g_object_unref (G_OBJECT (result)); +} + +void +empathy_account_update_settings_async (EmpathyAccount *account, + GHashTable *parameters, const gchar **unset_parameters, + GAsyncReadyCallback callback, gpointer user_data) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_update_settings_finish); + + tp_cli_account_call_update_parameters (priv->account, + -1, + parameters, + unset_parameters, + empathy_account_updated_cb, + result, + NULL, + G_OBJECT (account)); +} + +gboolean +empathy_account_update_settings_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (account), empathy_account_update_settings_finish), FALSE); + + return TRUE; +} + +static void +account_display_name_set_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = user_data; + + if (error != NULL) + g_simple_async_result_set_from_error (result, (GError *) error); + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +void +empathy_account_set_display_name_async (EmpathyAccount *account, + const char *display_name, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + GValue value = {0, }; + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (display_name == NULL) + { + g_simple_async_report_error_in_idle (G_OBJECT (account), + callback, user_data, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Can't set an empty display name")); + return; + } + + result = g_simple_async_result_new (G_OBJECT (account), callback, + user_data, empathy_account_set_display_name_finish); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, display_name); + + tp_cli_dbus_properties_call_set (priv->account, -1, TP_IFACE_ACCOUNT, + "DisplayName", &value, account_display_name_set_cb, result, NULL, + G_OBJECT (account)); +} - priv->enabled = enabled; - g_object_notify (G_OBJECT (account), "enabled"); +gboolean +empathy_account_set_display_name_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error) || + !g_simple_async_result_is_valid (result, G_OBJECT (account), + empathy_account_set_display_name_finish)) + return FALSE; + + return TRUE; } -McAccount * -_empathy_account_get_mc_account (EmpathyAccount *account) +static void +empathy_account_remove_cb (TpAccount *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + + if (error != NULL) + { + g_simple_async_result_set_from_error (result, (GError *) error); + } + + g_simple_async_result_complete (result); + g_object_unref (G_OBJECT (result)); +} + +void +empathy_account_remove_async (EmpathyAccount *account, + GAsyncReadyCallback callback, gpointer user_data) { EmpathyAccountPriv *priv = GET_PRIV (account); - return priv->mc_account; + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_remove_finish); + + tp_cli_account_call_remove (priv->account, + -1, + empathy_account_remove_cb, + result, + NULL, + G_OBJECT (account)); +} + +gboolean +empathy_account_remove_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (account), empathy_account_update_settings_finish), FALSE); + + return TRUE; } + diff --git a/libempathy/empathy-account.h b/libempathy/empathy-account.h index 75babd826..f88ac43e4 100644 --- a/libempathy/empathy-account.h +++ b/libempathy/empathy-account.h @@ -22,9 +22,9 @@ #define __EMPATHY_ACCOUNT_H__ #include <glib-object.h> +#include <gio/gio.h> #include <telepathy-glib/connection.h> -#include <libmissioncontrol/mc-profile.h> G_BEGIN_DECLS @@ -58,36 +58,51 @@ GType empathy_account_get_type (void); gboolean empathy_account_is_just_connected (EmpathyAccount *account); TpConnection *empathy_account_get_connection (EmpathyAccount *account); +TpConnection *empathy_account_get_connection_for_path (EmpathyAccount *account, + const gchar *path); const gchar *empathy_account_get_unique_name (EmpathyAccount *account); const gchar *empathy_account_get_display_name (EmpathyAccount *account); -void empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled); -gboolean empathy_account_is_enabled (EmpathyAccount *account); +const gchar *empathy_account_get_connection_manager (EmpathyAccount *account); +const gchar *empathy_account_get_protocol (EmpathyAccount *account); +const gchar *empathy_account_get_icon_name (EmpathyAccount *account); + +void empathy_account_set_enabled_async (EmpathyAccount *account, + gboolean enabled, GAsyncReadyCallback callback, gpointer user_data); +gboolean empathy_account_set_enabled_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); -void empathy_account_unset_param (EmpathyAccount *account, const gchar *param); -gchar *empathy_account_get_param_string (EmpathyAccount *account, - const gchar *param); -gint empathy_account_get_param_int (EmpathyAccount *account, - const gchar *param); -gboolean empathy_account_get_param_boolean (EmpathyAccount *account, - const gchar *param); - -void empathy_account_set_param_string (EmpathyAccount *account, - const gchar *param, const gchar *value); -void empathy_account_set_param_int (EmpathyAccount *account, - const gchar *param, gint value); -void empathy_account_set_param_boolean (EmpathyAccount *account, - const gchar *param, gboolean value); +gboolean empathy_account_is_enabled (EmpathyAccount *account); gboolean empathy_account_is_valid (EmpathyAccount *account); +gboolean empathy_account_is_ready (EmpathyAccount *account); + +void empathy_account_update_settings_async (EmpathyAccount *account, + GHashTable *parameters, const gchar **unset_parameters, + GAsyncReadyCallback callback, gpointer user_data); + +gboolean empathy_account_update_settings_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +void empathy_account_remove_async (EmpathyAccount *account, + GAsyncReadyCallback callback, gpointer user_data); +gboolean empathy_account_remove_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +void empathy_account_set_display_name_async (EmpathyAccount *account, + const gchar *display_name, GAsyncReadyCallback callback, + gpointer user_data); +gboolean empathy_account_set_display_name_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +EmpathyAccount *empathy_account_new (TpDBusDaemon *bus_daemon, + const gchar *unique_name); -void empathy_account_set_display_name (EmpathyAccount *account, - const gchar *display_name); +void empathy_account_request_presence (EmpathyAccount *account, + TpConnectionPresenceType type, const gchar *status, const gchar *message); +const GHashTable *empathy_account_get_parameters (EmpathyAccount *account); -/* TODO remove McProfile */ -McProfile *empathy_account_get_profile (EmpathyAccount *account); G_END_DECLS diff --git a/libempathy/empathy-call-handler.c b/libempathy/empathy-call-handler.c index 72c317b7f..1c6e53c6c 100644 --- a/libempathy/empathy-call-handler.c +++ b/libempathy/empathy-call-handler.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include <telepathy-farsight/channel.h> #include <telepathy-farsight/stream.h> diff --git a/libempathy/empathy-chatroom-manager.c b/libempathy/empathy-chatroom-manager.c index 940b56220..7c3559e2f 100644 --- a/libempathy/empathy-chatroom-manager.c +++ b/libempathy/empathy-chatroom-manager.c @@ -30,6 +30,8 @@ #include <libxml/parser.h> #include <libxml/tree.h> +#include <telepathy-glib/interfaces.h> + #include "empathy-tp-chat.h" #include "empathy-chatroom-manager.h" #include "empathy-account-manager.h" @@ -221,7 +223,8 @@ chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager, xmlFree (str); } - account = empathy_account_manager_lookup (priv->account_manager, account_id); + account = empathy_account_manager_get_account (priv->account_manager, + account_id); if (!account) { g_free (name); g_free (room); @@ -234,7 +237,6 @@ chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager, add_chatroom (manager, chatroom); g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom); - g_object_unref (account); g_free (name); g_free (room); g_free (account_id); @@ -578,9 +580,8 @@ empathy_chatroom_manager_find (EmpathyChatroomManager *manager, this_account = empathy_chatroom_get_account (chatroom); this_room = empathy_chatroom_get_room (chatroom); - if (this_account && this_room && - empathy_account_equal (account, this_account) && - strcmp (this_room, room) == 0) { + if (this_account && this_room && account == this_account + && strcmp (this_room, room) == 0) { return chatroom; } } @@ -609,8 +610,7 @@ empathy_chatroom_manager_get_chatrooms (EmpathyChatroomManager *manager, chatroom = l->data; - if (empathy_account_equal (account, - empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { chatrooms = g_list_append (chatrooms, chatroom); } } @@ -639,8 +639,7 @@ empathy_chatroom_manager_get_count (EmpathyChatroomManager *manager, chatroom = l->data; - if (empathy_account_equal (account, - empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { count++; } } @@ -705,8 +704,8 @@ chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher, chat = EMPATHY_TP_CHAT ( empathy_dispatch_operation_get_channel_wrapper (operation)); connection = empathy_tp_chat_get_connection (chat); - account = empathy_account_manager_get_account (priv->account_manager, - connection); + account = empathy_account_manager_get_account_for_connection ( + priv->account_manager, connection); roomname = empathy_tp_chat_get_id (chat); diff --git a/libempathy/empathy-chatroom.c b/libempathy/empathy-chatroom.c index b62d6ad77..33df9a3d6 100644 --- a/libempathy/empathy-chatroom.c +++ b/libempathy/empathy-chatroom.c @@ -480,8 +480,7 @@ empathy_chatroom_equal (gconstpointer v1, room_a = empathy_chatroom_get_room (EMPATHY_CHATROOM (v1)); room_b = empathy_chatroom_get_room (EMPATHY_CHATROOM (v2)); - return empathy_account_equal (account_a, account_b) && - !tp_strdiff (room_a, room_b); + return account_a == account_b && !tp_strdiff (room_a, room_b); } EmpathyTpChat * diff --git a/libempathy/empathy-connection-managers.c b/libempathy/empathy-connection-managers.c new file mode 100644 index 000000000..bd6f315e2 --- /dev/null +++ b/libempathy/empathy-connection-managers.c @@ -0,0 +1,293 @@ +/* + * empathy-connection-managers.c - Source for EmpathyConnectionManagers + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@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 + */ + + +#include <stdio.h> +#include <stdlib.h> + +#include <telepathy-glib/connection-manager.h> +#include <telepathy-glib/util.h> + +#include "empathy-connection-managers.h" +#include "empathy-utils.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_OTHER +#include <libempathy/empathy-debug.h> + +static GObject *managers = NULL; + +G_DEFINE_TYPE(EmpathyConnectionManagers, empathy_connection_managers, + G_TYPE_OBJECT) + +/* signal enum */ +enum +{ + UPDATED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +/* properties */ +enum { + PROP_READY = 1 +}; + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectionManagers) + + +/* private structure */ +typedef struct _EmpathyConnectionManagersPriv + EmpathyConnectionManagersPriv; + +struct _EmpathyConnectionManagersPriv +{ + gboolean dispose_has_run; + gboolean ready; + + GList *cms; + + TpDBusDaemon *dbus; +}; + +static void +empathy_connection_managers_init (EmpathyConnectionManagers *obj) +{ + EmpathyConnectionManagersPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + EMPATHY_TYPE_CONNECTION_MANAGERS, EmpathyConnectionManagersPriv); + + obj->priv = priv; + + priv->dbus = tp_dbus_daemon_dup (NULL); + g_assert (priv->dbus != NULL); + + empathy_connection_managers_update (obj); + + /* allocate any data required by the object here */ +} + +static void empathy_connection_managers_dispose (GObject *object); + +static GObject * +empathy_connection_managers_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + if (managers != NULL) + return g_object_ref (managers); + + managers = + G_OBJECT_CLASS (empathy_connection_managers_parent_class)->constructor + (type, n_construct_params, construct_params); + + g_object_add_weak_pointer (managers, (gpointer) &managers); + + return managers; +} + + + +static void +empathy_connection_managers_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyConnectionManagers *managers = EMPATHY_CONNECTION_MANAGERS (object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + switch (prop_id) + { + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_connection_managers_class_init ( + EmpathyConnectionManagersClass *empathy_connection_managers_class) +{ + GObjectClass *object_class = + G_OBJECT_CLASS (empathy_connection_managers_class); + + g_type_class_add_private (empathy_connection_managers_class, sizeof + (EmpathyConnectionManagersPriv)); + + object_class->constructor = empathy_connection_managers_constructor; + object_class->dispose = empathy_connection_managers_dispose; + object_class->get_property = empathy_connection_managers_get_property; + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether the connection manager information is ready to be used", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + + signals[UPDATED] = g_signal_new ("updated", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +empathy_connection_managers_free_cm_list (EmpathyConnectionManagers *self) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + GList *l; + + for (l = priv->cms ; l != NULL ; l = g_list_next (l)) + { + g_object_unref (l->data); + } + g_list_free (priv->cms); + + priv->cms = NULL; +} + +static void +empathy_connection_managers_dispose (GObject *object) +{ + EmpathyConnectionManagers *self = EMPATHY_CONNECTION_MANAGERS (object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->dbus != NULL) + g_object_unref (priv->dbus); + priv->dbus = NULL; + + empathy_connection_managers_free_cm_list (self); + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose) + G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose (object); +} + +EmpathyConnectionManagers * +empathy_connection_managers_dup_singleton (void) +{ + return EMPATHY_CONNECTION_MANAGERS ( + g_object_new (EMPATHY_TYPE_CONNECTION_MANAGERS, NULL)); +} + +gboolean +empathy_connection_managers_is_ready (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + return priv->ready; +} + +static void +empathy_connection_managers_listed_cb (TpConnectionManager * const *cms, + gsize n_cms, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyConnectionManagers *self = + EMPATHY_CONNECTION_MANAGERS (weak_object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + TpConnectionManager * const *iter; + + empathy_connection_managers_free_cm_list (self); + + if (error != NULL) + { + DEBUG ("Failed to get connection managers: %s", error->message); + goto out; + } + + for (iter = cms ; iter != NULL && *iter != NULL; iter++) + { + /* only list cms that didn't hit errors */ + if (tp_connection_manager_is_ready (*iter)) + priv->cms = g_list_prepend (priv->cms, g_object_ref (*iter)); + } + +out: + g_object_ref (weak_object); + if (!priv->ready) + { + priv->ready = TRUE; + g_object_notify (weak_object, "ready"); + } + g_signal_emit (weak_object, signals[UPDATED], 0); + g_object_unref (weak_object); +} + +void +empathy_connection_managers_update (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + tp_list_connection_managers (priv->dbus, + empathy_connection_managers_listed_cb, + NULL, NULL, G_OBJECT (managers)); +} + +GList * +empathy_connection_managers_get_cms (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + return priv->cms; +} + +TpConnectionManager * +empathy_connection_managers_get_cm (EmpathyConnectionManagers *managers, + const gchar *cm) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + GList *l; + + for (l = priv->cms ; l != NULL; l = g_list_next (l)) + { + TpConnectionManager *c = TP_CONNECTION_MANAGER (l->data); + + if (!tp_strdiff (c->name, cm)) + return c; + } + + return NULL; +} + +guint +empathy_connection_managers_get_cms_num (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_CONNECTION_MANAGERS (managers), 0); + + priv = GET_PRIV (managers); + + return g_list_length (priv->cms); +} diff --git a/libempathy/empathy-connection-managers.h b/libempathy/empathy-connection-managers.h new file mode 100644 index 000000000..17289d36d --- /dev/null +++ b/libempathy/empathy-connection-managers.h @@ -0,0 +1,77 @@ +/* + * empathy-connection-managers.h - Header for EmpathyConnectionManagers + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@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 + */ + +#ifndef __EMPATHY_CONNECTION_MANAGERS_H__ +#define __EMPATHY_CONNECTION_MANAGERS_H__ + +#include <glib-object.h> + +#include <telepathy-glib/connection-manager.h> + +G_BEGIN_DECLS + +typedef struct _EmpathyConnectionManagers EmpathyConnectionManagers; +typedef struct _EmpathyConnectionManagersClass EmpathyConnectionManagersClass; + +struct _EmpathyConnectionManagersClass { + GObjectClass parent_class; +}; + +struct _EmpathyConnectionManagers { + GObject parent; + gpointer priv; +}; + +GType empathy_connection_managers_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_CONNECTION_MANAGERS \ + (empathy_connection_managers_get_type ()) +#define EMPATHY_CONNECTION_MANAGERS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagers)) +#define EMPATHY_CONNECTION_MANAGERS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagersClass)) +#define EMPATHY_IS_CONNECTION_MANAGERS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_CONNECTION_MANAGERS)) +#define EMPATHY_IS_CONNECTION_MANAGERS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_CONNECTION_MANAGERS)) +#define EMPATHY_CONNECTION_MANAGERS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagersClass)) + +EmpathyConnectionManagers *empathy_connection_managers_dup_singleton (void); +gboolean empathy_connection_managers_is_ready ( + EmpathyConnectionManagers *managers); + +void empathy_connection_managers_update (EmpathyConnectionManagers *managers); + +GList * empathy_connection_managers_get_cms ( + EmpathyConnectionManagers *managers); +guint empathy_connection_managers_get_cms_num + (EmpathyConnectionManagers *managers); + +TpConnectionManager *empathy_connection_managers_get_cm ( + EmpathyConnectionManagers *managers, const gchar *cm); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_CONNECTION_MANAGERS_H__*/ diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c index c82ecd467..44d9dbeed 100644 --- a/libempathy/empathy-contact.c +++ b/libempathy/empathy-contact.c @@ -570,7 +570,8 @@ empathy_contact_get_account (EmpathyContact *contact) /* FIXME: This assume the account manager already exists */ manager = empathy_account_manager_dup_singleton (); connection = tp_contact_get_connection (priv->tp_contact); - priv->account = empathy_account_manager_get_account (manager, connection); + priv->account = empathy_account_manager_get_account_for_connection ( + manager, connection); g_object_ref (priv->account); g_object_unref (manager); } @@ -857,27 +858,23 @@ contact_get_avatar_filename (EmpathyContact *contact, gchar *avatar_path; gchar *avatar_file; gchar *token_escaped; - gchar *contact_escaped; if (EMP_STR_EMPTY (empathy_contact_get_id (contact))) return NULL; - contact_escaped = tp_escape_as_identifier (empathy_contact_get_id (contact)); token_escaped = tp_escape_as_identifier (token); account = empathy_contact_get_account (contact); - /* FIXME: Do not use the account, but proto/cm instead */ avatar_path = g_build_filename (g_get_user_cache_dir (), - PACKAGE_NAME, + "telepathy", "avatars", - empathy_account_get_unique_name (account), - contact_escaped, + empathy_account_get_connection_manager (account), + empathy_account_get_protocol (account), NULL); g_mkdir_with_parents (avatar_path, 0700); avatar_file = g_build_filename (avatar_path, token_escaped, NULL); - g_free (contact_escaped); g_free (token_escaped); g_free (avatar_path); diff --git a/libempathy/empathy-debug.c b/libempathy/empathy-debug.c index 9d69b801c..141340024 100644 --- a/libempathy/empathy-debug.c +++ b/libempathy/empathy-debug.c @@ -50,6 +50,7 @@ static GDebugKey keys[] = { { "Location", EMPATHY_DEBUG_LOCATION }, { "Other", EMPATHY_DEBUG_OTHER }, { "Connectivity", EMPATHY_DEBUG_CONNECTIVITY }, + { "ImportMc4Accounts", EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS }, { 0, } }; diff --git a/libempathy/empathy-debug.h b/libempathy/empathy-debug.h index edfa05d95..cc8eca0a3 100644 --- a/libempathy/empathy-debug.h +++ b/libempathy/empathy-debug.h @@ -43,6 +43,7 @@ typedef enum EMPATHY_DEBUG_OTHER = 1 << 9, EMPATHY_DEBUG_SHARE_DESKTOP = 1 << 10, EMPATHY_DEBUG_CONNECTIVITY = 1 << 11, + EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS = 1 << 11, } EmpathyDebugFlags; gboolean empathy_debug_flag_is_set (EmpathyDebugFlags flag); diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c index b51df95fa..c1a19f699 100644 --- a/libempathy/empathy-dispatcher.c +++ b/libempathy/empathy-dispatcher.c @@ -19,6 +19,9 @@ * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ +#define DISPATCHER_BUS_NAME TP_CLIENT_BUS_NAME_BASE "Empathy" +#define DISPATCHER_OBJECT_PATH TP_CLIENT_OBJECT_PATH_BASE "Empathy" + #include <config.h> #include <string.h> @@ -31,8 +34,10 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/proxy-subclass.h> #include <telepathy-glib/gtypes.h> - -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/defs.h> +#include <telepathy-glib/svc-client.h> +#include <telepathy-glib/svc-generic.h> +#include <telepathy-glib/interfaces.h> #include <extensions/extensions.h> @@ -51,7 +56,6 @@ typedef struct { EmpathyAccountManager *account_manager; - MissionControl *mc; /* connection to connection data mapping */ GHashTable *connections; GHashTable *outstanding_classes_requests; @@ -64,7 +68,30 @@ typedef struct GHashTable *request_channel_class_async_ids; } EmpathyDispatcherPriv; -G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT); +static void empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data); + +G_DEFINE_TYPE_WITH_CODE (EmpathyDispatcher, + empathy_dispatcher, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT, NULL); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT_HANDLER, + empathy_dispatcher_client_handler_iface_init); + ); + +static const gchar *empathy_dispatcher_interfaces[] = { + TP_IFACE_CLIENT_HANDLER, + NULL +}; + +enum +{ + PROP_INTERFACES = 1, + PROP_CHANNEL_FILTER, + PROP_CHANNELS +}; enum { @@ -77,6 +104,10 @@ enum static guint signals[LAST_SIGNAL]; static EmpathyDispatcher *dispatcher = NULL; +static void dispatcher_init_connection_if_needed ( + EmpathyDispatcher *dispatcher, + TpConnection *connection); + static GList * empathy_dispatcher_find_channel_classes (EmpathyDispatcher *dispatcher, TpConnection *connection, const gchar *channel_type, guint handle_type, GArray *fixed_properties); @@ -563,6 +594,8 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher, NULL }; + dispatcher_init_connection_if_needed (dispatcher, connection); + cd = g_hash_table_lookup (priv->connections, connection); /* Don't bother with channels we have already dispatched or are dispatching @@ -638,30 +671,11 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher, } static void -dispatcher_connection_new_channel_cb (TpConnection *connection, - const gchar *object_path, - const gchar *channel_type, - guint handle_type, - guint handle, - gboolean suppress_handler, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - - /* Empathy heavily abuses surpress handler (don't try this at home), if - * surpress handler is true then it is an outgoing channel, which is - * requested either by us or some other party (like the megaphone applet). - * Otherwise it's an incoming channel */ - dispatcher_connection_new_channel (dispatcher, connection, - object_path, channel_type, handle_type, handle, NULL, !suppress_handler); -} - -static void -dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher, - TpConnection *connection, - const gchar *object_path, - GHashTable *properties) +dispatcher_connection_new_channel_with_properties ( + EmpathyDispatcher *dispatcher, + TpConnection *connection, + const gchar *object_path, + GHashTable *properties) { const gchar *channel_type; guint handle_type; @@ -701,7 +715,7 @@ dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher if (!valid) { g_message ("%s had an invalid Requested property", object_path); - return; + requested = FALSE; } dispatcher_connection_new_channel (dispatcher, connection, @@ -709,29 +723,6 @@ dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher } static void -dispatcher_connection_new_channels_cb (TpConnection *connection, - const GPtrArray *channels, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - int i; - - for (i = 0; i < channels->len ; i++) - { - GValueArray *arr = g_ptr_array_index (channels, i); - const gchar *object_path; - GHashTable *properties; - - object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); - properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); - - dispatcher_connection_new_channel_with_properties (dispatcher, - connection, object_path, properties); - } -} - -static void dispatcher_connection_got_all (TpProxy *proxy, GHashTable *properties, const GError *error, @@ -740,7 +731,6 @@ dispatcher_connection_got_all (TpProxy *proxy, { EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); - GPtrArray *channels; GPtrArray *requestable_channels; if (error) { @@ -748,15 +738,6 @@ dispatcher_connection_got_all (TpProxy *proxy, return; } - channels = tp_asv_get_boxed (properties, "Channels", - TP_ARRAY_TYPE_CHANNEL_DETAILS_LIST); - - if (channels == NULL) - DEBUG ("No Channels property !?! on connection"); - else - dispatcher_connection_new_channels_cb (TP_CONNECTION (proxy), - channels, NULL, object); - requestable_channels = tp_asv_get_boxed (properties, "RequestableChannelClasses", TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST); @@ -798,38 +779,6 @@ dispatcher_connection_got_all (TpProxy *proxy, } static void -dispatcher_connection_list_channels_cb (TpConnection *connection, - const GPtrArray *channels, - const GError *error, - gpointer user_data, - GObject *dispatcher) -{ - int i; - - if (error) - { - DEBUG ("Error: %s", error->message); - return; - } - - for (i = 0; i < channels->len; i++) - { - GValueArray *values; - - values = g_ptr_array_index (channels, i); - /* We don't have any extra info, so assume already existing channels are - * incoming... */ - dispatcher_connection_new_channel (EMPATHY_DISPATCHER (dispatcher), - connection, - g_value_get_boxed (g_value_array_get_nth (values, 0)), - g_value_get_string (g_value_array_get_nth (values, 1)), - g_value_get_uint (g_value_array_get_nth (values, 2)), - g_value_get_uint (g_value_array_get_nth (values, 3)), - NULL, TRUE); - } -} - -static void dispatcher_connection_advertise_capabilities_cb (TpConnection *connection, const GPtrArray *capabilities, const GError *error, @@ -841,9 +790,8 @@ dispatcher_connection_advertise_capabilities_cb (TpConnection *connection, } static void -dispatcher_new_connection_cb (EmpathyAccountManager *manager, - TpConnection *connection, - EmpathyDispatcher *dispatcher) +dispatcher_init_connection_if_needed (EmpathyDispatcher *dispatcher, + TpConnection *connection) { EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); GPtrArray *capabilities; @@ -863,26 +811,11 @@ dispatcher_new_connection_cb (EmpathyAccountManager *manager, if (tp_proxy_has_interface_by_id (TP_PROXY (connection), TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS)) { - tp_cli_connection_interface_requests_connect_to_new_channels (connection, - dispatcher_connection_new_channels_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - tp_cli_dbus_properties_call_get_all (connection, -1, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, dispatcher_connection_got_all, NULL, NULL, G_OBJECT (dispatcher)); } - else - { - tp_cli_connection_connect_to_new_channel (connection, - dispatcher_connection_new_channel_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - - tp_cli_connection_call_list_channels (connection, -1, - dispatcher_connection_list_channels_cb, NULL, NULL, - G_OBJECT (dispatcher)); - - } /* Advertise VoIP capabilities */ capabilities = g_ptr_array_sized_new (1); @@ -908,6 +841,14 @@ dispatcher_new_connection_cb (EmpathyAccountManager *manager, } static void +dispatcher_new_connection_cb (EmpathyAccountManager *manager, + TpConnection *connection, + EmpathyDispatcher *dispatcher) +{ + dispatcher_init_connection_if_needed (dispatcher, connection); +} + +static void remove_idle_handlers (gpointer key, gpointer value, gpointer user_data) @@ -924,19 +865,25 @@ dispatcher_constructor (GType type, GObjectConstructParam *construct_params) { GObject *retval; + TpDBusDaemon *dbus; - if (dispatcher == NULL) - { - retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor - (type, n_construct_params, construct_params); + if (dispatcher != NULL) + return g_object_ref (dispatcher); - dispatcher = EMPATHY_DISPATCHER (retval); - g_object_add_weak_pointer (retval, (gpointer) &dispatcher); - } - else - { - retval = g_object_ref (dispatcher); - } + retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor + (type, n_construct_params, construct_params); + + dispatcher = EMPATHY_DISPATCHER (retval); + g_object_add_weak_pointer (retval, (gpointer) &dispatcher); + + dbus = tp_dbus_daemon_dup (NULL); + + g_assert (tp_dbus_daemon_request_name (dbus, + DISPATCHER_BUS_NAME, TRUE, NULL)); + dbus_g_connection_register_g_object (tp_get_bus (), + DISPATCHER_OBJECT_PATH, retval); + + DEBUG ("Registering at '%s'", DISPATCHER_OBJECT_PATH); return retval; } @@ -983,20 +930,113 @@ dispatcher_finalize (GObject *object) } g_object_unref (priv->account_manager); - g_object_unref (priv->mc); g_hash_table_destroy (priv->connections); g_hash_table_destroy (priv->outstanding_classes_requests); } static void +dispatcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); + EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); + + switch (property_id) + { + case PROP_INTERFACES: + g_value_set_boxed (value, empathy_dispatcher_interfaces); + break; + case PROP_CHANNEL_FILTER: + { + GPtrArray *filters = g_ptr_array_new (); + GHashTable *filter = g_hash_table_new (NULL, NULL); + + g_ptr_array_add (filters, filter); + + g_value_set_boxed (value, filters); + break; + } + case PROP_CHANNELS: + { + GPtrArray *accounts; + GList *l; + + accounts = g_ptr_array_new (); + + for (l = priv->channels; l != NULL; l = g_list_next (l)) + { + TpProxy *channel = TP_PROXY (l->data); + + g_ptr_array_add (accounts, + g_strdup (tp_proxy_get_object_path (channel))); + } + + g_value_set_boxed (value, accounts); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl client_props[] = { + { "Interfaces", "interfaces", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinPropImpl client_handler_props[] = { + { "HandlerChannelFilter", "channel-filter", NULL }, + { "HandledChannels", "channels", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CLIENT, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_props + }, + { TP_IFACE_CLIENT_HANDLER, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_handler_props + }, + { NULL } + }; object_class->finalize = dispatcher_finalize; object_class->constructor = dispatcher_constructor; + object_class->get_property = dispatcher_get_property; + + param_spec = g_param_spec_boxed ("interfaces", "interfaces", + "Available D-Bus interfaces", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_boxed ("channel-filter", "channel-filter", + "Filter for channels this handles", + TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CHANNEL_FILTER, param_spec); + + param_spec = g_param_spec_boxed ("channels", "channels", + "List of channels we're handling", + EMPATHY_ARRAY_TYPE_OBJECT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CHANNELS, param_spec); + signals[OBSERVE] = g_signal_new ("observe", G_TYPE_FROM_CLASS (klass), @@ -1027,8 +1067,12 @@ empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) G_TYPE_NONE, 1, EMPATHY_TYPE_DISPATCH_OPERATION); + g_type_class_add_private (object_class, sizeof (EmpathyDispatcherPriv)); + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (EmpathyDispatcherClass, dbus_props_class)); } static void @@ -1039,7 +1083,6 @@ empathy_dispatcher_init (EmpathyDispatcher *dispatcher) EMPATHY_TYPE_DISPATCHER, EmpathyDispatcherPriv); dispatcher->priv = priv; - priv->mc = empathy_mission_control_dup_singleton (); priv->account_manager = empathy_account_manager_dup_singleton (); g_signal_connect (priv->account_manager, "new-connection", @@ -1753,3 +1796,59 @@ empathy_dispatcher_find_requestable_channel_classes_async g_hash_table_insert (priv->request_channel_class_async_ids, request, GUINT_TO_POINTER (source_id)); } + +static void +empathy_dispatcher_handle_channels (TpSvcClientHandler *self, + const gchar *account_path, + const gchar *connection_path, + const GPtrArray *channels, + const GPtrArray *requests_satisfied, + guint64 timestamp, + GHashTable *handler_info, + DBusGMethodInvocation *context) +{ + EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (self); + EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); + int i; + EmpathyAccount *account; + TpConnection *connection; + + account = empathy_account_manager_ensure_account (priv->account_manager, + account_path); + g_assert (account != NULL); + + connection = empathy_account_get_connection_for_path (account, + connection_path); + if (connection == NULL) + { + GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Invalid connection argument" }; + dbus_g_method_return_error (context, &error); + return; + } + + for (i = 0; i < channels->len ; i++) + { + GValueArray *arr = g_ptr_array_index (channels, i); + const gchar *object_path; + GHashTable *properties; + + object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); + properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); + + dispatcher_connection_new_channel_with_properties (dispatcher, + connection, object_path, properties); + } + + tp_svc_client_handler_return_from_handle_channels (context); +} + +static void +empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data) +{ + TpSvcClientHandlerClass *klass = (TpSvcClientHandlerClass *) g_iface; + + tp_svc_client_handler_implement_handle_channels (klass, + empathy_dispatcher_handle_channels); +} diff --git a/libempathy/empathy-dispatcher.h b/libempathy/empathy-dispatcher.h index d6c83f6c1..41a1430fb 100644 --- a/libempathy/empathy-dispatcher.h +++ b/libempathy/empathy-dispatcher.h @@ -26,6 +26,7 @@ #include <gio/gio.h> #include <telepathy-glib/channel.h> +#include <telepathy-glib/dbus-properties-mixin.h> #include "empathy-contact.h" #include "empathy-dispatch-operation.h" @@ -51,6 +52,7 @@ struct _EmpathyDispatcher struct _EmpathyDispatcherClass { GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; }; /* Will be called when the channel is ready for dispatching. The requestor diff --git a/libempathy/empathy-ft-handler.c b/libempathy/empathy-ft-handler.c index d24467b24..b05da94aa 100644 --- a/libempathy/empathy-ft-handler.c +++ b/libempathy/empathy-ft-handler.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-ft-handler.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c index ac0ca72f6..c86b997af 100644 --- a/libempathy/empathy-idle.c +++ b/libempathy/empathy-idle.c @@ -28,8 +28,8 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mc-enum-types.h> +#include "empathy-account-manager.h" #include "empathy-idle.h" #include "empathy-utils.h" #include "empathy-connectivity.h" @@ -42,7 +42,6 @@ #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIdle) typedef struct { - MissionControl *mc; DBusGProxy *gs_proxy; EmpathyConnectivity *connectivity; gulong state_change_signal_id; @@ -58,6 +57,8 @@ typedef struct { gboolean is_idle; guint ext_away_timeout; + + EmpathyAccountManager *manager; } EmpathyIdlePriv; typedef enum { @@ -81,9 +82,10 @@ G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT); static EmpathyIdle * idle_singleton = NULL; static void -idle_presence_changed_cb (MissionControl *mc, +idle_presence_changed_cb (EmpathyAccountManager *manager, TpConnectionPresenceType state, gchar *status, + gchar *status_message, EmpathyIdle *idle) { EmpathyIdlePriv *priv; @@ -94,14 +96,15 @@ idle_presence_changed_cb (MissionControl *mc, /* Assume our presence is offline if MC reports UNSET */ state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - DEBUG ("Presence changed to '%s' (%d)", status, state); + DEBUG ("Presence changed to '%s' (%d) \"%s\"", status, state, + status_message); g_free (priv->status); priv->state = state; - priv->status = NULL; - if (!EMP_STR_EMPTY (status)) { - priv->status = g_strdup (status); - } + if (EMP_STR_EMPTY (status_message)) + priv->status = NULL; + else + priv->status = g_strdup (status_message); g_object_notify (G_OBJECT (idle), "state"); g_object_notify (G_OBJECT (idle), "status"); @@ -265,7 +268,6 @@ idle_finalize (GObject *object) priv = GET_PRIV (object); g_free (priv->status); - g_object_unref (priv->mc); if (priv->gs_proxy) { g_object_unref (priv->gs_proxy); @@ -407,67 +409,22 @@ empathy_idle_class_init (EmpathyIdleClass *klass) g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv)); } -static TpConnectionPresenceType -empathy_idle_get_actual_presence (EmpathyIdle *idle, GError **error) -{ - McPresence presence; - EmpathyIdlePriv *priv = GET_PRIV (idle); - - presence = mission_control_get_presence_actual (priv->mc, error); - - switch (presence) { - case MC_PRESENCE_OFFLINE: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - case MC_PRESENCE_AVAILABLE: - return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE; - case MC_PRESENCE_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_AWAY; - case MC_PRESENCE_EXTENDED_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY; - case MC_PRESENCE_HIDDEN: - return TP_CONNECTION_PRESENCE_TYPE_HIDDEN; - case MC_PRESENCE_DO_NOT_DISTURB: - return TP_CONNECTION_PRESENCE_TYPE_BUSY; - default: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - } -} - static void empathy_idle_init (EmpathyIdle *idle) { - GError *error = NULL; EmpathyIdlePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle, EMPATHY_TYPE_IDLE, EmpathyIdlePriv); idle->priv = priv; priv->is_idle = FALSE; - priv->mc = empathy_mission_control_dup_singleton (); - priv->state = empathy_idle_get_actual_presence (idle, &error); - if (error) { - DEBUG ("Error getting actual presence: %s", error->message); - - /* Fallback to OFFLINE as that's what mission_control_get_presence_actual - does. This also ensure to always display the status icon (there is no - unset presence icon). */ - priv->state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - g_clear_error (&error); - } - priv->status = mission_control_get_presence_message_actual (priv->mc, &error); - if (error || EMP_STR_EMPTY (priv->status)) { - g_free (priv->status); - priv->status = NULL; - if (error) { - DEBUG ("Error getting actual presence message: %s", error->message); - g_clear_error (&error); - } - } + priv->manager = empathy_account_manager_dup_singleton (); + priv->state = empathy_account_manager_get_global_presence (priv->manager, + NULL, &priv->status); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), - "PresenceChanged", - G_CALLBACK (idle_presence_changed_cb), - idle, NULL); + + g_signal_connect (priv->manager, "global-presence-changed", + G_CALLBACK (idle_presence_changed_cb), idle); priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (), "org.gnome.SessionManager", @@ -568,36 +525,31 @@ empathy_idle_set_flash_state (EmpathyIdle *idle, static void empathy_idle_do_set_presence (EmpathyIdle *idle, - TpConnectionPresenceType state, - const gchar *status) + TpConnectionPresenceType status_type, + const gchar *status_message) { - McPresence mc_state = MC_PRESENCE_UNSET; EmpathyIdlePriv *priv = GET_PRIV (idle); + const gchar *statuses[NUM_TP_CONNECTION_PRESENCE_TYPES] = { + NULL, + "offline", + "available", + "away", + "xa", + "hidden", + "busy", + NULL, + NULL, + }; + const gchar *status; - switch (state) { - case TP_CONNECTION_PRESENCE_TYPE_OFFLINE: - mc_state = MC_PRESENCE_OFFLINE; - break; - case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE: - mc_state = MC_PRESENCE_AVAILABLE; - break; - case TP_CONNECTION_PRESENCE_TYPE_AWAY: - mc_state = MC_PRESENCE_AWAY; - break; - case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY: - mc_state = MC_PRESENCE_EXTENDED_AWAY; - break; - case TP_CONNECTION_PRESENCE_TYPE_HIDDEN: - mc_state = MC_PRESENCE_HIDDEN; - break; - case TP_CONNECTION_PRESENCE_TYPE_BUSY: - mc_state = MC_PRESENCE_DO_NOT_DISTURB; - break; - default: - g_assert_not_reached (); - } + g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES); + + status = statuses[status_type]; + + g_return_if_fail (status != NULL); - mission_control_set_presence (priv->mc, mc_state, status, NULL, NULL); + empathy_account_manager_request_global_presence (priv->manager, + status_type, status, status_message); } void diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h index d0b426e59..47dcfee23 100644 --- a/libempathy/empathy-idle.h +++ b/libempathy/empathy-idle.h @@ -24,7 +24,7 @@ #include <glib.h> -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/enums.h> G_BEGIN_DECLS diff --git a/libempathy/empathy-log-manager.c b/libempathy/empathy-log-manager.c index c1e20f487..309b3b60f 100644 --- a/libempathy/empathy-log-manager.c +++ b/libempathy/empathy-log-manager.c @@ -29,6 +29,7 @@ #include <glib/gstdio.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-log-manager.h" #include "empathy-log-store-empathy.h" diff --git a/libempathy/empathy-log-manager.h b/libempathy/empathy-log-manager.h index 6907e2ede..a67f6e8dd 100644 --- a/libempathy/empathy-log-manager.h +++ b/libempathy/empathy-log-manager.h @@ -26,8 +26,6 @@ #include <glib-object.h> -#include <libmissioncontrol/mc-account.h> - #include "empathy-message.h" #include "empathy-dispatcher.h" diff --git a/libempathy/empathy-log-store-empathy.c b/libempathy/empathy-log-store-empathy.c index b814defe7..9963bfc44 100644 --- a/libempathy/empathy-log-store-empathy.c +++ b/libempathy/empathy-log-store-empathy.c @@ -36,6 +36,9 @@ #include <glib/gstdio.h> #define G_DISABLE_DEPRECATED +#include <telepathy-glib/util.h> +#include <telepathy-glib/defs.h> + #include "empathy-log-store.h" #include "empathy-log-store-empathy.h" #include "empathy-log-manager.h" @@ -105,33 +108,48 @@ empathy_log_store_empathy_init (EmpathyLogStoreEmpathy *self) self->priv = priv; - priv->basedir = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), - ".gnome2", PACKAGE_NAME, "logs", NULL); + priv->basedir = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), + PACKAGE_NAME, "logs", NULL); priv->name = g_strdup ("Empathy"); priv->account_manager = empathy_account_manager_dup_singleton (); } static gchar * +log_store_account_to_dirname (EmpathyAccount *account) +{ + const gchar *name; + + name = empathy_account_get_unique_name (account); + if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE)) + name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + return g_strdelimit (g_strdup (name), "/", '_'); +} + + +static gchar * log_store_empathy_get_dir (EmpathyLogStore *self, EmpathyAccount *account, const gchar *chat_id, gboolean chatroom) { - const gchar *account_id; gchar *basedir; + gchar *escaped; EmpathyLogStoreEmpathyPriv *priv; priv = GET_PRIV (self); - account_id = empathy_account_get_unique_name (account); + escaped = log_store_account_to_dirname (account); if (chatroom) - basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, account_id, + basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, escaped, LOG_DIR_CHATROOMS, chat_id, NULL); else basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, - account_id, chat_id, NULL); + escaped, chat_id, NULL); + + g_free (escaped); return basedir; } @@ -371,10 +389,11 @@ log_store_empathy_search_hit_new (EmpathyLogStore *self, { EmpathyLogStoreEmpathyPriv *priv = GET_PRIV (self); EmpathyLogSearchHit *hit; - const gchar *account_name; + gchar *account_name; const gchar *end; gchar **strv; guint len; + GList *accounts, *l; if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX)) return NULL; @@ -394,8 +413,25 @@ log_store_empathy_search_hit_new (EmpathyLogStore *self, else account_name = strv[len-3]; - hit->account = empathy_account_manager_lookup (priv->account_manager, - account_name); + accounts = empathy_account_manager_dup_accounts (priv->account_manager); + + for (l = accounts; l != NULL; l = g_list_next (l)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (l->data); + gchar *name; + + name = log_store_account_to_dirname (account); + if (!tp_strdiff (name, account_name)) + { + g_assert (hit->account == NULL); + hit->account = account; + g_object_ref (account); + } + g_object_unref (account); + g_free (name); + } + g_list_free (accounts); + hit->filename = g_strdup (filename); g_strfreev (strv); @@ -428,9 +464,15 @@ log_store_empathy_get_messages_for_file (EmpathyLogStore *self, /* Get the account from the filename */ hit = log_store_empathy_search_hit_new (self, filename); - account = g_object_ref (hit->account); + + if (hit->account != NULL) + account = g_object_ref (hit->account); + empathy_log_manager_search_hit_free (hit); + if (hit->account == NULL) + return NULL; + /* Create parser. */ ctxt = xmlNewParserCtxt (); @@ -708,8 +750,7 @@ log_store_empathy_get_chats (EmpathyLogStore *self, priv = GET_PRIV (self); - dir = g_build_filename (priv->basedir, - empathy_account_get_unique_name (account), NULL); + dir = log_store_empathy_get_dir (self, account, NULL, FALSE); hits = log_store_empathy_get_chats_for_dir (self, dir, FALSE); diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 9300364d5..69057a878 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -26,6 +26,7 @@ #include <telepathy-glib/channel.h> #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-chat.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c index f62c7f12f..6b4c20b53 100644 --- a/libempathy/empathy-tp-contact-factory.c +++ b/libempathy/empathy-tp-contact-factory.c @@ -26,6 +26,8 @@ #include <telepathy-glib/util.h> #include <telepathy-glib/gtypes.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> + #if HAVE_GEOCLUE #include <geoclue/geoclue-geocode.h> #endif diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 71d8efa67..2bf2ec416 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -29,6 +29,7 @@ #include <telepathy-glib/connection.h> #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-contact-list.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c index e60b2999d..c43fa0be7 100644 --- a/libempathy/empathy-tp-file.c +++ b/libempathy/empathy-tp-file.c @@ -40,6 +40,7 @@ #include <telepathy-glib/gtypes.h> #include <telepathy-glib/proxy-subclass.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-file.h" #include "empathy-marshal.h" diff --git a/libempathy/empathy-tp-roomlist.c b/libempathy/empathy-tp-roomlist.c index b3d955ee4..54d232339 100644 --- a/libempathy/empathy-tp-roomlist.c +++ b/libempathy/empathy-tp-roomlist.c @@ -26,6 +26,7 @@ #include <telepathy-glib/channel.h> #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-account.h" @@ -517,6 +518,10 @@ empathy_tp_roomlist_stop (EmpathyTpRoomlist *list) EmpathyTpRoomlistPriv *priv = GET_PRIV (list); g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list)); + + if (priv->channel == NULL) + return; + g_return_if_fail (TP_IS_CHANNEL (priv->channel)); tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1, diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c index fd54c9a98..db35e94dd 100644 --- a/libempathy/empathy-utils.c +++ b/libempathy/empathy-utils.c @@ -227,36 +227,6 @@ empathy_xml_node_find_child_prop_value (xmlNodePtr node, return found; } -guint -empathy_account_hash (gconstpointer key) -{ - g_return_val_if_fail (EMPATHY_IS_ACCOUNT (key), 0); - - return g_str_hash (empathy_account_get_unique_name (EMPATHY_ACCOUNT (key))); -} - -gboolean -empathy_account_equal (gconstpointer a, - gconstpointer b) -{ - return a == b; -} - -MissionControl * -empathy_mission_control_dup_singleton (void) -{ - static MissionControl *mc = NULL; - - if (!mc) { - mc = mission_control_new (tp_get_bus ()); - g_object_add_weak_pointer (G_OBJECT (mc), (gpointer) &mc); - } else { - g_object_ref (mc); - } - - return mc; -} - const gchar * empathy_presence_get_default_message (TpConnectionPresenceType presence) { @@ -378,3 +348,19 @@ empathy_uint_compare (gconstpointer a, return *(guint *) a - *(guint *) b; } +gchar * +empathy_protocol_icon_name (const gchar *protocol) +{ + return g_strdup_printf ("im-%s", protocol); +} + +GType +empathy_type_dbus_ao (void) +{ + static GType t = 0; + + if (G_UNLIKELY (t == 0)) + t = dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH); + + return t; +} diff --git a/libempathy/empathy-utils.h b/libempathy/empathy-utils.h index 42acbc8e3..c6aebb4f2 100644 --- a/libempathy/empathy-utils.h +++ b/libempathy/empathy-utils.h @@ -32,8 +32,6 @@ #include <libxml/parser.h> #include <libxml/tree.h> -#include <libmissioncontrol/mission-control.h> - #include "empathy-contact.h" #define EMPATHY_GET_PRIV(obj,type) ((type##Priv *) ((type *) obj)->priv) @@ -64,10 +62,6 @@ xmlNodePtr empathy_xml_node_find_child_prop_value (xmlNodePtr node, const gchar *prop_value); /* Others */ -guint empathy_account_hash (gconstpointer key); -gboolean empathy_account_equal (gconstpointer a, - gconstpointer b); -MissionControl *empathy_mission_control_dup_singleton (void); const gchar * empathy_presence_get_default_message (TpConnectionPresenceType presence); const gchar * empathy_presence_to_str (TpConnectionPresenceType presence); TpConnectionPresenceType empathy_presence_from_str (const gchar *str); @@ -80,6 +74,11 @@ gboolean empathy_check_available_state (void); gint empathy_uint_compare (gconstpointer a, gconstpointer b); +gchar *empathy_protocol_icon_name (const gchar *protocol); + +#define EMPATHY_ARRAY_TYPE_OBJECT (empathy_type_dbus_ao ()) +GType empathy_type_dbus_ao (void); + G_END_DECLS #endif /* __EMPATHY_UTILS_H__ */ |