]> git.0d.be Git - empathy.git/blob - libempathy/empathy-tp-roomlist.c
Initial room list support. It does not works yet.
[empathy.git] / libempathy / empathy-tp-roomlist.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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.
19  * 
20  * Authors: Xavier Claessens <xclaesse@gmail.com>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26
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>
31
32 #include <libmissioncontrol/mission-control.h>
33
34 #include "empathy-tp-roomlist.h"
35 #include "empathy-chatroom.h"
36 #include "empathy-utils.h"
37 #include "empathy-debug.h"
38
39 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
40                        EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
41
42 #define DEBUG_DOMAIN "TpRoomlist"
43
44 struct _EmpathyTpRoomlistPriv {
45         McAccount  *account;
46         TpChan     *tp_chan;
47         DBusGProxy *roomlist_iface;
48 };
49
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,
58                                             gboolean                listing,
59                                             EmpathyTpRoomlist      *list);
60 static void tp_roomlist_got_rooms_cb       (DBusGProxy             *roomlist_iface,
61                                             GPtrArray              *room_list,
62                                             EmpathyTpRoomlist      *list);
63
64 enum {
65         NEW_ROOM,
66         LISTING,
67         DESTROY,
68         LAST_SIGNAL
69 };
70
71 static guint signals[LAST_SIGNAL];
72
73 G_DEFINE_TYPE (EmpathyTpRoomlist, empathy_tp_roomlist, G_TYPE_OBJECT);
74
75 static void
76 empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass)
77 {
78         GObjectClass *object_class = G_OBJECT_CLASS (klass);
79
80         object_class->finalize = tp_roomlist_finalize;
81
82         signals[NEW_ROOM] =
83                 g_signal_new ("new-room",
84                               G_TYPE_FROM_CLASS (klass),
85                               G_SIGNAL_RUN_LAST,
86                               0,
87                               NULL, NULL,
88                               g_cclosure_marshal_VOID__OBJECT,
89                               G_TYPE_NONE,
90                               1, EMPATHY_TYPE_CHATROOM);
91
92         signals[LISTING] =
93                 g_signal_new ("listing",
94                               G_TYPE_FROM_CLASS (klass),
95                               G_SIGNAL_RUN_LAST,
96                               0,
97                               NULL, NULL,
98                               g_cclosure_marshal_VOID__BOOLEAN,
99                               G_TYPE_NONE,
100                               1, G_TYPE_BOOLEAN);
101
102         signals[DESTROY] =
103                 g_signal_new ("destroy",
104                               G_TYPE_FROM_CLASS (klass),
105                               G_SIGNAL_RUN_LAST,
106                               0,
107                               NULL, NULL,
108                               g_cclosure_marshal_VOID__VOID,
109                               G_TYPE_NONE,
110                               0);
111
112         g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
113 }
114
115 static void
116 empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
117 {
118 }
119
120 static void
121 tp_roomlist_finalize (GObject *object)
122 {
123         EmpathyTpRoomlistPriv *priv;
124         GError                *error = NULL;
125
126         priv = GET_PRIV (object);
127
128         if (priv->tp_chan) {
129                 g_signal_handlers_disconnect_by_func (priv->tp_chan,
130                                                       tp_roomlist_destroy_cb,
131                                                       object);
132
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);
139                 }
140                 g_object_unref (priv->tp_chan);
141         }
142
143         if (priv->account) {
144                 g_object_unref (priv->account);
145         }
146
147         G_OBJECT_CLASS (empathy_tp_roomlist_parent_class)->finalize (object);
148 }
149
150 EmpathyTpRoomlist *
151 empathy_tp_roomlist_new (McAccount *account)
152 {
153         EmpathyTpRoomlist     *list;
154         EmpathyTpRoomlistPriv *priv;
155         TpConn                *tp_conn;
156         MissionControl        *mc;
157         const gchar           *bus_name;
158
159         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
160
161         list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST, NULL);
162         priv = GET_PRIV (list);
163
164         mc = empathy_mission_control_new ();
165         tp_conn = mission_control_get_connection (mc, account, NULL);
166         g_object_unref (mc);
167
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 (),
170                                              tp_conn,
171                                              bus_name,
172                                              TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
173                                              TP_HANDLE_TYPE_NONE,
174                                              0,
175                                              TRUE);
176         g_object_unref (tp_conn);
177
178         if (!priv->tp_chan) {
179                 empathy_debug (DEBUG_DOMAIN, "Failed to get roomlist channel");
180                 g_object_unref (list);
181                 return NULL;
182         }
183
184         priv->account = g_object_ref (account);
185         priv->roomlist_iface = tp_chan_get_interface (priv->tp_chan,
186                                                       TELEPATHY_CHAN_IFACE_ROOMLIST_QUARK);
187
188         g_signal_connect (priv->tp_chan, "destroy",
189                           G_CALLBACK (tp_roomlist_destroy_cb),
190                           list);
191         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
192                                      G_CALLBACK (tp_roomlist_closed_cb),
193                                      list, NULL);
194         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "ListingRooms",
195                                      G_CALLBACK (tp_roomlist_listing_cb),
196                                      list, NULL);
197         dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->roomlist_iface), "GotRooms",
198                                      G_CALLBACK (tp_roomlist_got_rooms_cb),
199                                      list, NULL);
200
201         return list;
202 }
203
204 gboolean
205 empathy_tp_roomlist_is_listing (EmpathyTpRoomlist *list)
206 {
207         EmpathyTpRoomlistPriv *priv;
208         GError                *error = NULL;
209         gboolean               listing = FALSE;
210
211         g_return_val_if_fail (EMPATHY_IS_TP_ROOMLIST (list), FALSE);
212
213         priv = GET_PRIV (list);
214
215         if (!tp_chan_type_room_list_get_listing_rooms (priv->roomlist_iface,
216                                                        &listing,
217                                                        &error)) {
218                 empathy_debug (DEBUG_DOMAIN, 
219                               "Error GetListingRooms: %s",
220                               error ? error->message : "No error given");
221                 g_clear_error (&error);
222                 return FALSE;
223         }
224
225         return listing;
226 }
227
228 void
229 empathy_tp_roomlist_start (EmpathyTpRoomlist *list)
230 {
231         EmpathyTpRoomlistPriv *priv;
232         GError                *error = NULL;
233
234         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
235
236         priv = GET_PRIV (list);
237
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);
243         }
244 }
245
246 void
247 empathy_tp_roomlist_stop (EmpathyTpRoomlist *list)
248 {
249         EmpathyTpRoomlistPriv *priv;
250         GError                *error = NULL;
251
252         g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
253
254         priv = GET_PRIV (list);
255
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);
261         }
262 }
263
264 static void
265 tp_roomlist_destroy_cb (TpChan            *tp_chan,
266                         EmpathyTpRoomlist *list)
267 {
268         EmpathyTpRoomlistPriv *priv;
269
270         priv = GET_PRIV (list);
271
272         empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
273
274         tp_roomlist_listing_cb (priv->roomlist_iface, FALSE, list);
275
276         g_object_unref  (priv->tp_chan);
277         priv->tp_chan = NULL;
278         priv->roomlist_iface = NULL;
279
280         g_signal_emit (list, signals[DESTROY], 0);
281 }
282
283 static void
284 tp_roomlist_closed_cb (TpChan            *tp_chan,
285                        EmpathyTpRoomlist *list)
286 {
287         EmpathyTpRoomlistPriv *priv;
288
289         priv = GET_PRIV (list);
290
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,
294                                               list);
295         tp_roomlist_destroy_cb (priv->tp_chan, list);
296 }
297
298 static void
299 tp_roomlist_listing_cb (DBusGProxy        *roomlist_iface,
300                         gboolean           listing,
301                         EmpathyTpRoomlist *list)
302 {
303         empathy_debug (DEBUG_DOMAIN, "Listing: %s", listing ? "Yes" : "No");
304         g_signal_emit (list, signals[LISTING], 0, listing);
305 }
306
307 static void
308 tp_roomlist_got_rooms_cb (DBusGProxy        *roomlist_iface,
309                           GPtrArray         *room_list,
310                           EmpathyTpRoomlist *list)
311 {
312         EmpathyTpRoomlistPriv *priv;
313         guint                  i;
314
315         priv = GET_PRIV (list);
316
317         g_print ("Got negsghgfdhgfdhgfdw room !!!");
318
319         for (i = 0; i < room_list->len; i++) {
320                 EmpathyChatroom *chatroom;
321                 gchar           *room_id;
322                 const gchar     *room_name;
323                 GValueArray     *room_struct;
324                 guint            handle;
325                 const gchar     *channel_type;
326                 GHashTable      *info;
327
328                 /* Get information */
329                 room_struct = g_ptr_array_index (room_list, i);
330                 handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
331                 channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
332                 info = g_value_get_boxed (g_value_array_get_nth (room_struct, 0));
333
334                 g_print ("Got new room !!!");
335
336                 /* Create the chatroom */
337                 room_name = g_hash_table_lookup (info, "name");
338                 room_id = empathy_inspect_handle (priv->account,
339                                                   handle,
340                                                   TP_HANDLE_TYPE_ROOM);
341                 chatroom = empathy_chatroom_new_full (priv->account,
342                                                       room_id,
343                                                       room_name,
344                                                       FALSE);
345
346                 /* Tells the world */
347                 g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
348
349                 g_object_unref (chatroom);
350         }
351 }
352