Tagged for release 2.26.0.
[empathy-mirror.git] / gnome-2-26 / libempathy / empathy-tp-roomlist.c
bloba1583c083dea172cade196c7a3b0993eedac1c06
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2007-2008 Collabora Ltd.
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.
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.
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
19 * Authors: Xavier Claessens <xclaesse@gmail.com>
22 #include <config.h>
24 #include <string.h>
26 #include <telepathy-glib/channel.h>
27 #include <telepathy-glib/dbus.h>
28 #include <telepathy-glib/util.h>
30 #include <libmissioncontrol/mission-control.h>
32 #include "empathy-tp-roomlist.h"
33 #include "empathy-chatroom.h"
34 #include "empathy-utils.h"
36 #define DEBUG_FLAG EMPATHY_DEBUG_TP
37 #include "empathy-debug.h"
39 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpRoomlist)
40 typedef struct {
41 TpConnection *connection;
42 TpChannel *channel;
43 McAccount *account;
44 gboolean is_listing;
45 } EmpathyTpRoomlistPriv;
47 enum {
48 NEW_ROOM,
49 DESTROY,
50 LAST_SIGNAL
53 enum {
54 PROP_0,
55 PROP_CONNECTION,
56 PROP_IS_LISTING,
59 static guint signals[LAST_SIGNAL];
61 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
63 static void
64 tp_roomlist_listing_cb (TpChannel *channel,
65 gboolean listing,
66 gpointer user_data,
67 GObject *list)
69 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
71 DEBUG ("Listing: %s", listing ? "Yes" : "No");
72 priv->is_listing = listing;
73 g_object_notify (list, "is-listing");
76 static void
77 tp_roomlist_chatrooms_free (gpointer data)
79 GSList *chatrooms = data;
81 g_slist_foreach (chatrooms, (GFunc) g_object_unref, NULL);
82 g_slist_free (chatrooms);
85 static void
86 tp_roomlist_inspect_handles_cb (TpConnection *connection,
87 const gchar **names,
88 const GError *error,
89 gpointer user_data,
90 GObject *list)
92 GSList *chatrooms = user_data;
94 if (error != NULL) {
95 DEBUG ("Error: %s", error->message);
96 return;
99 while (*names != NULL) {
100 EmpathyChatroom *chatroom = chatrooms->data;
102 empathy_chatroom_set_room (chatroom, *names);
103 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
105 names++;
106 chatrooms = chatrooms->next;
110 static void
111 tp_roomlist_got_rooms_cb (TpChannel *channel,
112 const GPtrArray *rooms,
113 gpointer user_data,
114 GObject *list)
116 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
117 EmpathyChatroom *chatroom;
118 guint i;
119 GArray *handles = NULL;
120 GSList *chatrooms = NULL;
122 for (i = 0; i < rooms->len; i++) {
123 const GValue *room_name_value;
124 const GValue *handle_name_value;
125 GValueArray *room_struct;
126 guint handle;
127 const gchar *channel_type;
128 GHashTable *info;
130 /* Get information */
131 room_struct = g_ptr_array_index (rooms, i);
132 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
133 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
134 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
135 room_name_value = g_hash_table_lookup (info, "name");
136 handle_name_value = g_hash_table_lookup (info, "handle-name");
138 if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) {
139 continue;
142 chatroom = empathy_chatroom_new (priv->account);
144 if (room_name_value != NULL) {
145 empathy_chatroom_set_name (chatroom,
146 g_value_get_string (room_name_value));
149 if (handle_name_value != NULL) {
150 empathy_chatroom_set_room (chatroom,
151 g_value_get_string (handle_name_value));
153 /* We have the room ID, we can directly emit it */
154 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
155 g_object_unref (chatroom);
156 } else {
157 /* We don't have the room ID, we'll inspect all handles
158 * at once and then emit rooms */
159 if (handles == NULL) {
160 handles = g_array_new (FALSE, FALSE, sizeof (guint));
163 g_array_append_val (handles, handle);
164 chatrooms = g_slist_prepend (chatrooms, chatroom);
168 if (handles != NULL) {
169 chatrooms = g_slist_reverse (chatrooms);
170 tp_cli_connection_call_inspect_handles (priv->connection, -1,
171 TP_HANDLE_TYPE_ROOM,
172 handles,
173 tp_roomlist_inspect_handles_cb,
174 chatrooms,
175 tp_roomlist_chatrooms_free,
176 list);
177 g_array_free (handles, TRUE);
181 static void
182 tp_roomlist_get_listing_rooms_cb (TpChannel *channel,
183 gboolean is_listing,
184 const GError *error,
185 gpointer user_data,
186 GObject *list)
188 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
190 if (error) {
191 DEBUG ("Error geting listing rooms: %s", error->message);
192 return;
195 priv->is_listing = is_listing;
196 g_object_notify (list, "is-listing");
199 static void
200 tp_roomlist_invalidated_cb (TpChannel *channel,
201 guint domain,
202 gint code,
203 gchar *message,
204 EmpathyTpRoomlist *list)
206 DEBUG ("Channel invalidated: %s", message);
207 g_signal_emit (list, signals[DESTROY], 0);
210 static void
211 tp_roomlist_request_channel_cb (TpConnection *connection,
212 const gchar *object_path,
213 const GError *error,
214 gpointer user_data,
215 GObject *list)
217 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
219 if (error) {
220 DEBUG ("Error requesting channel: %s", error->message);
221 return;
224 priv->channel = tp_channel_new (priv->connection, object_path,
225 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
226 TP_HANDLE_TYPE_NONE,
227 0, NULL);
228 tp_channel_run_until_ready (priv->channel, NULL, NULL);
230 g_signal_connect (priv->channel, "invalidated",
231 G_CALLBACK (tp_roomlist_invalidated_cb),
232 list);
234 tp_cli_channel_type_room_list_connect_to_listing_rooms (priv->channel,
235 tp_roomlist_listing_cb,
236 NULL, NULL,
237 G_OBJECT (list),
238 NULL);
239 tp_cli_channel_type_room_list_connect_to_got_rooms (priv->channel,
240 tp_roomlist_got_rooms_cb,
241 NULL, NULL,
242 G_OBJECT (list),
243 NULL);
245 tp_cli_channel_type_room_list_call_get_listing_rooms (priv->channel, -1,
246 tp_roomlist_get_listing_rooms_cb,
247 NULL, NULL,
248 G_OBJECT (list));
251 static void
252 tp_roomlist_finalize (GObject *object)
254 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
256 if (priv->channel) {
257 DEBUG ("Closing channel...");
258 g_signal_handlers_disconnect_by_func (priv->channel,
259 tp_roomlist_invalidated_cb,
260 object);
261 tp_cli_channel_call_close (priv->channel, -1,
262 NULL, NULL, NULL, NULL);
263 g_object_unref (priv->channel);
266 if (priv->account) {
267 g_object_unref (priv->account);
269 if (priv->connection) {
270 g_object_unref (priv->connection);
273 G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
276 static void
277 tp_roomlist_constructed (GObject *list)
279 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
280 MissionControl *mc;
282 mc = empathy_mission_control_dup_singleton ();
283 priv->account = mission_control_get_account_for_tpconnection (mc,
284 priv->connection,
285 NULL);
286 g_object_unref (mc);
288 tp_cli_connection_call_request_channel (priv->connection, -1,
289 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
290 TP_HANDLE_TYPE_NONE,
292 TRUE,
293 tp_roomlist_request_channel_cb,
294 NULL, NULL,
295 list);
298 static void
299 tp_roomlist_get_property (GObject *object,
300 guint param_id,
301 GValue *value,
302 GParamSpec *pspec)
304 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
306 switch (param_id) {
307 case PROP_CONNECTION:
308 g_value_set_object (value, priv->connection);
309 break;
310 case PROP_IS_LISTING:
311 g_value_set_boolean (value, priv->is_listing);
312 break;
313 default:
314 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
315 break;
319 static void
320 tp_roomlist_set_property (GObject *object,
321 guint param_id,
322 const GValue *value,
323 GParamSpec *pspec)
325 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
327 switch (param_id) {
328 case PROP_CONNECTION:
329 priv->connection = g_object_ref (g_value_get_object (value));
330 break;
331 default:
332 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
333 break;
337 static void
338 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
340 GObjectClass *object_class = G_OBJECT_CLASS (klass);
342 object_class->finalize = tp_roomlist_finalize;
343 object_class->constructed = tp_roomlist_constructed;
344 object_class->get_property = tp_roomlist_get_property;
345 object_class->set_property = tp_roomlist_set_property;
347 g_object_class_install_property (object_class,
348 PROP_CONNECTION,
349 g_param_spec_object ("connection",
350 "The Connection",
351 "The connection on which it lists rooms",
352 TP_TYPE_CONNECTION,
353 G_PARAM_READWRITE |
354 G_PARAM_CONSTRUCT_ONLY));
355 g_object_class_install_property (object_class,
356 PROP_IS_LISTING,
357 g_param_spec_boolean ("is-listing",
358 "Is listing",
359 "Are we listing rooms",
360 FALSE,
361 G_PARAM_READABLE));
363 signals[NEW_ROOM] =
364 g_signal_new ("new-room",
365 G_TYPE_FROM_CLASS (klass),
366 G_SIGNAL_RUN_LAST,
368 NULL, NULL,
369 g_cclosure_marshal_VOID__OBJECT,
370 G_TYPE_NONE,
371 1, EMPATHY_TYPE_CHATROOM);
373 signals[DESTROY] =
374 g_signal_new ("destroy",
375 G_TYPE_FROM_CLASS (klass),
376 G_SIGNAL_RUN_LAST,
378 NULL, NULL,
379 g_cclosure_marshal_VOID__VOID,
380 G_TYPE_NONE,
383 g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
386 static void
387 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
389 EmpathyTpRoomlistPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (list,
390 EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv);
392 list->priv = priv;
395 EmpathyTpRoomlist *
396 empathy_tp_roomlist_new (McAccount *account)
398 EmpathyTpRoomlist *list;
399 MissionControl *mc;
400 TpConnection *connection;
402 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
404 mc = empathy_mission_control_dup_singleton ();
405 connection = mission_control_get_tpconnection (mc, account, NULL);
407 list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST,
408 "connection", connection,
409 NULL);
411 g_object_unref (mc);
412 g_object_unref (connection);
414 return list;
417 gboolean
418 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
420 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
422 g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
424 return priv->is_listing;
427 void
428 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
430 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
432 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
433 g_return_if_fail (TP_IS_CHANNEL (priv->channel));
435 tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
436 NULL, NULL, NULL, NULL);
439 void
440 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
442 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
444 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
445 g_return_if_fail (TP_IS_CHANNEL (priv->channel));
447 tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1,
448 NULL, NULL, NULL, NULL);