1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
3 * Copyright (C) 2008 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
24 #include <libmissioncontrol/mc-account-monitor.h>
26 #include "empathy-account-manager.h"
27 #include "empathy-marshal.h"
28 #include "empathy-utils.h"
30 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager)
33 McAccountMonitor *monitor;
40 } EmpathyAccountManagerPriv;
44 TpConnectionStatus connection;
56 ACCOUNT_CONNECTION_CHANGED,
57 ACCOUNT_PRESENCE_CHANGED,
61 static guint signals[LAST_SIGNAL];
62 static EmpathyAccountManager *manager = NULL;
64 G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT);
67 account_data_new (McPresence presence, 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);
91 actual_p = MC_PRESENCE_UNSET;
95 actual_c = mission_control_get_connection_status (mc,
98 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) {
108 g_source_remove (data->source_id);
112 g_slice_free (AccountData, data);
116 account_created_cb (McAccountMonitor *mon,
118 EmpathyAccountManager *manager)
121 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
123 account = mc_account_lookup (account_name);
128 data = account_data_new_default (priv->mc, account);
130 g_hash_table_insert (priv->accounts, account, data);
132 g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
137 account_deleted_cb (McAccountMonitor *mon,
139 EmpathyAccountManager *manager)
142 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
144 account = mc_account_lookup (account_name);
147 g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account);
149 g_hash_table_remove (priv->accounts, account);
150 g_object_unref (account);
155 account_changed_cb (McAccountMonitor *mon,
157 EmpathyAccountManager *manager)
161 account = mc_account_lookup (account_name);
164 g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
165 g_object_unref (account);
170 account_disabled_cb (McAccountMonitor *mon,
172 EmpathyAccountManager *manager)
175 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
178 account = mc_account_lookup (account_name);
181 data = g_hash_table_lookup (priv->accounts, account);
183 data->is_enabled = FALSE;
185 g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
190 account_enabled_cb (McAccountMonitor *mon,
192 EmpathyAccountManager *manager)
195 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
198 account = mc_account_lookup (account_name);
201 data = g_hash_table_lookup (priv->accounts, account);
203 data->is_enabled = TRUE;
205 g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
206 g_object_unref (account);
211 update_connection_numbers (EmpathyAccountManager *manager,
212 TpConnectionStatus conn,
213 TpConnectionStatus old_c)
215 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
217 if (conn == TP_CONNECTION_STATUS_CONNECTED) {
219 if (old_c == TP_CONNECTION_STATUS_CONNECTING) {
224 if (conn == TP_CONNECTION_STATUS_CONNECTING) {
226 if (old_c == TP_CONNECTION_STATUS_CONNECTED) {
231 if (conn == TP_CONNECTION_STATUS_DISCONNECTED) {
232 if (old_c == TP_CONNECTION_STATUS_CONNECTED) {
235 if (old_c == TP_CONNECTION_STATUS_CONNECTING) {
242 remove_data_timeout (gpointer _data)
244 AccountData *data = _data;
252 account_status_changed_cb (MissionControl *mc,
253 TpConnectionStatus connection,
255 TpConnectionStatusReason reason,
256 const gchar *unique_name,
257 EmpathyAccountManager *manager)
260 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
263 TpConnectionStatus old_c;
264 gboolean emit_presence = FALSE, emit_connection = FALSE;
266 account = mc_account_lookup (unique_name);
269 data = g_hash_table_lookup (priv->accounts, account);
272 old_p = data->presence;
273 old_c = data->connection;
275 if (old_p != presence) {
276 data->presence = presence;
277 emit_presence = TRUE;
280 if (old_c != connection) {
281 data->connection = connection;
282 update_connection_numbers (manager, connection, old_c);
284 if (old_c == TP_CONNECTION_STATUS_CONNECTING &&
285 connection == TP_CONNECTION_STATUS_CONNECTED) {
286 if (data->source_id > 0) {
287 g_source_remove (data->source_id);
291 data->source_id = g_timeout_add_seconds (10,
295 emit_connection = TRUE;
299 g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
300 account, presence, old_p);
303 if (emit_connection) {
304 g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
305 account, reason, connection, old_c);
309 g_object_unref (account);
314 empathy_account_manager_init (EmpathyAccountManager *manager)
316 EmpathyAccountManagerPriv *priv =
317 G_TYPE_INSTANCE_GET_PRIVATE (manager,
318 EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
319 GList *mc_accounts, *l;
322 manager->priv = priv;
323 priv->monitor = mc_account_monitor_new ();
324 priv->mc = empathy_mission_control_new ();
325 priv->connected = priv->connecting = 0;
326 priv->dispose_run = FALSE;
328 priv->accounts = g_hash_table_new_full (empathy_account_hash,
329 empathy_account_equal,
331 (GDestroyNotify) account_data_free);
333 mc_accounts = mc_accounts_list ();
335 for (l = mc_accounts; l; l = l->next) {
336 data = account_data_new_default (priv->mc, l->data);
338 /* no need to g_object_ref () the account here, as mc_accounts_list ()
339 * already increases the refcount.
341 g_hash_table_insert (priv->accounts, l->data, data);
344 g_signal_connect (priv->monitor, "account-created",
345 G_CALLBACK (account_created_cb), manager);
346 g_signal_connect (priv->monitor, "account-deleted",
347 G_CALLBACK (account_deleted_cb), manager);
348 g_signal_connect (priv->monitor, "account-disabled",
349 G_CALLBACK (account_disabled_cb), manager);
350 g_signal_connect (priv->monitor, "account-enabled",
351 G_CALLBACK (account_enabled_cb), manager);
352 g_signal_connect (priv->monitor, "account-changed",
353 G_CALLBACK (account_changed_cb), manager);
355 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
356 G_CALLBACK (account_status_changed_cb),
359 g_list_free (mc_accounts);
363 disconnect_monitor_signals (McAccountMonitor *monitor,
366 g_signal_handlers_disconnect_by_func (monitor,
367 account_created_cb, obj);
368 g_signal_handlers_disconnect_by_func (monitor,
369 account_deleted_cb, obj);
370 g_signal_handlers_disconnect_by_func (monitor,
371 account_disabled_cb, obj);
372 g_signal_handlers_disconnect_by_func (monitor,
373 account_enabled_cb, obj);
374 g_signal_handlers_disconnect_by_func (monitor,
375 account_changed_cb, obj);
379 do_finalize (GObject *obj)
381 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
382 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
384 g_hash_table_unref (priv->accounts);
386 G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
390 do_dispose (GObject *obj)
392 EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
393 EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
395 if (priv->dispose_run) {
399 dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
400 "AccountStatusChanged",
401 G_CALLBACK (account_status_changed_cb),
404 disconnect_monitor_signals (priv->monitor, obj);
407 g_object_unref (priv->monitor);
408 priv->monitor = NULL;
412 g_object_unref (priv->mc);
415 g_hash_table_remove_all (priv->accounts);
417 priv->dispose_run = TRUE;
419 G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj);
423 empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
425 GObjectClass *oclass = G_OBJECT_CLASS (klass);
427 oclass->finalize = do_finalize;
428 oclass->dispose = do_dispose;
430 signals[ACCOUNT_CREATED] =
431 g_signal_new ("account-created",
432 G_TYPE_FROM_CLASS (klass),
436 g_cclosure_marshal_VOID__OBJECT,
440 signals[ACCOUNT_DELETED] =
441 g_signal_new ("account-deleted",
442 G_TYPE_FROM_CLASS (klass),
446 g_cclosure_marshal_VOID__OBJECT,
450 signals[ACCOUNT_ENABLED] =
451 g_signal_new ("account-enabled",
452 G_TYPE_FROM_CLASS (klass),
456 g_cclosure_marshal_VOID__OBJECT,
460 signals[ACCOUNT_DISABLED] =
461 g_signal_new ("account-disabled",
462 G_TYPE_FROM_CLASS (klass),
466 g_cclosure_marshal_VOID__OBJECT,
470 signals[ACCOUNT_CHANGED] =
471 g_signal_new ("account-changed",
472 G_TYPE_FROM_CLASS (klass),
476 g_cclosure_marshal_VOID__OBJECT,
480 signals[ACCOUNT_CONNECTION_CHANGED] =
481 g_signal_new ("account-connection-changed",
482 G_TYPE_FROM_CLASS (klass),
486 _empathy_marshal_VOID__OBJECT_INT_UINT_UINT,
489 G_TYPE_INT, /* reason */
490 G_TYPE_UINT, /* actual connection */
491 G_TYPE_UINT); /* previous connection */
493 signals[ACCOUNT_PRESENCE_CHANGED] =
494 g_signal_new ("account-presence-changed",
495 G_TYPE_FROM_CLASS (klass),
499 _empathy_marshal_VOID__OBJECT_INT_INT,
502 G_TYPE_INT, /* actual presence */
503 G_TYPE_INT); /* previous presence */
505 g_type_class_add_private (oclass, sizeof (EmpathyAccountManagerPriv));
510 EmpathyAccountManager *
511 empathy_account_manager_new (void)
514 manager = g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL);
515 g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
517 g_object_ref (manager);
524 empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager)
526 EmpathyAccountManagerPriv *priv;
528 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
530 priv = GET_PRIV (manager);
532 return priv->connected;
536 empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager)
538 EmpathyAccountManagerPriv *priv;
540 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
542 priv = GET_PRIV (manager);
544 return priv->connecting;
548 empathy_account_manager_is_account_just_connected (EmpathyAccountManager *manager,
551 EmpathyAccountManagerPriv *priv;
554 g_assert (EMPATHY_IS_ACCOUNT_MANAGER (manager));
556 priv = GET_PRIV (manager);
557 data = g_hash_table_lookup (priv->accounts, account);
561 return (data->source_id > 0);