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