1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
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>
26 #include <telepathy-glib/channel.h>
27 #include <telepathy-glib/dbus.h>
28 #include <telepathy-glib/util.h>
29 #include <telepathy-glib/interfaces.h>
31 #include "empathy-account.h"
33 #include "empathy-tp-roomlist.h"
34 #include "empathy-chatroom.h"
35 #include "empathy-utils.h"
37 #define DEBUG_FLAG EMPATHY_DEBUG_TP
38 #include "empathy-debug.h"
40 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpRoomlist)
42 TpConnection *connection;
44 EmpathyAccount *account;
46 gboolean start_requested;
47 } EmpathyTpRoomlistPriv;
62 static guint signals[LAST_SIGNAL];
64 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
67 tp_roomlist_listing_cb (TpChannel *channel,
72 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
74 DEBUG ("Listing: %s", listing ? "Yes" : "No");
75 priv->is_listing = listing;
76 g_object_notify (list, "is-listing");
80 tp_roomlist_chatrooms_free (gpointer data)
82 GSList *chatrooms = data;
84 g_slist_foreach (chatrooms, (GFunc) g_object_unref, NULL);
85 g_slist_free (chatrooms);
89 tp_roomlist_inspect_handles_cb (TpConnection *connection,
95 GSList *chatrooms = user_data;
98 DEBUG ("Error: %s", error->message);
102 while (*names != NULL) {
103 EmpathyChatroom *chatroom = chatrooms->data;
105 empathy_chatroom_set_room (chatroom, *names);
106 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
109 chatrooms = chatrooms->next;
114 tp_roomlist_got_rooms_cb (TpChannel *channel,
115 const GPtrArray *rooms,
119 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
120 EmpathyChatroom *chatroom;
122 GArray *handles = NULL;
123 GSList *chatrooms = NULL;
125 for (i = 0; i < rooms->len; i++) {
126 const GValue *room_name_value;
127 const GValue *handle_name_value;
128 const GValue *room_members_value;
129 const GValue *room_subject_value;
130 const GValue *room_invite_value;
131 const GValue *room_password_value;
132 GValueArray *room_struct;
134 const gchar *channel_type;
137 /* Get information */
138 room_struct = g_ptr_array_index (rooms, i);
139 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
140 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
141 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
142 room_name_value = g_hash_table_lookup (info, "name");
143 handle_name_value = g_hash_table_lookup (info, "handle-name");
144 room_subject_value = g_hash_table_lookup (info, "subject");
145 room_members_value = g_hash_table_lookup (info, "members");
146 room_invite_value = g_hash_table_lookup (info, "invite-only");
147 room_password_value = g_hash_table_lookup (info, "password");
149 if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) {
153 chatroom = empathy_chatroom_new (priv->account);
155 if (room_name_value != NULL) {
156 empathy_chatroom_set_name (chatroom,
157 g_value_get_string (room_name_value));
160 if (room_members_value != NULL) {
161 empathy_chatroom_set_members_count (chatroom,
162 g_value_get_uint (room_members_value));
165 if (room_subject_value != NULL) {
166 empathy_chatroom_set_subject (chatroom,
167 g_value_get_string (room_subject_value));
170 if (room_invite_value != NULL) {
171 empathy_chatroom_set_invite_only (chatroom,
172 g_value_get_boolean (room_invite_value));
175 if (room_password_value != NULL) {
176 empathy_chatroom_set_need_password (chatroom,
177 g_value_get_boolean (room_password_value));
180 if (handle_name_value != NULL) {
181 empathy_chatroom_set_room (chatroom,
182 g_value_get_string (handle_name_value));
184 /* We have the room ID, we can directly emit it */
185 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
186 g_object_unref (chatroom);
188 /* We don't have the room ID, we'll inspect all handles
189 * at once and then emit rooms */
190 if (handles == NULL) {
191 handles = g_array_new (FALSE, FALSE, sizeof (guint));
194 g_array_append_val (handles, handle);
195 chatrooms = g_slist_prepend (chatrooms, chatroom);
199 if (handles != NULL) {
200 chatrooms = g_slist_reverse (chatrooms);
201 tp_cli_connection_call_inspect_handles (priv->connection, -1,
204 tp_roomlist_inspect_handles_cb,
206 tp_roomlist_chatrooms_free,
208 g_array_free (handles, TRUE);
213 tp_roomlist_get_listing_rooms_cb (TpChannel *channel,
219 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
222 DEBUG ("Error geting listing rooms: %s", error->message);
226 priv->is_listing = is_listing;
227 g_object_notify (list, "is-listing");
231 tp_roomlist_invalidated_cb (TpChannel *channel,
235 EmpathyTpRoomlist *list)
237 DEBUG ("Channel invalidated: %s", message);
238 g_signal_emit (list, signals[DESTROY], 0);
242 call_list_rooms_cb (TpChannel *proxy,
245 GObject *weak_object)
248 DEBUG ("Error listing rooms: %s", error->message);
249 g_signal_emit_by_name (list, "error::start", error);
254 stop_listing_cb (TpChannel *proxy,
257 GObject *weak_object)
260 DEBUG ("Error on stop listing: %s", error->message);
261 g_signal_emit_by_name (list, "error::stop", error);
266 channel_ready_cb (TpChannel *channel,
270 EmpathyTpRoomlist *list = EMPATHY_TP_ROOMLIST (user_data);
271 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
274 DEBUG ("Channel invalidated: %s", error->message);
275 g_signal_emit (list, signals[DESTROY], 0);
279 g_signal_connect (priv->channel, "invalidated",
280 G_CALLBACK (tp_roomlist_invalidated_cb),
283 tp_cli_channel_type_room_list_connect_to_listing_rooms (priv->channel,
284 tp_roomlist_listing_cb,
288 tp_cli_channel_type_room_list_connect_to_got_rooms (priv->channel,
289 tp_roomlist_got_rooms_cb,
294 tp_cli_channel_type_room_list_call_get_listing_rooms (priv->channel, -1,
295 tp_roomlist_get_listing_rooms_cb,
299 if (priv->start_requested == TRUE) {
300 tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
301 call_list_rooms_cb, list, NULL, NULL);
302 priv->start_requested = FALSE;
307 tp_roomlist_request_channel_cb (TpConnection *connection,
308 const gchar *object_path,
313 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
316 DEBUG ("Error requesting channel: %s", error->message);
320 priv->channel = tp_channel_new (priv->connection, object_path,
321 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
324 tp_channel_call_when_ready (priv->channel, channel_ready_cb, list);
328 tp_roomlist_finalize (GObject *object)
330 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
333 DEBUG ("Closing channel...");
334 g_signal_handlers_disconnect_by_func (priv->channel,
335 tp_roomlist_invalidated_cb,
337 tp_cli_channel_call_close (priv->channel, -1,
338 NULL, NULL, NULL, NULL);
339 g_object_unref (priv->channel);
343 g_object_unref (priv->account);
345 if (priv->connection) {
346 g_object_unref (priv->connection);
349 G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
353 tp_roomlist_constructed (GObject *list)
355 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
357 priv->connection = empathy_account_get_connection (priv->account);
358 g_object_ref (priv->connection);
360 tp_cli_connection_call_request_channel (priv->connection, -1,
361 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
365 tp_roomlist_request_channel_cb,
371 tp_roomlist_get_property (GObject *object,
376 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
380 g_value_set_object (value, priv->account);
382 case PROP_IS_LISTING:
383 g_value_set_boolean (value, priv->is_listing);
386 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
392 tp_roomlist_set_property (GObject *object,
397 EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
401 priv->account = g_value_dup_object (value);
404 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
410 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
412 GObjectClass *object_class = G_OBJECT_CLASS (klass);
414 object_class->finalize = tp_roomlist_finalize;
415 object_class->constructed = tp_roomlist_constructed;
416 object_class->get_property = tp_roomlist_get_property;
417 object_class->set_property = tp_roomlist_set_property;
419 g_object_class_install_property (object_class,
421 g_param_spec_object ("account",
423 "The account on which it lists rooms",
424 EMPATHY_TYPE_ACCOUNT,
426 G_PARAM_CONSTRUCT_ONLY));
427 g_object_class_install_property (object_class,
429 g_param_spec_boolean ("is-listing",
431 "Are we listing rooms",
436 g_signal_new ("new-room",
437 G_TYPE_FROM_CLASS (klass),
441 g_cclosure_marshal_VOID__OBJECT,
443 1, EMPATHY_TYPE_CHATROOM);
446 g_signal_new ("destroy",
447 G_TYPE_FROM_CLASS (klass),
451 g_cclosure_marshal_VOID__VOID,
456 g_signal_new ("error",
457 G_TYPE_FROM_CLASS (klass),
458 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
461 g_cclosure_marshal_VOID__POINTER,
465 g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
469 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
471 EmpathyTpRoomlistPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (list,
472 EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv);
475 priv->start_requested = FALSE;
476 priv->is_listing = FALSE;
480 empathy_tp_roomlist_new (EmpathyAccount *account)
482 EmpathyTpRoomlist *list;
484 list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST,
492 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
494 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
496 g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
498 return priv->is_listing;
502 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
504 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
506 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
507 if (priv->channel != NULL) {
508 tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
509 call_list_rooms_cb, list, NULL, NULL);
511 priv->start_requested = TRUE;
516 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
518 EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
520 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
522 if (priv->channel == NULL)
525 g_return_if_fail (TP_IS_CHANNEL (priv->channel));
527 tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1,
528 stop_listing_cb, list, NULL, NULL);