]> git.0d.be Git - empathy.git/blob - libempathy/empathy-tp-roomlist.c
Make use of tp-glib debug system.
[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-2008 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 <telepathy-glib/channel.h>
27 #include <telepathy-glib/dbus.h>
28
29 #include <libmissioncontrol/mission-control.h>
30
31 #include "empathy-tp-roomlist.h"
32 #include "empathy-chatroom.h"
33 #include "empathy-utils.h"
34 #include "empathy-debug.h"
35
36 #define DEBUG_FLAG EMPATHY_DEBUG_TP
37 #include "empathy-debug.h"
38
39 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
40                        EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
41
42 struct _EmpathyTpRoomlistPriv {
43         TpConnection *connection;
44         TpChannel    *channel;
45         McAccount    *account;
46         gboolean      is_listing;
47 };
48
49 static void empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass);
50 static void empathy_tp_roomlist_init       (EmpathyTpRoomlist      *chat);
51
52 enum {
53         NEW_ROOM,
54         DESTROY,
55         LAST_SIGNAL
56 };
57
58 enum {
59         PROP_0,
60         PROP_CONNECTION,
61         PROP_IS_LISTING,
62 };
63
64 static guint signals[LAST_SIGNAL];
65
66 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
67
68 static void
69 tp_roomlist_listing_cb (TpChannel *channel,
70                         gboolean   listing,
71                         gpointer   user_data,
72                         GObject   *list)
73 {
74         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
75
76         DEBUG ("Listing: %s", listing ? "Yes" : "No");
77         priv->is_listing = listing;
78         g_object_notify (list, "is-listing");
79 }
80
81 static void
82 tp_roomlist_got_rooms_cb (TpChannel       *channel,
83                           const GPtrArray *rooms,
84                           gpointer         user_data,
85                           GObject         *list)
86 {
87         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
88         guint                  i;
89         const gchar          **names;
90         gchar                **room_ids;
91         GArray                *handles;
92
93         names = g_new0 (const gchar*, rooms->len + 1);
94         handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), rooms->len);
95         for (i = 0; i < rooms->len; i++) {
96                 const GValue *room_name_value;
97                 GValueArray  *room_struct;
98                 guint         handle;
99                 GHashTable   *info;
100
101                 /* Get information */
102                 room_struct = g_ptr_array_index (rooms, i);
103                 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
104                 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
105                 room_name_value = g_hash_table_lookup (info, "name");
106
107                 names[i] = g_value_get_string (room_name_value);
108                 g_array_append_val (handles, handle);
109         }
110                 
111         tp_cli_connection_run_inspect_handles (priv->connection, -1,
112                                                TP_HANDLE_TYPE_ROOM,
113                                                handles,
114                                                &room_ids,
115                                                NULL, NULL);
116         for (i = 0; i < handles->len; i++) {
117                 EmpathyChatroom *chatroom;
118
119                 chatroom = empathy_chatroom_new_full (priv->account,
120                                                       room_ids[i],
121                                                       names[i],
122                                                       FALSE);
123                 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
124                 g_object_unref (chatroom);
125                 g_free (room_ids[i]);
126         }
127
128         g_free (names);
129         g_free (room_ids);
130         g_array_free (handles, TRUE);
131 }
132
133 static void
134 tp_roomlist_get_listing_rooms_cb (TpChannel    *channel,
135                                   gboolean      is_listing,
136                                   const GError *error,
137                                   gpointer      user_data,
138                                   GObject      *list)
139 {
140         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
141
142         if (error) {
143                 DEBUG ("Error geting listing rooms: %s", error->message);
144                 return;
145         }
146
147         priv->is_listing = is_listing;
148         g_object_notify (list, "is-listing");
149 }
150
151 static void
152 tp_roomlist_invalidated_cb (TpChannel         *channel,
153                             guint              domain,
154                             gint               code,
155                             gchar             *message,
156                             EmpathyTpRoomlist *list)
157 {
158         DEBUG ("Channel invalidated: %s", message);
159         g_signal_emit (list, signals[DESTROY], 0);
160 }
161
162 static void
163 tp_roomlist_request_channel_cb (TpConnection *connection,
164                                 const gchar  *object_path,
165                                 const GError *error,
166                                 gpointer      user_data,
167                                 GObject      *list)
168 {
169         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
170
171         if (error) {
172                 DEBUG ("Error requesting channel: %s", error->message);
173                 return;
174         }
175
176         priv->channel = tp_channel_new (priv->connection, object_path,
177                                         TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
178                                         TP_HANDLE_TYPE_NONE,
179                                         0, NULL);
180         tp_channel_run_until_ready (priv->channel, NULL, NULL);
181
182         g_signal_connect (priv->channel, "invalidated",
183                           G_CALLBACK (tp_roomlist_invalidated_cb),
184                           list);
185
186         tp_cli_channel_type_room_list_connect_to_listing_rooms (priv->channel,
187                                                                 tp_roomlist_listing_cb,
188                                                                 NULL, NULL,
189                                                                 G_OBJECT (list),
190                                                                 NULL);
191         tp_cli_channel_type_room_list_connect_to_got_rooms (priv->channel,
192                                                             tp_roomlist_got_rooms_cb,
193                                                             NULL, NULL,
194                                                             G_OBJECT (list),
195                                                             NULL);
196
197         tp_cli_channel_type_room_list_call_get_listing_rooms (priv->channel, -1,
198                                                               tp_roomlist_get_listing_rooms_cb,
199                                                               NULL, NULL,
200                                                               G_OBJECT (list));
201 }
202
203 static void
204 tp_roomlist_finalize (GObject *object)
205 {
206         EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
207
208         if (priv->channel) {
209                 DEBUG ("Closing channel...");
210                 g_signal_handlers_disconnect_by_func (priv->channel,
211                                                       tp_roomlist_invalidated_cb,
212                                                       object);
213                 tp_cli_channel_call_close (priv->channel, -1,
214                                            NULL, NULL, NULL, NULL);
215                 g_object_unref (priv->channel);
216         }
217
218         if (priv->account) {
219                 g_object_unref (priv->account);
220         }
221         if (priv->connection) {
222                 g_object_unref (priv->connection);
223         }
224
225         G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
226 }
227
228 static void
229 tp_roomlist_constructed (GObject *list)
230 {
231         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
232         MissionControl        *mc;
233
234         mc = empathy_mission_control_new ();
235         priv->account = mission_control_get_account_for_tpconnection (mc,
236                                                                       priv->connection,
237                                                                       NULL);
238         g_object_unref (mc);
239
240         tp_cli_connection_call_request_channel (priv->connection, -1,
241                                                 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
242                                                 TP_HANDLE_TYPE_NONE,
243                                                 0,
244                                                 TRUE,
245                                                 tp_roomlist_request_channel_cb,
246                                                 NULL, NULL,
247                                                 list);
248 }
249
250 static void
251 tp_roomlist_get_property (GObject    *object,
252                           guint       param_id,
253                           GValue     *value,
254                           GParamSpec *pspec)
255 {
256         EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
257
258         switch (param_id) {
259         case PROP_CONNECTION:
260                 g_value_set_object (value, priv->connection);
261                 break;
262         case PROP_IS_LISTING:
263                 g_value_set_boolean (value, priv->is_listing);
264                 break;
265         default:
266                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
267                 break;
268         };
269 }
270
271 static void
272 tp_roomlist_set_property (GObject      *object,
273                           guint         param_id,
274                           const GValue *value,
275                           GParamSpec   *pspec)
276 {
277         EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
278
279         switch (param_id) {
280         case PROP_CONNECTION:
281                 priv->connection = g_object_ref (g_value_get_object (value));
282                 break;
283         default:
284                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
285                 break;
286         };
287 }
288
289 static void
290 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
291 {
292         GObjectClass *object_class = G_OBJECT_CLASS (klass);
293
294         object_class->finalize = tp_roomlist_finalize;
295         object_class->constructed = tp_roomlist_constructed;
296         object_class->get_property = tp_roomlist_get_property;
297         object_class->set_property = tp_roomlist_set_property;
298
299         g_object_class_install_property (object_class,
300                                          PROP_CONNECTION,
301                                          g_param_spec_object ("connection",
302                                                               "The Connection",
303                                                               "The connection on which it lists rooms",
304                                                               TP_TYPE_CONNECTION,
305                                                               G_PARAM_READWRITE |
306                                                               G_PARAM_CONSTRUCT_ONLY));
307         g_object_class_install_property (object_class,
308                                          PROP_IS_LISTING,
309                                          g_param_spec_boolean ("is-listing",
310                                                                "Is listing",
311                                                                "Are we listing rooms",
312                                                                FALSE,
313                                                                G_PARAM_READABLE));
314
315         signals[NEW_ROOM] =
316                 g_signal_new ("new-room",
317                               G_TYPE_FROM_CLASS (klass),
318                               G_SIGNAL_RUN_LAST,
319                               0,
320                               NULL, NULL,
321                               g_cclosure_marshal_VOID__OBJECT,
322                               G_TYPE_NONE,
323                               1, EMPATHY_TYPE_CHATROOM);
324
325         signals[DESTROY] =
326                 g_signal_new ("destroy",
327                               G_TYPE_FROM_CLASS (klass),
328                               G_SIGNAL_RUN_LAST,
329                               0,
330                               NULL, NULL,
331                               g_cclosure_marshal_VOID__VOID,
332                               G_TYPE_NONE,
333                               0);
334
335         g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
336 }
337
338 static void
339 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
340 {
341 }
342
343 EmpathyTpRoomlist *
344 empathy_tp_roomlist_new (McAccount *account)
345 {
346         EmpathyTpRoomlist *list;
347         MissionControl    *mc;
348         TpConnection      *connection;
349
350         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
351
352         mc = empathy_mission_control_new ();
353         connection = mission_control_get_tpconnection (mc, account, NULL);
354
355         list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST,
356                              "connection", connection,
357                              NULL);
358
359         g_object_unref (mc);
360         g_object_unref (connection);
361
362         return list;
363 }
364
365 gboolean
366 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
367 {
368         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
369
370         g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
371
372         return priv->is_listing;
373 }
374
375 void
376 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
377 {
378         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
379
380         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
381         g_return_if_fail (TP_IS_CHANNEL (priv->channel));
382
383         tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
384                                                        NULL, NULL, NULL,
385                                                        G_OBJECT (list));
386 }
387
388 void
389 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
390 {
391         EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
392
393         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
394         g_return_if_fail (TP_IS_CHANNEL (priv->channel));
395
396         tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1,
397                                                          NULL, NULL, NULL,
398                                                          G_OBJECT (list));
399 }
400