aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy')
-rw-r--r--libempathy/Makefile.am5
-rw-r--r--libempathy/empathy-account-manager.c759
-rw-r--r--libempathy/empathy-account-manager.h55
-rw-r--r--libempathy/empathy-account-priv.h44
-rw-r--r--libempathy/empathy-account-settings.c1179
-rw-r--r--libempathy/empathy-account-settings.h163
-rw-r--r--libempathy/empathy-account.c920
-rw-r--r--libempathy/empathy-account.h59
-rw-r--r--libempathy/empathy-call-handler.c1
-rw-r--r--libempathy/empathy-chatroom-manager.c21
-rw-r--r--libempathy/empathy-chatroom.c3
-rw-r--r--libempathy/empathy-connection-managers.c293
-rw-r--r--libempathy/empathy-connection-managers.h77
-rw-r--r--libempathy/empathy-contact.c13
-rw-r--r--libempathy/empathy-debug.c1
-rw-r--r--libempathy/empathy-debug.h1
-rw-r--r--libempathy/empathy-dispatcher.c349
-rw-r--r--libempathy/empathy-dispatcher.h2
-rw-r--r--libempathy/empathy-ft-handler.c1
-rw-r--r--libempathy/empathy-idle.c124
-rw-r--r--libempathy/empathy-idle.h2
-rw-r--r--libempathy/empathy-log-manager.c1
-rw-r--r--libempathy/empathy-log-manager.h2
-rw-r--r--libempathy/empathy-log-store-empathy.c65
-rw-r--r--libempathy/empathy-tp-chat.c1
-rw-r--r--libempathy/empathy-tp-contact-factory.c2
-rw-r--r--libempathy/empathy-tp-contact-list.c1
-rw-r--r--libempathy/empathy-tp-file.c1
-rw-r--r--libempathy/empathy-tp-roomlist.c5
-rw-r--r--libempathy/empathy-utils.c46
-rw-r--r--libempathy/empathy-utils.h11
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__ */