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-tp-roomlist.h"
32 #include "empathy-chatroom.h"
33 #include "empathy-utils.h"
35 #define DEBUG_FLAG EMPATHY_DEBUG_TP
36 #include "empathy-debug.h"
38 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpRoomlist)
40 TpConnection
*connection
;
44 gboolean start_requested
;
45 } EmpathyTpRoomlistPriv
;
60 static guint signals
[LAST_SIGNAL
];
62 G_DEFINE_TYPE (EmpathyTpRoomlist
, empathy_tp_roomlist
, G_TYPE_OBJECT
);
65 tp_roomlist_listing_cb (TpChannel
*channel
,
70 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
72 DEBUG ("Listing: %s", listing
? "Yes" : "No");
73 priv
->is_listing
= listing
;
74 g_object_notify (list
, "is-listing");
78 tp_roomlist_chatrooms_free (gpointer data
)
80 GSList
*chatrooms
= data
;
82 g_slist_foreach (chatrooms
, (GFunc
) g_object_unref
, NULL
);
83 g_slist_free (chatrooms
);
87 tp_roomlist_inspect_handles_cb (TpConnection
*connection
,
93 GSList
*chatrooms
= user_data
;
96 DEBUG ("Error: %s", error
->message
);
100 while (*names
!= NULL
) {
101 EmpathyChatroom
*chatroom
= chatrooms
->data
;
103 empathy_chatroom_set_room (chatroom
, *names
);
104 g_signal_emit (list
, signals
[NEW_ROOM
], 0, chatroom
);
107 chatrooms
= chatrooms
->next
;
112 tp_roomlist_got_rooms_cb (TpChannel
*channel
,
113 const GPtrArray
*rooms
,
117 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
118 EmpathyChatroom
*chatroom
;
120 GArray
*handles
= NULL
;
121 GSList
*chatrooms
= NULL
;
123 for (i
= 0; i
< rooms
->len
; i
++) {
124 const GValue
*room_name_value
;
125 const GValue
*handle_name_value
;
126 const GValue
*room_members_value
;
127 const GValue
*room_subject_value
;
128 const GValue
*room_invite_value
;
129 const GValue
*room_password_value
;
130 GValueArray
*room_struct
;
132 const gchar
*channel_type
;
135 /* Get information */
136 room_struct
= g_ptr_array_index (rooms
, i
);
137 handle
= g_value_get_uint (g_value_array_get_nth (room_struct
, 0));
138 channel_type
= g_value_get_string (g_value_array_get_nth (room_struct
, 1));
139 info
= g_value_get_boxed (g_value_array_get_nth (room_struct
, 2));
140 room_name_value
= g_hash_table_lookup (info
, "name");
141 handle_name_value
= g_hash_table_lookup (info
, "handle-name");
142 room_subject_value
= g_hash_table_lookup (info
, "subject");
143 room_members_value
= g_hash_table_lookup (info
, "members");
144 room_invite_value
= g_hash_table_lookup (info
, "invite-only");
145 room_password_value
= g_hash_table_lookup (info
, "password");
147 if (tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_TEXT
)) {
151 chatroom
= empathy_chatroom_new (priv
->account
);
153 if (room_name_value
!= NULL
) {
154 empathy_chatroom_set_name (chatroom
,
155 g_value_get_string (room_name_value
));
158 if (room_members_value
!= NULL
) {
159 empathy_chatroom_set_members_count (chatroom
,
160 g_value_get_uint (room_members_value
));
163 if (room_subject_value
!= NULL
) {
164 empathy_chatroom_set_subject (chatroom
,
165 g_value_get_string (room_subject_value
));
168 if (room_invite_value
!= NULL
) {
169 empathy_chatroom_set_invite_only (chatroom
,
170 g_value_get_boolean (room_invite_value
));
173 if (room_password_value
!= NULL
) {
174 empathy_chatroom_set_need_password (chatroom
,
175 g_value_get_boolean (room_password_value
));
178 if (handle_name_value
!= NULL
) {
179 empathy_chatroom_set_room (chatroom
,
180 g_value_get_string (handle_name_value
));
182 /* We have the room ID, we can directly emit it */
183 g_signal_emit (list
, signals
[NEW_ROOM
], 0, chatroom
);
184 g_object_unref (chatroom
);
186 /* We don't have the room ID, we'll inspect all handles
187 * at once and then emit rooms */
188 if (handles
== NULL
) {
189 handles
= g_array_new (FALSE
, FALSE
, sizeof (guint
));
192 g_array_append_val (handles
, handle
);
193 chatrooms
= g_slist_prepend (chatrooms
, chatroom
);
197 if (handles
!= NULL
) {
198 chatrooms
= g_slist_reverse (chatrooms
);
199 tp_cli_connection_call_inspect_handles (priv
->connection
, -1,
202 tp_roomlist_inspect_handles_cb
,
204 tp_roomlist_chatrooms_free
,
206 g_array_unref (handles
);
211 tp_roomlist_get_listing_rooms_cb (TpChannel
*channel
,
217 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
220 DEBUG ("Error geting listing rooms: %s", error
->message
);
224 priv
->is_listing
= is_listing
;
225 g_object_notify (list
, "is-listing");
229 tp_roomlist_invalidated_cb (TpChannel
*channel
,
233 EmpathyTpRoomlist
*list
)
235 DEBUG ("Channel invalidated: %s", message
);
236 g_signal_emit (list
, signals
[DESTROY
], 0);
240 call_list_rooms_cb (TpChannel
*proxy
,
243 GObject
*weak_object
)
246 DEBUG ("Error listing rooms: %s", error
->message
);
247 g_signal_emit_by_name (list
, "error::start", error
);
252 stop_listing_cb (TpChannel
*proxy
,
255 GObject
*weak_object
)
258 DEBUG ("Error on stop listing: %s", error
->message
);
259 g_signal_emit_by_name (list
, "error::stop", error
);
264 tp_roomlist_create_channel_cb (GObject
*source
,
265 GAsyncResult
*result
,
268 EmpathyTpRoomlist
*self
= user_data
;
269 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (self
);
270 GError
*error
= NULL
;
272 priv
->channel
= tp_account_channel_request_create_and_handle_channel_finish (
273 TP_ACCOUNT_CHANNEL_REQUEST (source
), result
, NULL
, &error
);
275 if (priv
->channel
== NULL
) {
276 DEBUG ("Error creating channel: %s", error
->message
);
277 g_error_free (error
);
281 g_signal_connect (priv
->channel
, "invalidated",
282 G_CALLBACK (tp_roomlist_invalidated_cb
), self
);
284 tp_cli_channel_type_room_list_connect_to_listing_rooms (priv
->channel
,
285 tp_roomlist_listing_cb
,
289 tp_cli_channel_type_room_list_connect_to_got_rooms (priv
->channel
,
290 tp_roomlist_got_rooms_cb
,
295 tp_cli_channel_type_room_list_call_get_listing_rooms (priv
->channel
, -1,
296 tp_roomlist_get_listing_rooms_cb
,
300 if (priv
->start_requested
== TRUE
) {
301 tp_cli_channel_type_room_list_call_list_rooms (priv
->channel
, -1,
302 call_list_rooms_cb
, self
, NULL
, G_OBJECT (self
));
303 priv
->start_requested
= FALSE
;
307 g_object_unref (self
);
311 tp_roomlist_finalize (GObject
*object
)
313 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (object
);
316 DEBUG ("Closing channel...");
317 g_signal_handlers_disconnect_by_func (priv
->channel
,
318 tp_roomlist_invalidated_cb
,
320 tp_cli_channel_call_close (priv
->channel
, -1,
321 NULL
, NULL
, NULL
, NULL
);
322 g_object_unref (priv
->channel
);
326 g_object_unref (priv
->account
);
328 if (priv
->connection
) {
329 g_object_unref (priv
->connection
);
332 G_OBJECT_CLASS (empathy_tp_roomlist_parent_class
)->finalize (object
);
336 tp_roomlist_constructed (GObject
*list
)
338 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
340 TpAccountChannelRequest
*req
;
342 request
= tp_asv_new (
343 TP_PROP_CHANNEL_CHANNEL_TYPE
, G_TYPE_STRING
,
344 TP_IFACE_CHANNEL_TYPE_ROOM_LIST
,
345 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE
, G_TYPE_UINT
, TP_HANDLE_TYPE_NONE
,
348 priv
->connection
= tp_account_get_connection (priv
->account
);
349 g_object_ref (priv
->connection
);
351 req
= tp_account_channel_request_new (priv
->account
, request
,
352 TP_USER_ACTION_TIME_CURRENT_TIME
);
354 /* Ensure we stay alive during the async call */
357 tp_account_channel_request_create_and_handle_channel_async (req
, NULL
,
358 tp_roomlist_create_channel_cb
, list
);
360 g_hash_table_unref (request
);
361 g_object_unref (req
);
365 tp_roomlist_get_property (GObject
*object
,
370 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (object
);
374 g_value_set_object (value
, priv
->account
);
376 case PROP_IS_LISTING
:
377 g_value_set_boolean (value
, priv
->is_listing
);
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
386 tp_roomlist_set_property (GObject
*object
,
391 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (object
);
395 priv
->account
= g_value_dup_object (value
);
398 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
404 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass
*klass
)
406 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
408 object_class
->finalize
= tp_roomlist_finalize
;
409 object_class
->constructed
= tp_roomlist_constructed
;
410 object_class
->get_property
= tp_roomlist_get_property
;
411 object_class
->set_property
= tp_roomlist_set_property
;
413 g_object_class_install_property (object_class
,
415 g_param_spec_object ("account",
417 "The account on which it lists rooms",
420 G_PARAM_CONSTRUCT_ONLY
));
421 g_object_class_install_property (object_class
,
423 g_param_spec_boolean ("is-listing",
425 "Are we listing rooms",
430 g_signal_new ("new-room",
431 G_TYPE_FROM_CLASS (klass
),
435 g_cclosure_marshal_generic
,
437 1, EMPATHY_TYPE_CHATROOM
);
440 g_signal_new ("destroy",
441 G_TYPE_FROM_CLASS (klass
),
445 g_cclosure_marshal_generic
,
450 g_signal_new ("error",
451 G_TYPE_FROM_CLASS (klass
),
452 G_SIGNAL_RUN_LAST
| G_SIGNAL_DETAILED
,
455 g_cclosure_marshal_generic
,
459 g_type_class_add_private (object_class
, sizeof (EmpathyTpRoomlistPriv
));
463 empathy_tp_roomlist_init (EmpathyTpRoomlist
*list
)
465 EmpathyTpRoomlistPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (list
,
466 EMPATHY_TYPE_TP_ROOMLIST
, EmpathyTpRoomlistPriv
);
469 priv
->start_requested
= FALSE
;
470 priv
->is_listing
= FALSE
;
474 empathy_tp_roomlist_new (TpAccount
*account
)
476 EmpathyTpRoomlist
*list
;
478 list
= g_object_new (EMPATHY_TYPE_TP_ROOMLIST
,
486 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist
*list
)
488 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
490 g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list
), FALSE
);
492 return priv
->is_listing
;
496 empathy_tp_roomlist_start (EmpathyTpRoomlist
*list
)
498 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
500 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list
));
501 if (priv
->channel
!= NULL
) {
502 tp_cli_channel_type_room_list_call_list_rooms (priv
->channel
, -1,
503 call_list_rooms_cb
, list
, NULL
, NULL
);
505 priv
->start_requested
= TRUE
;
510 empathy_tp_roomlist_stop (EmpathyTpRoomlist
*list
)
512 EmpathyTpRoomlistPriv
*priv
= GET_PRIV (list
);
514 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list
));
516 if (priv
->channel
== NULL
)
519 g_return_if_fail (TP_IS_CHANNEL (priv
->channel
));
521 tp_cli_channel_type_room_list_call_stop_listing (priv
->channel
, -1,
522 stop_listing_cb
, list
, NULL
, NULL
);