1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program 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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
27 #include <libtelepathy/tp-chan-type-room-list-gen.h>
28 #include <libtelepathy/tp-helpers.h>
29 #include <libtelepathy/tp-conn.h>
30 #include <libtelepathy/tp-chan.h>
32 #include <libmissioncontrol/mission-control.h>
34 #include "empathy-tp-roomlist.h"
35 #include "empathy-chatroom.h"
36 #include "empathy-utils.h"
37 #include "empathy-debug.h"
39 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
40 EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
42 #define DEBUG_DOMAIN "TpRoomlist"
44 struct _EmpathyTpRoomlistPriv {
47 DBusGProxy *roomlist_iface;
50 static void empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass);
51 static void empathy_tp_roomlist_init (EmpathyTpRoomlist *chat);
52 static void tp_roomlist_finalize (GObject *object);
53 static void tp_roomlist_destroy_cb (TpChan *tp_chan,
54 EmpathyTpRoomlist *list);
55 static void tp_roomlist_closed_cb (TpChan *tp_chan,
56 EmpathyTpRoomlist *list);
57 static void tp_roomlist_listing_cb (DBusGProxy *roomlist_iface,
59 EmpathyTpRoomlist *list);
60 static void tp_roomlist_got_rooms_cb (DBusGProxy *roomlist_iface,
62 EmpathyTpRoomlist *list);
71 static guint signals[LAST_SIGNAL];
73 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
76 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
78 GObjectClass *object_class = G_OBJECT_CLASS (klass);
80 object_class->finalize = tp_roomlist_finalize;
83 g_signal_new ("new-room",
84 G_TYPE_FROM_CLASS (klass),
88 g_cclosure_marshal_VOID__OBJECT,
90 1, EMPATHY_TYPE_CHATROOM);
93 g_signal_new ("listing",
94 G_TYPE_FROM_CLASS (klass),
98 g_cclosure_marshal_VOID__BOOLEAN,
103 g_signal_new ("destroy",
104 G_TYPE_FROM_CLASS (klass),
108 g_cclosure_marshal_VOID__VOID,
112 g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
116 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
121 tp_roomlist_finalize (GObject *object)
123 EmpathyTpRoomlistPriv *priv;
124 GError *error = NULL;
126 priv = GET_PRIV (object);
129 g_signal_handlers_disconnect_by_func (priv->tp_chan,
130 tp_roomlist_destroy_cb,
133 empathy_debug (DEBUG_DOMAIN, "Closing channel...");
134 if (!tp_chan_close (DBUS_G_PROXY (priv->tp_chan), &error)) {
135 empathy_debug (DEBUG_DOMAIN,
136 "Error closing roomlist channel: %s",
137 error ? error->message : "No error given");
138 g_clear_error (&error);
140 g_object_unref (priv->tp_chan);
144 g_object_unref (priv->account);
147 G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
151 empathy_tp_roomlist_new (McAccount *account)
153 EmpathyTpRoomlist *list;
154 EmpathyTpRoomlistPriv *priv;
157 const gchar *bus_name;
159 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
161 list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST, NULL);
162 priv = GET_PRIV (list);
164 mc = empathy_mission_control_new ();
165 tp_conn = mission_control_get_connection (mc, account, NULL);
168 bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (tp_conn));
169 priv->tp_chan = tp_conn_new_channel (tp_get_bus (),
172 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
176 g_object_unref (tp_conn);
178 if (!priv->tp_chan) {
179 empathy_debug (DEBUG_DOMAIN, "Failed to get roomlist channel");
180 g_object_unref (list);
184 priv->account = g_object_ref (account);
185 priv->roomlist_iface = tp_chan_get_interface (priv->tp_chan,
186 TELEPATHY_CHAN_IFACE_ROOMLIST_QUARK);
188 g_signal_connect (priv->tp_chan, "destroy",
189 G_CALLBACK (tp_roomlist_destroy_cb),
191 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
192 G_CALLBACK (tp_roomlist_closed_cb),
194 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "ListingRooms",
195 G_CALLBACK (tp_roomlist_listing_cb),
197 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "GotRooms",
198 G_CALLBACK (tp_roomlist_got_rooms_cb),
205 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
207 EmpathyTpRoomlistPriv *priv;
208 GError *error = NULL;
209 gboolean listing = FALSE;
211 g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
213 priv = GET_PRIV (list);
215 if (!tp_chan_type_room_list_get_listing_rooms (priv->roomlist_iface,
218 empathy_debug (DEBUG_DOMAIN,
219 "Error GetListingRooms: %s",
220 error ? error->message : "No error given");
221 g_clear_error (&error);
229 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
231 EmpathyTpRoomlistPriv *priv;
232 GError *error = NULL;
234 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
236 priv = GET_PRIV (list);
238 if (!tp_chan_type_room_list_list_rooms (priv->roomlist_iface, &error)) {
239 empathy_debug (DEBUG_DOMAIN,
240 "Error ListRooms: %s",
241 error ? error->message : "No error given");
242 g_clear_error (&error);
247 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
249 EmpathyTpRoomlistPriv *priv;
250 GError *error = NULL;
252 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
254 priv = GET_PRIV (list);
256 if (!tp_chan_type_room_list_stop_listing (priv->roomlist_iface, &error)) {
257 empathy_debug (DEBUG_DOMAIN,
258 "Error StopListing: %s",
259 error ? error->message : "No error given");
260 g_clear_error (&error);
265 tp_roomlist_destroy_cb (TpChan *tp_chan,
266 EmpathyTpRoomlist *list)
268 EmpathyTpRoomlistPriv *priv;
270 priv = GET_PRIV (list);
272 empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
274 tp_roomlist_listing_cb (priv->roomlist_iface, FALSE, list);
276 g_object_unref (priv->tp_chan);
277 priv->tp_chan = NULL;
278 priv->roomlist_iface = NULL;
280 g_signal_emit (list, signals[DESTROY], 0);
284 tp_roomlist_closed_cb (TpChan *tp_chan,
285 EmpathyTpRoomlist *list)
287 EmpathyTpRoomlistPriv *priv;
289 priv = GET_PRIV (list);
291 /* The channel is closed, do just like if the proxy was destroyed */
292 g_signal_handlers_disconnect_by_func (priv->tp_chan,
293 tp_roomlist_destroy_cb,
295 tp_roomlist_destroy_cb (priv->tp_chan, list);
299 tp_roomlist_listing_cb (DBusGProxy *roomlist_iface,
301 EmpathyTpRoomlist *list)
303 empathy_debug (DEBUG_DOMAIN, "Listing: %s", listing ? "Yes" : "No");
304 g_signal_emit (list, signals[LISTING], 0, listing);
308 tp_roomlist_got_rooms_cb (DBusGProxy *roomlist_iface,
309 GPtrArray *room_list,
310 EmpathyTpRoomlist *list)
312 EmpathyTpRoomlistPriv *priv;
315 priv = GET_PRIV (list);
317 for (i = 0; i < room_list->len; i++) {
318 EmpathyChatroom *chatroom;
320 const gchar *room_name;
321 const GValue *room_name_value;
322 GValueArray *room_struct;
324 const gchar *channel_type;
327 /* Get information */
328 room_struct = g_ptr_array_index (room_list, i);
329 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
330 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
331 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
333 /* Create the chatroom */
334 room_name_value = g_hash_table_lookup (info, "name");
335 room_name = g_value_get_string (room_name_value);
336 room_id = empathy_inspect_handle (priv->account,
338 TP_HANDLE_TYPE_ROOM);
339 chatroom = empathy_chatroom_new_full (priv->account,
344 /* Tells the world */
345 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
347 g_object_unref (chatroom);