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);
99 actual_c = TP_CONNECTION_STATUS_DISCONNECTED;
101 return account_data_new (actual_p, actual_c, mc_account_is_enabled (account));
105 account_data_free (AccountData *data)
107 if (data->source_id > 0)
109 g_source_remove (data->source_id);
113 g_slice_free (AccountData, data);
117 account_created_cb (McAccountMonitor *mon,
119 EmpathyAccountManager *manager)
122 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
124 account = mc_account_lookup (account_name);
130 data = account_data_new_default (priv->mc, account);
132 g_hash_table_insert (priv->accounts, account, data);
134 g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
139 account_deleted_cb (McAccountMonitor *mon,
141 EmpathyAccountManager *manager)
144 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
146 account = mc_account_lookup (account_name);
150 g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account);
152 g_hash_table_remove (priv->accounts, account);
153 g_object_unref (account);
158 account_changed_cb (McAccountMonitor *mon,
160 EmpathyAccountManager *manager)
164 account = mc_account_lookup (account_name);
168 g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
169 g_object_unref (account);
174 account_disabled_cb (McAccountMonitor *mon,
176 EmpathyAccountManager *manager)
179 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
182 account = mc_account_lookup (account_name);
186 data = g_hash_table_lookup (priv->accounts, account);
188 data->is_enabled = FALSE;
190 g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
195 account_enabled_cb (McAccountMonitor *mon,
197 EmpathyAccountManager *manager)
200 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
203 account = mc_account_lookup (account_name);
207 data = g_hash_table_lookup (priv->accounts, account);
209 data->is_enabled = TRUE;
211 g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
212 g_object_unref (account);
217 update_connection_numbers (EmpathyAccountManager *manager,
218 TpConnectionStatus conn,
219 TpConnectionStatus old_c)
221 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
223 if (conn == TP_CONNECTION_STATUS_CONNECTED)
226 if (old_c == TP_CONNECTION_STATUS_CONNECTING)
230 if (conn == TP_CONNECTION_STATUS_CONNECTING)
233 if (old_c == TP_CONNECTION_STATUS_CONNECTED)
237 if (conn == TP_CONNECTION_STATUS_DISCONNECTED)
239 if (old_c == TP_CONNECTION_STATUS_CONNECTED)
242 if (old_c == TP_CONNECTION_STATUS_CONNECTING)
248 remove_data_timeout (gpointer _data)
250 AccountData *data = _data;
258 account_status_changed_cb (MissionControl *mc,
259 TpConnectionStatus connection,
261 TpConnectionStatusReason reason,
262 const gchar *unique_name,
263 EmpathyAccountManager *manager)
266 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
269 TpConnectionStatus old_c;
270 gboolean emit_presence = FALSE, emit_connection = FALSE;
272 account = mc_account_lookup (unique_name);
276 data = g_hash_table_lookup (priv->accounts, account);
279 old_p = data->presence;
280 old_c = data->connection;
282 if (old_p != presence)
284 data->presence = presence;
285 emit_presence = TRUE;
288 if (old_c != connection)
290 data->connection = connection;
291 update_connection_numbers (manager, connection, old_c);
293 if (old_c == TP_CONNECTION_STATUS_CONNECTING &&
294 connection == TP_CONNECTION_STATUS_CONNECTED)
296 if (data->source_id > 0) {
297 g_source_remove (data->source_id);
301 data->source_id = g_timeout_add_seconds (10,
305 emit_connection = TRUE;
309 g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
310 account, presence, old_p);
313 g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
314 account, reason, connection, old_c);
316 g_object_unref (account);
321 empathy_account_manager_init (EmpathyAccountManager *manager)
323 EmpathyAccountManagerPriv *priv =
324 G_TYPE_INSTANCE_GET_PRIVATE (manager,
325 EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
326 GList *mc_accounts, *l;
329 manager->priv = priv;
330 priv->monitor = mc_account_monitor_new ();
331 priv->mc = empathy_mission_control_new ();
332 priv->connected = priv->connecting = 0;
333 priv->dispose_run = FALSE;
335 priv->accounts = g_hash_table_new_full (empathy_account_hash,
336 empathy_account_equal,
338 (GDestroyNotify) account_data_free);
340 mc_accounts = mc_accounts_list ();
342 for (l = mc_accounts; l; l = l->next)
344 data = account_data_new_default (priv->mc, l->data);
346 /* no need to g_object_ref () the account here, as mc_accounts_list ()
347 * already increases the refcount.
349 g_hash_table_insert (priv->accounts, l->data, data);
352 g_signal_connect (priv->monitor, "account-created",
353 G_CALLBACK (account_created_cb), manager);
354 g_signal_connect (priv->monitor, "account-deleted",
355 G_CALLBACK (account_deleted_cb), manager);
356 g_signal_connect (priv->monitor, "account-disabled",
357 G_CALLBACK (account_disabled_cb), manager);
358 g_signal_connect (priv->monitor, "account-enabled",
359 G_CALLBACK (account_enabled_cb), manager);
360 g_signal_connect (priv->monitor, "account-changed",
361 G_CALLBACK (account_changed_cb), manager);
363 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
364 G_CALLBACK (account_status_changed_cb),
367 g_list_free (mc_accounts);
371 disconnect_monitor_signals (McAccountMonitor *monitor,
374 g_signal_handlers_disconnect_by_func (monitor,
375 account_created_cb, obj);
376 g_signal_handlers_disconnect_by_func (monitor,
377 account_deleted_cb, obj);
378 g_signal_handlers_disconnect_by_func (monitor,
379 account_disabled_cb, obj);
380 g_signal_handlers_disconnect_by_func (monitor,
381 account_enabled_cb, obj);
382 g_signal_handlers_disconnect_by_func (monitor,
383 account_changed_cb, obj);
387 do_finalize (GObject *obj)
389 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
390 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
392 g_hash_table_unref (priv->accounts);
394 G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
398 do_dispose (GObject *obj)
400 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
401 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
403 if (priv->dispose_run)
406 priv->dispose_run = TRUE;
408 dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
409 "AccountStatusChanged",
410 G_CALLBACK (account_status_changed_cb),
413 disconnect_monitor_signals (priv->monitor, obj);
417 g_object_unref (priv->monitor);
418 priv->monitor = NULL;
422 g_object_unref (priv->mc);
424 g_hash_table_remove_all (priv->accounts);
426 G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj);
430 do_constructor (GType type,
431 guint n_construct_params,
432 GObjectConstructParam *construct_params)
436 if (!manager_singleton)
438 retval = G_OBJECT_CLASS (empathy_account_manager_parent_class)->constructor (type,
441 manager_singleton = EMPATHY_ACCOUNT_MANAGER (retval);
444 retval = g_object_ref (manager_singleton);
450 empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
452 GObjectClass *oclass = G_OBJECT_CLASS (klass);
454 oclass->finalize = do_finalize;
455 oclass->dispose = do_dispose;
456 oclass->constructor = do_constructor;
458 signals[ACCOUNT_CREATED] =
459 g_signal_new ("account-created",
460 G_TYPE_FROM_CLASS (klass),
464 g_cclosure_marshal_VOID__OBJECT,
468 signals[ACCOUNT_DELETED] =
469 g_signal_new ("account-deleted",
470 G_TYPE_FROM_CLASS (klass),
474 g_cclosure_marshal_VOID__OBJECT,
478 signals[ACCOUNT_ENABLED] =
479 g_signal_new ("account-enabled",
480 G_TYPE_FROM_CLASS (klass),
484 g_cclosure_marshal_VOID__OBJECT,
488 signals[ACCOUNT_DISABLED] =
489 g_signal_new ("account-disabled",
490 G_TYPE_FROM_CLASS (klass),
494 g_cclosure_marshal_VOID__OBJECT,
498 signals[ACCOUNT_CHANGED] =
499 g_signal_new ("account-changed",
500 G_TYPE_FROM_CLASS (klass),
504 g_cclosure_marshal_VOID__OBJECT,
508 signals[ACCOUNT_CONNECTION_CHANGED] =
509 g_signal_new ("account-connection-changed",
510 G_TYPE_FROM_CLASS (klass),
514 _empathy_marshal_VOID__OBJECT_INT_UINT_UINT,
517 G_TYPE_INT, /* reason */
518 G_TYPE_UINT, /* actual connection */
519 G_TYPE_UINT); /* previous connection */
521 signals[ACCOUNT_PRESENCE_CHANGED] =
522 g_signal_new ("account-presence-changed",
523 G_TYPE_FROM_CLASS (klass),
527 _empathy_marshal_VOID__OBJECT_INT_INT,
530 G_TYPE_INT, /* actual presence */
531 G_TYPE_INT); /* previous presence */
533 g_type_class_add_private (oclass, sizeof (EmpathyAccountManagerPriv));
538 EmpathyAccountManager *
539 empathy_account_manager_new (void)
541 return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL);
545 empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager)
547 EmpathyAccountManagerPriv *priv;
549 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
551 priv = GET_PRIV (manager);
553 return priv->connected;
557 empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager)
559 EmpathyAccountManagerPriv *priv;
561 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
563 priv = GET_PRIV (manager);
565 return priv->connecting;
569 empathy_account_manager_is_account_just_connected (EmpathyAccountManager *manager,
572 EmpathyAccountManagerPriv *priv;
575 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
577 priv = GET_PRIV (manager);
578 data = g_hash_table_lookup (priv->accounts, account);
582 return (data->source_id > 0);