2 * Copyright (C) 2008 Collabora Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
23 #include <libmissioncontrol/mc-account-monitor.h>
25 #include "empathy-account-manager.h"
26 #include "empathy-marshal.h"
27 #include "empathy-utils.h"
29 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager)
32 McAccountMonitor *monitor;
39 } EmpathyAccountManagerPriv;
43 TpConnectionStatus connection;
55 ACCOUNT_CONNECTION_CHANGED,
56 ACCOUNT_PRESENCE_CHANGED,
60 static guint signals[LAST_SIGNAL];
61 static EmpathyAccountManager *manager_singleton = NULL;
63 G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT);
66 account_data_new (McPresence presence,
67 TpConnectionStatus connection,
72 retval = g_slice_new0 (AccountData);
73 retval->presence = presence;
74 retval->connection = connection;
75 retval->is_enabled = is_enabled;
76 retval->source_id = 0;
82 account_data_new_default (MissionControl *mc,
86 TpConnectionStatus actual_c;
89 actual_p = mission_control_get_presence_actual (mc, &err);
92 actual_p = MC_PRESENCE_UNSET;
96 actual_c = mission_control_get_connection_status (mc, account, &err);
100 actual_c = TP_CONNECTION_STATUS_DISCONNECTED;
104 return account_data_new (actual_p, actual_c, mc_account_is_enabled (account));
108 account_data_free (AccountData *data)
110 if (data->source_id > 0)
112 g_source_remove (data->source_id);
116 g_slice_free (AccountData, data);
120 account_created_cb (McAccountMonitor *mon,
122 EmpathyAccountManager *manager)
125 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
127 account = mc_account_lookup (account_name);
133 data = account_data_new_default (priv->mc, account);
135 /* the reference returned by mc_account_lookup is owned by the
138 g_hash_table_insert (priv->accounts, account, data);
140 g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
145 account_deleted_cb (McAccountMonitor *mon,
147 EmpathyAccountManager *manager)
150 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
152 account = mc_account_lookup (account_name);
156 g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account);
158 g_hash_table_remove (priv->accounts, account);
159 g_object_unref (account);
164 account_changed_cb (McAccountMonitor *mon,
166 EmpathyAccountManager *manager)
170 account = mc_account_lookup (account_name);
174 g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
175 g_object_unref (account);
180 account_disabled_cb (McAccountMonitor *mon,
182 EmpathyAccountManager *manager)
185 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
188 account = mc_account_lookup (account_name);
192 data = g_hash_table_lookup (priv->accounts, account);
194 data->is_enabled = FALSE;
196 g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
197 g_object_unref (account);
202 account_enabled_cb (McAccountMonitor *mon,
204 EmpathyAccountManager *manager)
207 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
210 account = mc_account_lookup (account_name);
214 data = g_hash_table_lookup (priv->accounts, account);
216 data->is_enabled = TRUE;
218 g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
219 g_object_unref (account);
224 update_connection_numbers (EmpathyAccountManager *manager,
225 TpConnectionStatus conn,
226 TpConnectionStatus old_c)
228 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
230 if (conn == TP_CONNECTION_STATUS_CONNECTED)
233 if (old_c == TP_CONNECTION_STATUS_CONNECTING)
237 if (conn == TP_CONNECTION_STATUS_CONNECTING)
240 if (old_c == TP_CONNECTION_STATUS_CONNECTED)
244 if (conn == TP_CONNECTION_STATUS_DISCONNECTED)
246 if (old_c == TP_CONNECTION_STATUS_CONNECTED)
249 if (old_c == TP_CONNECTION_STATUS_CONNECTING)
255 remove_data_timeout (gpointer _data)
257 AccountData *data = _data;
265 account_status_changed_cb (MissionControl *mc,
266 TpConnectionStatus connection,
268 TpConnectionStatusReason reason,
269 const gchar *unique_name,
270 EmpathyAccountManager *manager)
273 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
276 TpConnectionStatus old_c;
277 gboolean emit_presence = FALSE, emit_connection = FALSE;
279 account = mc_account_lookup (unique_name);
283 data = g_hash_table_lookup (priv->accounts, account);
286 old_p = data->presence;
287 old_c = data->connection;
289 if (old_p != presence)
291 data->presence = presence;
292 emit_presence = TRUE;
295 if (old_c != connection)
297 data->connection = connection;
298 update_connection_numbers (manager, connection, old_c);
300 if (old_c == TP_CONNECTION_STATUS_CONNECTING &&
301 connection == TP_CONNECTION_STATUS_CONNECTED)
303 if (data->source_id > 0) {
304 g_source_remove (data->source_id);
308 data->source_id = g_timeout_add_seconds (10,
312 emit_connection = TRUE;
316 g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
317 account, presence, old_p);
320 g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
321 account, reason, connection, old_c);
323 g_object_unref (account);
328 empathy_account_manager_init (EmpathyAccountManager *manager)
330 EmpathyAccountManagerPriv *priv =
331 G_TYPE_INSTANCE_GET_PRIVATE (manager,
332 EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
333 GList *mc_accounts, *l;
334 guint initial_connection;
337 manager->priv = priv;
338 priv->monitor = mc_account_monitor_new ();
339 priv->mc = empathy_mission_control_new ();
340 priv->connected = priv->connecting = 0;
341 priv->dispose_run = FALSE;
343 priv->accounts = g_hash_table_new_full (empathy_account_hash,
344 empathy_account_equal,
346 (GDestroyNotify) account_data_free);
348 mc_accounts = mc_accounts_list ();
350 for (l = mc_accounts; l; l = l->next)
352 data = account_data_new_default (priv->mc, l->data);
354 initial_connection = mission_control_get_connection_status (priv->mc,
356 if (initial_connection == TP_CONNECTION_STATUS_CONNECTED) {
358 } else if (initial_connection == TP_CONNECTION_STATUS_CONNECTING) {
362 /* no need to g_object_ref () the account here, as mc_accounts_list ()
363 * already increases the refcount.
365 g_hash_table_insert (priv->accounts, l->data, data);
368 g_signal_connect (priv->monitor, "account-created",
369 G_CALLBACK (account_created_cb), manager);
370 g_signal_connect (priv->monitor, "account-deleted",
371 G_CALLBACK (account_deleted_cb), manager);
372 g_signal_connect (priv->monitor, "account-disabled",
373 G_CALLBACK (account_disabled_cb), manager);
374 g_signal_connect (priv->monitor, "account-enabled",
375 G_CALLBACK (account_enabled_cb), manager);
376 g_signal_connect (priv->monitor, "account-changed",
377 G_CALLBACK (account_changed_cb), manager);
379 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
380 G_CALLBACK (account_status_changed_cb),
383 g_list_free (mc_accounts);
387 disconnect_monitor_signals (McAccountMonitor *monitor,
390 g_signal_handlers_disconnect_by_func (monitor,
391 account_created_cb, obj);
392 g_signal_handlers_disconnect_by_func (monitor,
393 account_deleted_cb, obj);
394 g_signal_handlers_disconnect_by_func (monitor,
395 account_disabled_cb, obj);
396 g_signal_handlers_disconnect_by_func (monitor,
397 account_enabled_cb, obj);
398 g_signal_handlers_disconnect_by_func (monitor,
399 account_changed_cb, obj);
403 do_finalize (GObject *obj)
405 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
406 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
408 g_hash_table_unref (priv->accounts);
410 G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
414 do_dispose (GObject *obj)
416 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
417 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
419 if (priv->dispose_run)
422 priv->dispose_run = TRUE;
424 dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
425 "AccountStatusChanged",
426 G_CALLBACK (account_status_changed_cb),
429 disconnect_monitor_signals (priv->monitor, obj);
433 g_object_unref (priv->monitor);
434 priv->monitor = NULL;
438 g_object_unref (priv->mc);
440 g_hash_table_remove_all (priv->accounts);
442 G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj);
446 do_constructor (GType type,
447 guint n_construct_params,
448 GObjectConstructParam *construct_params)
452 if (!manager_singleton)
454 retval = G_OBJECT_CLASS (empathy_account_manager_parent_class)->constructor (type,
457 g_object_add_weak_pointer (retval, (gpointer *) &retval);
458 manager_singleton = EMPATHY_ACCOUNT_MANAGER (retval);
462 retval = g_object_ref (manager_singleton);
469 empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
471 GObjectClass *oclass = G_OBJECT_CLASS (klass);
473 oclass->finalize = do_finalize;
474 oclass->dispose = do_dispose;
475 oclass->constructor = do_constructor;
477 signals[ACCOUNT_CREATED] =
478 g_signal_new ("account-created",
479 G_TYPE_FROM_CLASS (klass),
483 g_cclosure_marshal_VOID__OBJECT,
487 signals[ACCOUNT_DELETED] =
488 g_signal_new ("account-deleted",
489 G_TYPE_FROM_CLASS (klass),
493 g_cclosure_marshal_VOID__OBJECT,
497 signals[ACCOUNT_ENABLED] =
498 g_signal_new ("account-enabled",
499 G_TYPE_FROM_CLASS (klass),
503 g_cclosure_marshal_VOID__OBJECT,
507 signals[ACCOUNT_DISABLED] =
508 g_signal_new ("account-disabled",
509 G_TYPE_FROM_CLASS (klass),
513 g_cclosure_marshal_VOID__OBJECT,
517 signals[ACCOUNT_CHANGED] =
518 g_signal_new ("account-changed",
519 G_TYPE_FROM_CLASS (klass),
523 g_cclosure_marshal_VOID__OBJECT,
527 signals[ACCOUNT_CONNECTION_CHANGED] =
528 g_signal_new ("account-connection-changed",
529 G_TYPE_FROM_CLASS (klass),
533 _empathy_marshal_VOID__OBJECT_INT_UINT_UINT,
536 G_TYPE_INT, /* reason */
537 G_TYPE_UINT, /* actual connection */
538 G_TYPE_UINT); /* previous connection */
540 signals[ACCOUNT_PRESENCE_CHANGED] =
541 g_signal_new ("account-presence-changed",
542 G_TYPE_FROM_CLASS (klass),
546 _empathy_marshal_VOID__OBJECT_INT_INT,
549 G_TYPE_INT, /* actual presence */
550 G_TYPE_INT); /* previous presence */
552 g_type_class_add_private (oclass, sizeof (EmpathyAccountManagerPriv));
557 EmpathyAccountManager *
558 empathy_account_manager_dup_singleton (void)
560 return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL);
564 empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager)
566 EmpathyAccountManagerPriv *priv;
568 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
570 priv = GET_PRIV (manager);
572 return priv->connected;
576 empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager)
578 EmpathyAccountManagerPriv *priv;
580 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
582 priv = GET_PRIV (manager);
584 return priv->connecting;
588 empathy_account_manager_is_account_just_connected (EmpathyAccountManager *manager,
591 EmpathyAccountManagerPriv *priv;
594 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
596 priv = GET_PRIV (manager);
597 data = g_hash_table_lookup (priv->accounts, account);
601 return (data->source_id > 0);