]> git.0d.be Git - empathy.git/blob - libempathy/empathy-tp-contact-factory.c
Merge branch 'sasl'
[empathy.git] / libempathy / empathy-tp-contact-factory.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-2009 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include <config.h>
23
24 #include "empathy-tp-contact-factory.h"
25
26 #define DEBUG_FLAG EMPATHY_DEBUG_TP | EMPATHY_DEBUG_CONTACT
27 #include "empathy-debug.h"
28
29 static TpContactFeature contact_features[] = {
30         TP_CONTACT_FEATURE_ALIAS,
31         TP_CONTACT_FEATURE_AVATAR_DATA,
32         TP_CONTACT_FEATURE_PRESENCE,
33         TP_CONTACT_FEATURE_LOCATION,
34         TP_CONTACT_FEATURE_CAPABILITIES,
35         TP_CONTACT_FEATURE_CLIENT_TYPES,
36 };
37
38 typedef union {
39         EmpathyTpContactFactoryContactsByIdCb ids_cb;
40         EmpathyTpContactFactoryContactsByHandleCb handles_cb;
41         EmpathyTpContactFactoryContactCb contact_cb;
42 } GetContactsCb;
43
44 typedef struct {
45         TpConnection *connection;
46         GetContactsCb callback;
47         gpointer user_data;
48         GDestroyNotify destroy;
49 } GetContactsData;
50
51 static void
52 get_contacts_data_free (gpointer user_data)
53 {
54         GetContactsData *data = user_data;
55
56         if (data->destroy) {
57                 data->destroy (data->user_data);
58         }
59         g_object_unref (data->connection);
60
61         g_slice_free (GetContactsData, data);
62 }
63
64 static EmpathyContact **
65 contacts_array_new (guint n_contacts,
66                     TpContact * const * contacts)
67 {
68         EmpathyContact **ret;
69         guint            i;
70
71         ret = g_new0 (EmpathyContact *, n_contacts);
72         for (i = 0; i < n_contacts; i++) {
73                 ret[i] = empathy_contact_dup_from_tp_contact (contacts[i]);
74         }
75
76         return ret;
77 }
78
79 static void
80 contacts_array_free (guint            n_contacts,
81                      EmpathyContact **contacts)
82 {
83         guint i;
84
85         for (i = 0; i < n_contacts; i++) {
86                 g_object_unref (contacts[i]);
87         }
88         g_free (contacts);
89 }
90
91 static void
92 get_contacts_by_id_cb (TpConnection *connection,
93                        guint n_contacts,
94                        TpContact * const *contacts,
95                        const gchar * const *requested_ids,
96                        GHashTable *failed_id_errors,
97                        const GError *error,
98                        gpointer user_data,
99                        GObject *weak_object)
100 {
101         GetContactsData *data = user_data;
102         EmpathyContact **empathy_contacts;
103
104         empathy_contacts = contacts_array_new (n_contacts, contacts);
105         if (data->callback.ids_cb) {
106                 data->callback.ids_cb (data->connection,
107                                        n_contacts, empathy_contacts,
108                                        requested_ids,
109                                        failed_id_errors,
110                                        error,
111                                        data->user_data, weak_object);
112         }
113
114         contacts_array_free (n_contacts, empathy_contacts);
115 }
116
117 /* The callback is NOT given a reference to the EmpathyContact objects */
118 void
119 empathy_tp_contact_factory_get_from_ids (TpConnection            *connection,
120                                          guint                    n_ids,
121                                          const gchar * const     *ids,
122                                          EmpathyTpContactFactoryContactsByIdCb callback,
123                                          gpointer                 user_data,
124                                          GDestroyNotify           destroy,
125                                          GObject                 *weak_object)
126 {
127         GetContactsData *data;
128
129         g_return_if_fail (TP_IS_CONNECTION (connection));
130         g_return_if_fail (ids != NULL);
131
132         data = g_slice_new (GetContactsData);
133         data->callback.ids_cb = callback;
134         data->user_data = user_data;
135         data->destroy = destroy;
136         data->connection = g_object_ref (connection);
137         tp_connection_get_contacts_by_id (connection,
138                                           n_ids, ids,
139                                           G_N_ELEMENTS (contact_features),
140                                           contact_features,
141                                           get_contacts_by_id_cb,
142                                           data,
143                                           (GDestroyNotify) get_contacts_data_free,
144                                           weak_object);
145 }
146
147 static void
148 get_contact_by_id_cb (TpConnection *connection,
149                       guint n_contacts,
150                       TpContact * const *contacts,
151                       const gchar * const *requested_ids,
152                       GHashTable *failed_id_errors,
153                       const GError *error,
154                       gpointer user_data,
155                       GObject *weak_object)
156 {
157         GetContactsData *data = user_data;
158         EmpathyContact  *contact = NULL;
159
160         if (n_contacts == 1) {
161                 contact = empathy_contact_dup_from_tp_contact (contacts[0]);
162         }
163         else if (error == NULL) {
164                 GHashTableIter iter;
165                 gpointer       value;
166
167                 g_hash_table_iter_init (&iter, failed_id_errors);
168                 while (g_hash_table_iter_next (&iter, NULL, &value)) {
169                         if (value) {
170                                 error = value;
171                                 break;
172                         }
173                 }
174         }
175
176         if (data->callback.contact_cb) {
177                 data->callback.contact_cb (data->connection,
178                                            contact,
179                                            error,
180                                            data->user_data, weak_object);
181         }
182
183         if (contact != NULL)
184                 g_object_unref (contact);
185 }
186
187 /* The callback is NOT given a reference to the EmpathyContact objects */
188 void
189 empathy_tp_contact_factory_get_from_id (TpConnection            *connection,
190                                         const gchar             *id,
191                                         EmpathyTpContactFactoryContactCb callback,
192                                         gpointer                 user_data,
193                                         GDestroyNotify           destroy,
194                                         GObject                 *weak_object)
195 {
196         GetContactsData *data;
197
198         g_return_if_fail (TP_IS_CONNECTION (connection));
199         g_return_if_fail (id != NULL);
200
201         data = g_slice_new (GetContactsData);
202         data->callback.contact_cb = callback;
203         data->user_data = user_data;
204         data->destroy = destroy;
205         data->connection = g_object_ref (connection);
206         tp_connection_get_contacts_by_id (connection,
207                                           1, &id,
208                                           G_N_ELEMENTS (contact_features),
209                                           contact_features,
210                                           get_contact_by_id_cb,
211                                           data,
212                                           (GDestroyNotify) get_contacts_data_free,
213                                           weak_object);
214 }
215
216 static void
217 get_contacts_by_handle_cb (TpConnection *connection,
218                            guint n_contacts,
219                            TpContact * const *contacts,
220                            guint n_failed,
221                            const TpHandle *failed,
222                            const GError *error,
223                            gpointer user_data,
224                            GObject *weak_object)
225 {
226         GetContactsData *data = user_data;
227         EmpathyContact **empathy_contacts;
228
229         empathy_contacts = contacts_array_new (n_contacts, contacts);
230         if (data->callback.handles_cb) {
231                 data->callback.handles_cb (data->connection,
232                                            n_contacts, empathy_contacts,
233                                            n_failed, failed,
234                                            error,
235                                            data->user_data, weak_object);
236         }
237
238         contacts_array_free (n_contacts, empathy_contacts);
239 }
240
241 /* The callback is NOT given a reference to the EmpathyContact objects */
242 void
243 empathy_tp_contact_factory_get_from_handles (TpConnection *connection,
244                                              guint n_handles,
245                                              const TpHandle *handles,
246                                              EmpathyTpContactFactoryContactsByHandleCb callback,
247                                              gpointer                 user_data,
248                                              GDestroyNotify           destroy,
249                                              GObject                 *weak_object)
250 {
251         GetContactsData *data;
252
253         if (n_handles == 0) {
254                 callback (connection, 0, NULL, 0, NULL, NULL, user_data, weak_object);
255                 return;
256         }
257
258         g_return_if_fail (TP_IS_CONNECTION (connection));
259         g_return_if_fail (handles != NULL);
260
261         data = g_slice_new (GetContactsData);
262         data->callback.handles_cb = callback;
263         data->user_data = user_data;
264         data->destroy = destroy;
265         data->connection = g_object_ref (connection);
266         tp_connection_get_contacts_by_handle (connection,
267                                               n_handles, handles,
268                                               G_N_ELEMENTS (contact_features),
269                                               contact_features,
270                                               get_contacts_by_handle_cb,
271                                               data,
272                                               (GDestroyNotify) get_contacts_data_free,
273                                               weak_object);
274 }
275
276 /* The callback is NOT given a reference to the EmpathyContact objects */
277 static void
278 get_contact_by_handle_cb (TpConnection *connection,
279                           guint n_contacts,
280                           TpContact * const *contacts,
281                           guint n_failed,
282                           const TpHandle *failed,
283                           const GError *error,
284                           gpointer user_data,
285                           GObject *weak_object)
286 {
287         GetContactsData *data = user_data;
288         EmpathyContact  *contact = NULL;
289         GError *err = NULL;
290
291         if (n_contacts == 1) {
292                 contact = empathy_contact_dup_from_tp_contact (contacts[0]);
293         }
294         else {
295                 if (error == NULL) {
296                         /* tp-glib will provide an error only if the whole operation failed,
297                          * but not if, for example, the handle was invalid. We create an error
298                          * so the caller of empathy_tp_contact_factory_get_from_handle can
299                          * rely on the error to check if the operation succeeded or not. */
300
301                         err = g_error_new_literal (TP_ERRORS, TP_ERROR_INVALID_HANDLE,
302                                                       "handle is invalid");
303                 }
304                 else {
305                         err = g_error_copy (error);
306                 }
307         }
308
309         if (data->callback.contact_cb) {
310                 data->callback.contact_cb (data->connection,
311                                            contact,
312                                            err,
313                                            data->user_data, weak_object);
314         }
315
316         g_clear_error (&err);
317         if (contact != NULL)
318                 g_object_unref (contact);
319 }
320
321 void
322 empathy_tp_contact_factory_get_from_handle (TpConnection            *connection,
323                                             TpHandle                 handle,
324                                             EmpathyTpContactFactoryContactCb callback,
325                                             gpointer                 user_data,
326                                             GDestroyNotify           destroy,
327                                             GObject                 *weak_object)
328 {
329         GetContactsData *data;
330
331         g_return_if_fail (TP_IS_CONNECTION (connection));
332
333         data = g_slice_new (GetContactsData);
334         data->callback.contact_cb = callback;
335         data->user_data = user_data;
336         data->destroy = destroy;
337         data->connection = g_object_ref (connection);
338         tp_connection_get_contacts_by_handle (connection,
339                                               1, &handle,
340                                               G_N_ELEMENTS (contact_features),
341                                               contact_features,
342                                               get_contact_by_handle_cb,
343                                               data,
344                                               (GDestroyNotify) get_contacts_data_free,
345                                               weak_object);
346 }
347