]> git.0d.be Git - empathy.git/blob - libempathy/empathy-connection-aggregator.c
Merge remote-tracking branch 'jonny/ft'
[empathy.git] / libempathy / empathy-connection-aggregator.c
1 /*
2  * empathy-connection-aggregator.c - Source for EmpathyConnectionAggregator
3  * Copyright (C) 2010 Collabora Ltd.
4  * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include <config.h>
22
23 #include "empathy-connection-aggregator.h"
24
25 #include <telepathy-glib/telepathy-glib.h>
26
27 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
28 #include "empathy-debug.h"
29 #include "empathy-utils.h"
30
31
32 #include "extensions/extensions.h"
33
34 G_DEFINE_TYPE (EmpathyConnectionAggregator, empathy_connection_aggregator, 
35     G_TYPE_OBJECT);
36
37 struct _EmpathyConnectionAggregatorPriv {
38   TpAccountManager *mgr;
39
40   /* List of owned TpConnection */
41   GList *conns;
42 };
43
44 static void
45 empathy_connection_aggregator_dispose (GObject *object)
46 {
47   EmpathyConnectionAggregator *self = (EmpathyConnectionAggregator *) object;
48
49   g_clear_object (&self->priv->mgr);
50
51   g_list_free_full (self->priv->conns, g_object_unref);
52   self->priv->conns = NULL;
53
54   G_OBJECT_CLASS (empathy_connection_aggregator_parent_class)->dispose (object);
55 }
56
57 static void
58 empathy_connection_aggregator_class_init (
59     EmpathyConnectionAggregatorClass *klass)
60 {
61   GObjectClass *oclass = G_OBJECT_CLASS (klass);
62
63   oclass->dispose = empathy_connection_aggregator_dispose;
64
65   g_type_class_add_private (klass, sizeof (EmpathyConnectionAggregatorPriv));
66 }
67
68 static void
69 conn_invalidated_cb (TpConnection *conn,
70     guint domain,
71     gint code,
72     gchar *message,
73     EmpathyConnectionAggregator *self)
74 {
75   self->priv->conns = g_list_remove (self->priv->conns, conn);
76
77   g_object_unref (conn);
78 }
79
80 static void
81 check_connection (EmpathyConnectionAggregator *self,
82     TpConnection *conn)
83 {
84   if (g_list_find (self->priv->conns, conn) != NULL)
85     return;
86
87   self->priv->conns = g_list_prepend (self->priv->conns,
88       g_object_ref (conn));
89
90   tp_g_signal_connect_object (conn, "invalidated",
91       G_CALLBACK (conn_invalidated_cb), self, 0);
92 }
93
94 static void
95 check_account (EmpathyConnectionAggregator *self,
96     TpAccount *account)
97 {
98   TpConnection *conn;
99
100   conn = tp_account_get_connection (account);
101   if (conn != NULL)
102     check_connection (self, conn);
103 }
104
105 static void
106 account_conn_changed_cb (TpAccount *account,
107     GParamSpec *spec,
108     EmpathyConnectionAggregator *self)
109 {
110   check_account (self, account);
111 }
112
113 static void
114 add_account (EmpathyConnectionAggregator *self,
115     TpAccount *account)
116 {
117   check_account (self, account);
118
119   tp_g_signal_connect_object (account, "notify::connection",
120       G_CALLBACK (account_conn_changed_cb), self, 0);
121 }
122
123 static void
124 account_validity_changed_cb (TpAccountManager *manager,
125     TpAccount *account,
126     gboolean valid,
127     EmpathyConnectionAggregator *self)
128 {
129   if (valid)
130     add_account (self, account);
131 }
132
133 static void
134 am_prepare_cb (GObject *source,
135     GAsyncResult *result,
136     gpointer user_data)
137 {
138   EmpathyConnectionAggregator *self = EMPATHY_CONNECTION_AGGREGATOR (user_data);
139   GError *error = NULL;
140   GList *accounts, *l;
141
142   if (!tp_proxy_prepare_finish (source, result, &error))
143     {
144       DEBUG ("Failed to prepare account manager: %s", error->message);
145       g_error_free (error);
146       goto out;
147     }
148
149   accounts = tp_account_manager_get_valid_accounts (self->priv->mgr);
150   for (l = accounts; l != NULL; l = g_list_next (l))
151     {
152       TpAccount *account = l->data;
153
154       add_account (self, account);
155     }
156
157   tp_g_signal_connect_object (self->priv->mgr, "account-validity-changed",
158       G_CALLBACK (account_validity_changed_cb), self, 0);
159
160   g_list_free (accounts);
161
162 out:
163   g_object_unref (self);
164 }
165
166 static void
167 empathy_connection_aggregator_init (EmpathyConnectionAggregator *self)
168 {
169   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
170       EMPATHY_TYPE_CONNECTION_AGGREGATOR, EmpathyConnectionAggregatorPriv);
171
172   self->priv->mgr = tp_account_manager_dup ();
173
174   tp_proxy_prepare_async (self->priv->mgr, NULL, am_prepare_cb,
175       g_object_ref (self));
176 }
177
178 EmpathyConnectionAggregator *
179 empathy_connection_aggregator_dup_singleton (void)
180 {
181   static EmpathyConnectionAggregator *aggregator = NULL;
182
183   if (G_LIKELY (aggregator != NULL))
184       return g_object_ref (aggregator);
185
186   aggregator = g_object_new (EMPATHY_TYPE_CONNECTION_AGGREGATOR, NULL);
187
188   g_object_add_weak_pointer (G_OBJECT (aggregator), (gpointer *) &aggregator);
189   return aggregator;
190 }
191
192 GList *
193 empathy_connection_aggregator_get_all_groups (EmpathyConnectionAggregator *self)
194 {
195   GList *keys, *l;
196   GHashTable *set;
197
198   set = g_hash_table_new (g_str_hash, g_str_equal);
199
200   for (l = self->priv->conns; l != NULL; l = g_list_next (l))
201     {
202       TpConnection *conn = l->data;
203       const gchar * const *groups;
204       guint i;
205
206       groups = tp_connection_get_contact_groups (conn);
207       if (groups == NULL)
208         continue;
209
210       for (i = 0; groups[i] != NULL; i++)
211         g_hash_table_insert (set, (gchar *) groups[i], GUINT_TO_POINTER (TRUE));
212     }
213
214   keys = g_hash_table_get_keys (set);
215   g_hash_table_unref (set);
216
217   return keys;
218 }