1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 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 <libtelepathy/tp-chan-type-room-list-gen.h>
27 #include <libtelepathy/tp-helpers.h>
28 #include <libtelepathy/tp-conn.h>
29 #include <libtelepathy/tp-chan.h>
31 #include <libmissioncontrol/mission-control.h>
33 #include "empathy-tp-roomlist.h"
34 #include "empathy-chatroom.h"
35 #include "empathy-utils.h"
36 #include "empathy-debug.h"
38 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
39 EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
41 #define DEBUG_DOMAIN "TpRoomlist"
43 struct _EmpathyTpRoomlistPriv {
46 DBusGProxy *roomlist_iface;
49 static void empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass);
50 static void empathy_tp_roomlist_init (EmpathyTpRoomlist *chat);
51 static void tp_roomlist_finalize (GObject *object);
52 static void tp_roomlist_destroy_cb (TpChan *tp_chan,
53 EmpathyTpRoomlist *list);
54 static void tp_roomlist_closed_cb (TpChan *tp_chan,
55 EmpathyTpRoomlist *list);
56 static void tp_roomlist_listing_cb (DBusGProxy *roomlist_iface,
58 EmpathyTpRoomlist *list);
59 static void tp_roomlist_got_rooms_cb (DBusGProxy *roomlist_iface,
61 EmpathyTpRoomlist *list);
70 static guint signals[LAST_SIGNAL];
72 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
75 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
77 GObjectClass *object_class = G_OBJECT_CLASS (klass);
79 object_class->finalize = tp_roomlist_finalize;
82 g_signal_new ("new-room",
83 G_TYPE_FROM_CLASS (klass),
87 g_cclosure_marshal_VOID__OBJECT,
89 1, EMPATHY_TYPE_CHATROOM);
92 g_signal_new ("listing",
93 G_TYPE_FROM_CLASS (klass),
97 g_cclosure_marshal_VOID__BOOLEAN,
102 g_signal_new ("destroy",
103 G_TYPE_FROM_CLASS (klass),
107 g_cclosure_marshal_VOID__VOID,
111 g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
115 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
120 tp_roomlist_finalize (GObject *object)
122 EmpathyTpRoomlistPriv *priv;
123 GError *error = NULL;
125 priv = GET_PRIV (object);
128 g_signal_handlers_disconnect_by_func (priv->tp_chan,
129 tp_roomlist_destroy_cb,
132 empathy_debug (DEBUG_DOMAIN, "Closing channel...");
133 if (!tp_chan_close (DBUS_G_PROXY (priv->tp_chan), &error)) {
134 empathy_debug (DEBUG_DOMAIN,
135 "Error closing roomlist channel: %s",
136 error ? error->message : "No error given");
137 g_clear_error (&error);
139 g_object_unref (priv->tp_chan);
143 g_object_unref (priv->account);
146 G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
150 empathy_tp_roomlist_new (McAccount *account)
152 EmpathyTpRoomlist *list;
153 EmpathyTpRoomlistPriv *priv;
156 const gchar *bus_name;
158 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
160 list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST, NULL);
161 priv = GET_PRIV (list);
163 mc = empathy_mission_control_new ();
164 tp_conn = mission_control_get_connection (mc, account, NULL);
167 bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (tp_conn));
168 priv->tp_chan = tp_conn_new_channel (tp_get_bus (),
171 TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
175 g_object_unref (tp_conn);
177 if (!priv->tp_chan) {
178 empathy_debug (DEBUG_DOMAIN, "Failed to get roomlist channel");
179 g_object_unref (list);
183 priv->account = g_object_ref (account);
184 priv->roomlist_iface = tp_chan_get_interface (priv->tp_chan,
185 TP_IFACE_QUARK_CHANNEL_TYPE_ROOM_LIST);
187 g_signal_connect (priv->tp_chan, "destroy",
188 G_CALLBACK (tp_roomlist_destroy_cb),
190 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
191 G_CALLBACK (tp_roomlist_closed_cb),
193 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "ListingRooms",
194 G_CALLBACK (tp_roomlist_listing_cb),
196 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "GotRooms",
197 G_CALLBACK (tp_roomlist_got_rooms_cb),
204 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
206 EmpathyTpRoomlistPriv *priv;
207 GError *error = NULL;
208 gboolean listing = FALSE;
210 g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
212 priv = GET_PRIV (list);
214 if (!tp_chan_type_room_list_get_listing_rooms (priv->roomlist_iface,
217 empathy_debug (DEBUG_DOMAIN,
218 "Error GetListingRooms: %s",
219 error ? error->message : "No error given");
220 g_clear_error (&error);
228 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
230 EmpathyTpRoomlistPriv *priv;
231 GError *error = NULL;
233 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
235 priv = GET_PRIV (list);
237 if (!tp_chan_type_room_list_list_rooms (priv->roomlist_iface, &error)) {
238 empathy_debug (DEBUG_DOMAIN,
239 "Error ListRooms: %s",
240 error ? error->message : "No error given");
241 g_clear_error (&error);
246 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
248 EmpathyTpRoomlistPriv *priv;
249 GError *error = NULL;
251 g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
253 priv = GET_PRIV (list);
255 if (!tp_chan_type_room_list_stop_listing (priv->roomlist_iface, &error)) {
256 empathy_debug (DEBUG_DOMAIN,
257 "Error StopListing: %s",
258 error ? error->message : "No error given");
259 g_clear_error (&error);
264 tp_roomlist_destroy_cb (TpChan *tp_chan,
265 EmpathyTpRoomlist *list)
267 EmpathyTpRoomlistPriv *priv;
269 priv = GET_PRIV (list);
271 empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
273 tp_roomlist_listing_cb (priv->roomlist_iface, FALSE, list);
275 g_object_unref (priv->tp_chan);
276 priv->tp_chan = NULL;
277 priv->roomlist_iface = NULL;
279 g_signal_emit (list, signals[DESTROY], 0);
283 tp_roomlist_closed_cb (TpChan *tp_chan,
284 EmpathyTpRoomlist *list)
286 EmpathyTpRoomlistPriv *priv;
288 priv = GET_PRIV (list);
290 /* The channel is closed, do just like if the proxy was destroyed */
291 g_signal_handlers_disconnect_by_func (priv->tp_chan,
292 tp_roomlist_destroy_cb,
294 tp_roomlist_destroy_cb (priv->tp_chan, list);
298 tp_roomlist_listing_cb (DBusGProxy *roomlist_iface,
300 EmpathyTpRoomlist *list)
302 empathy_debug (DEBUG_DOMAIN, "Listing: %s", listing ? "Yes" : "No");
303 g_signal_emit (list, signals[LISTING], 0, listing);
307 tp_roomlist_got_rooms_cb (DBusGProxy *roomlist_iface,
308 GPtrArray *room_list,
309 EmpathyTpRoomlist *list)
311 EmpathyTpRoomlistPriv *priv;
314 priv = GET_PRIV (list);
316 for (i = 0; i < room_list->len; i++) {
317 EmpathyChatroom *chatroom;
319 const gchar *room_name;
320 const GValue *room_name_value;
321 GValueArray *room_struct;
323 const gchar *channel_type;
326 /* Get information */
327 room_struct = g_ptr_array_index (room_list, i);
328 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
329 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
330 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
332 /* Create the chatroom */
333 room_name_value = g_hash_table_lookup (info, "name");
334 room_name = g_value_get_string (room_name_value);
335 room_id = empathy_inspect_handle (priv->account,
337 TP_HANDLE_TYPE_ROOM);
338 chatroom = empathy_chatroom_new_full (priv->account,
343 /* Tells the world */
344 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
346 g_object_unref (chatroom);