]> git.0d.be Git - empathy.git/blob - libempathy/empathy-tp-roomlist.c
Do not load avatar from cache if token is empty. Fixes bug #517098.
[empathy.git] / libempathy / empathy-tp-roomlist.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 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 <string.h>
25
26 #include <libtelepathy/tp-chan-type-room-list-gen.h>
27 #include <libtelepathy/tp-helpers.h>
28 #include <libtelepathy/tp-conn.h>
29 #include <libtelepathy/tp-chan.h>
30
31 #include <libmissioncontrol/mission-control.h>
32
33 #include "empathy-tp-roomlist.h"
34 #include "empathy-chatroom.h"
35 #include "empathy-utils.h"
36 #include "empathy-debug.h"
37
38 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
39                        EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
40
41 #define DEBUG_DOMAIN "TpRoomlist"
42
43 struct _EmpathyTpRoomlistPriv {
44         McAccount  *account;
45         TpChan     *tp_chan;
46         DBusGProxy *roomlist_iface;
47 };
48
49 static void empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass);
50 static void empathy_tp_roomlist_init       (EmpathyTpRoomlist      *chat);
51 static void tp_roomlist_finalize           (GObject                *object);
52 static void tp_roomlist_destroy_cb         (TpChan                 *tp_chan,
53                                             EmpathyTpRoomlist      *list);
54 static void tp_roomlist_closed_cb          (TpChan                 *tp_chan,
55                                             EmpathyTpRoomlist      *list);
56 static void tp_roomlist_listing_cb         (DBusGProxy             *roomlist_iface,
57                                             gboolean                listing,
58                                             EmpathyTpRoomlist      *list);
59 static void tp_roomlist_got_rooms_cb       (DBusGProxy             *roomlist_iface,
60                                             GPtrArray              *room_list,
61                                             EmpathyTpRoomlist      *list);
62
63 enum {
64         NEW_ROOM,
65         LISTING,
66         DESTROY,
67         LAST_SIGNAL
68 };
69
70 static guint signals[LAST_SIGNAL];
71
72 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
73
74 static void
75 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
76 {
77         GObjectClass *object_class = G_OBJECT_CLASS (klass);
78
79         object_class->finalize = tp_roomlist_finalize;
80
81         signals[NEW_ROOM] =
82                 g_signal_new ("new-room",
83                               G_TYPE_FROM_CLASS (klass),
84                               G_SIGNAL_RUN_LAST,
85                               0,
86                               NULL, NULL,
87                               g_cclosure_marshal_VOID__OBJECT,
88                               G_TYPE_NONE,
89                               1, EMPATHY_TYPE_CHATROOM);
90
91         signals[LISTING] =
92                 g_signal_new ("listing",
93                               G_TYPE_FROM_CLASS (klass),
94                               G_SIGNAL_RUN_LAST,
95                               0,
96                               NULL, NULL,
97                               g_cclosure_marshal_VOID__BOOLEAN,
98                               G_TYPE_NONE,
99                               1, G_TYPE_BOOLEAN);
100
101         signals[DESTROY] =
102                 g_signal_new ("destroy",
103                               G_TYPE_FROM_CLASS (klass),
104                               G_SIGNAL_RUN_LAST,
105                               0,
106                               NULL, NULL,
107                               g_cclosure_marshal_VOID__VOID,
108                               G_TYPE_NONE,
109                               0);
110
111         g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
112 }
113
114 static void
115 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
116 {
117 }
118
119 static void
120 tp_roomlist_finalize (GObject *object)
121 {
122         EmpathyTpRoomlistPriv *priv;
123         GError                *error = NULL;
124
125         priv = GET_PRIV (object);
126
127         if (priv->tp_chan) {
128                 g_signal_handlers_disconnect_by_func (priv->tp_chan,
129                                                       tp_roomlist_destroy_cb,
130                                                       object);
131
132                 empathy_debug (DEBUG_DOMAIN, "Closing channel...");
133                 if (!tp_chan_close (DBUS_G_PROXY (priv->tp_chan), &error)) {
134                         empathy_debug (DEBUG_DOMAIN, 
135                                       "Error closing roomlist channel: %s",
136                                       error ? error->message : "No error given");
137                         g_clear_error (&error);
138                 }
139                 g_object_unref (priv->tp_chan);
140         }
141
142         if (priv->account) {
143                 g_object_unref (priv->account);
144         }
145
146         G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
147 }
148
149 EmpathyTpRoomlist *
150 empathy_tp_roomlist_new (McAccount *account)
151 {
152         EmpathyTpRoomlist     *list;
153         EmpathyTpRoomlistPriv *priv;
154         TpConn                *tp_conn;
155         MissionControl        *mc;
156         const gchar           *bus_name;
157
158         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
159
160         list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST, NULL);
161         priv = GET_PRIV (list);
162
163         mc = empathy_mission_control_new ();
164         tp_conn = mission_control_get_connection (mc, account, NULL);
165         g_object_unref (mc);
166
167         bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (tp_conn));
168         priv->tp_chan = tp_conn_new_channel (tp_get_bus (),
169                                              tp_conn,
170                                              bus_name,
171                                              TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
172                                              TP_HANDLE_TYPE_NONE,
173                                              0,
174                                              TRUE);
175         g_object_unref (tp_conn);
176
177         if (!priv->tp_chan) {
178                 empathy_debug (DEBUG_DOMAIN, "Failed to get roomlist channel");
179                 g_object_unref (list);
180                 return NULL;
181         }
182
183         priv->account = g_object_ref (account);
184         priv->roomlist_iface = tp_chan_get_interface (priv->tp_chan,
185                                                       TP_IFACE_QUARK_CHANNEL_TYPE_ROOM_LIST);
186
187         g_signal_connect (priv->tp_chan, "destroy",
188                           G_CALLBACK (tp_roomlist_destroy_cb),
189                           list);
190         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
191                                      G_CALLBACK (tp_roomlist_closed_cb),
192                                      list, NULL);
193         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "ListingRooms",
194                                      G_CALLBACK (tp_roomlist_listing_cb),
195                                      list, NULL);
196         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "GotRooms",
197                                      G_CALLBACK (tp_roomlist_got_rooms_cb),
198                                      list, NULL);
199
200         return list;
201 }
202
203 gboolean
204 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
205 {
206         EmpathyTpRoomlistPriv *priv;
207         GError                *error = NULL;
208         gboolean               listing = FALSE;
209
210         g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
211
212         priv = GET_PRIV (list);
213
214         if (!tp_chan_type_room_list_get_listing_rooms (priv->roomlist_iface,
215                                                        &listing,
216                                                        &error)) {
217                 empathy_debug (DEBUG_DOMAIN, 
218                               "Error GetListingRooms: %s",
219                               error ? error->message : "No error given");
220                 g_clear_error (&error);
221                 return FALSE;
222         }
223
224         return listing;
225 }
226
227 void
228 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
229 {
230         EmpathyTpRoomlistPriv *priv;
231         GError                *error = NULL;
232
233         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
234
235         priv = GET_PRIV (list);
236
237         if (!tp_chan_type_room_list_list_rooms (priv->roomlist_iface, &error)) {
238                 empathy_debug (DEBUG_DOMAIN, 
239                               "Error ListRooms: %s",
240                               error ? error->message : "No error given");
241                 g_clear_error (&error);
242         }
243 }
244
245 void
246 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
247 {
248         EmpathyTpRoomlistPriv *priv;
249         GError                *error = NULL;
250
251         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
252
253         priv = GET_PRIV (list);
254
255         if (!tp_chan_type_room_list_stop_listing (priv->roomlist_iface, &error)) {
256                 empathy_debug (DEBUG_DOMAIN, 
257                               "Error StopListing: %s",
258                               error ? error->message : "No error given");
259                 g_clear_error (&error);
260         }
261 }
262
263 static void
264 tp_roomlist_destroy_cb (TpChan            *tp_chan,
265                         EmpathyTpRoomlist *list)
266 {
267         EmpathyTpRoomlistPriv *priv;
268
269         priv = GET_PRIV (list);
270
271         empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
272
273         tp_roomlist_listing_cb (priv->roomlist_iface, FALSE, list);
274
275         g_object_unref  (priv->tp_chan);
276         priv->tp_chan = NULL;
277         priv->roomlist_iface = NULL;
278
279         g_signal_emit (list, signals[DESTROY], 0);
280 }
281
282 static void
283 tp_roomlist_closed_cb (TpChan            *tp_chan,
284                        EmpathyTpRoomlist *list)
285 {
286         EmpathyTpRoomlistPriv *priv;
287
288         priv = GET_PRIV (list);
289
290         /* The channel is closed, do just like if the proxy was destroyed */
291         g_signal_handlers_disconnect_by_func (priv->tp_chan,
292                                               tp_roomlist_destroy_cb,
293                                               list);
294         tp_roomlist_destroy_cb (priv->tp_chan, list);
295 }
296
297 static void
298 tp_roomlist_listing_cb (DBusGProxy        *roomlist_iface,
299                         gboolean           listing,
300                         EmpathyTpRoomlist *list)
301 {
302         empathy_debug (DEBUG_DOMAIN, "Listing: %s", listing ? "Yes" : "No");
303         g_signal_emit (list, signals[LISTING], 0, listing);
304 }
305
306 static void
307 tp_roomlist_got_rooms_cb (DBusGProxy        *roomlist_iface,
308                           GPtrArray         *room_list,
309                           EmpathyTpRoomlist *list)
310 {
311         EmpathyTpRoomlistPriv *priv;
312         guint                  i;
313
314         priv = GET_PRIV (list);
315
316         for (i = 0; i < room_list->len; i++) {
317                 EmpathyChatroom *chatroom;
318                 gchar           *room_id;
319                 const gchar     *room_name;
320                 const GValue    *room_name_value;
321                 GValueArray     *room_struct;
322                 guint            handle;
323                 const gchar     *channel_type;
324                 GHashTable      *info;
325
326                 /* Get information */
327                 room_struct = g_ptr_array_index (room_list, i);
328                 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
329                 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
330                 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
331
332                 /* Create the chatroom */
333                 room_name_value = g_hash_table_lookup (info, "name");
334                 room_name = g_value_get_string (room_name_value);
335                 room_id = empathy_inspect_handle (priv->account,
336                                                   handle,
337                                                   TP_HANDLE_TYPE_ROOM);
338                 chatroom = empathy_chatroom_new_full (priv->account,
339                                                       room_id,
340                                                       room_name,
341                                                       FALSE);
342
343                 /* Tells the world */
344                 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
345
346                 g_object_unref (chatroom);
347         }
348 }
349