1 /* |
|
2 * gabble-roomlist-channel.c - Source for GabbleRoomlistChannel |
|
3 * Copyright (C) 2005 Collabora Ltd. |
|
4 * |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Lesser General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2.1 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Lesser General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Lesser General Public |
|
17 * License along with this library; if not, write to the Free Software |
|
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 */ |
|
20 |
|
21 #include <dbus/dbus-glib.h> |
|
22 #include <stdio.h> |
|
23 #include <stdlib.h> |
|
24 #include <string.h> |
|
25 |
|
26 #define DEBUG_FLAG GABBLE_DEBUG_ROOMLIST |
|
27 |
|
28 #include "debug.h" |
|
29 #include "disco.h" |
|
30 #include "gabble-connection.h" |
|
31 #include "handles.h" |
|
32 #include "handle-set.h" |
|
33 #include "telepathy-constants.h" |
|
34 #include "telepathy-interfaces.h" |
|
35 #include "telepathy-helpers.h" |
|
36 #include "tp-channel-iface.h" |
|
37 #include "namespaces.h" |
|
38 #include "util.h" |
|
39 |
|
40 #include "gabble-roomlist-channel.h" |
|
41 #include "gabble-roomlist-channel-glue.h" |
|
42 #include "gabble-roomlist-channel-signals-marshal.h" |
|
43 |
|
44 #include "gabble_enums.h" |
|
45 |
|
46 #define TP_TYPE_ROOM_STRUCT (dbus_g_type_get_struct ("GValueArray", \ |
|
47 G_TYPE_UINT, \ |
|
48 G_TYPE_STRING, \ |
|
49 dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), \ |
|
50 G_TYPE_INVALID)) |
|
51 |
|
52 #define TP_TYPE_ROOM_LIST (dbus_g_type_get_collection ("GPtrArray", \ |
|
53 TP_TYPE_ROOM_STRUCT)) |
|
54 |
|
55 #ifndef EMULATOR |
|
56 G_DEFINE_TYPE_WITH_CODE (GabbleRoomlistChannel, gabble_roomlist_channel, |
|
57 G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)); |
|
58 #endif |
|
59 |
|
60 /* signal enum */ |
|
61 enum |
|
62 { |
|
63 CLOSED, |
|
64 GOT_ROOMS, |
|
65 LISTING_ROOMS, |
|
66 LAST_SIGNAL |
|
67 #ifdef EMULATOR |
|
68 = LAST_SIGNAL_ROOM_CHNL |
|
69 #endif |
|
70 |
|
71 }; |
|
72 |
|
73 #ifdef EMULATOR |
|
74 #include "libgabble_wsd_solution.h" |
|
75 |
|
76 GET_STATIC_ARRAY_FROM_TLS(signals,gabble_room_chnl,guint) |
|
77 #define signals (GET_WSD_VAR_NAME(signals,gabble_room_chnl, s)()) |
|
78 |
|
79 GET_STATIC_VAR_FROM_TLS(gabble_roomlist_channel_parent_class,gabble_room_chnl,gpointer) |
|
80 #define gabble_roomlist_channel_parent_class (*GET_WSD_VAR_NAME(gabble_roomlist_channel_parent_class,gabble_room_chnl,s)()) |
|
81 |
|
82 GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_room_chnl,GType) |
|
83 #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_room_chnl,s)()) |
|
84 |
|
85 |
|
86 static void gabble_roomlist_channel_init (GabbleRoomlistChannel *self); |
|
87 static void gabble_roomlist_channel_class_init (GabbleRoomlistChannelClass *klass); |
|
88 static void gabble_roomlist_channel_class_intern_init (gpointer klass) |
|
89 { |
|
90 gabble_roomlist_channel_parent_class = g_type_class_peek_parent (klass); |
|
91 gabble_roomlist_channel_class_init ((GabbleRoomlistChannelClass*) klass); |
|
92 } |
|
93 EXPORT_C GType gabble_roomlist_channel_get_type (void) |
|
94 { |
|
95 if ((g_define_type_id == 0)) { static const GTypeInfo g_define_type_info = { sizeof (GabbleRoomlistChannelClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_roomlist_channel_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleRoomlistChannel), 0, (GInstanceInitFunc) gabble_roomlist_channel_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleRoomlistChannel"), &g_define_type_info, (GTypeFlags) 0); { { static const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc) ((void *)0) }; g_type_add_interface_static (g_define_type_id, tp_channel_iface_get_type(), &g_implement_interface_info); } ; } } return g_define_type_id; } ; |
|
96 |
|
97 |
|
98 #else |
|
99 |
|
100 static guint signals[LAST_SIGNAL] = {0}; |
|
101 |
|
102 #endif |
|
103 |
|
104 |
|
105 /* properties */ |
|
106 enum |
|
107 { |
|
108 PROP_OBJECT_PATH = 1, |
|
109 PROP_CHANNEL_TYPE, |
|
110 PROP_HANDLE_TYPE, |
|
111 PROP_HANDLE, |
|
112 PROP_CONNECTION, |
|
113 PROP_CONFERENCE_SERVER, |
|
114 LAST_PROPERTY |
|
115 }; |
|
116 |
|
117 /* private structure */ |
|
118 typedef struct _GabbleRoomlistChannelPrivate GabbleRoomlistChannelPrivate; |
|
119 |
|
120 struct _GabbleRoomlistChannelPrivate |
|
121 { |
|
122 GabbleConnection *conn; |
|
123 gchar *object_path; |
|
124 gchar *conference_server; |
|
125 |
|
126 gboolean closed; |
|
127 gboolean listing; |
|
128 |
|
129 gpointer disco_pipeline; |
|
130 GabbleHandleSet *signalled_rooms; |
|
131 |
|
132 GPtrArray *pending_room_signals; |
|
133 guint timer_source_id; |
|
134 |
|
135 gboolean dispose_has_run; |
|
136 }; |
|
137 |
|
138 #define GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE(obj) \ |
|
139 ((GabbleRoomlistChannelPrivate *)obj->priv) |
|
140 |
|
141 #define ROOM_SIGNAL_INTERVAL 300 |
|
142 |
|
143 static gboolean emit_room_signal (gpointer data); |
|
144 |
|
145 static void |
|
146 gabble_roomlist_channel_init (GabbleRoomlistChannel *self) |
|
147 { |
|
148 GabbleRoomlistChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, |
|
149 GABBLE_TYPE_ROOMLIST_CHANNEL, GabbleRoomlistChannelPrivate); |
|
150 |
|
151 self->priv = priv; |
|
152 |
|
153 priv->pending_room_signals = g_ptr_array_new (); |
|
154 } |
|
155 |
|
156 |
|
157 static GObject * |
|
158 gabble_roomlist_channel_constructor (GType type, guint n_props, |
|
159 GObjectConstructParam *props) |
|
160 { |
|
161 GObject *obj; |
|
162 GabbleRoomlistChannelPrivate *priv; |
|
163 DBusGConnection *bus; |
|
164 |
|
165 obj = G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)-> |
|
166 constructor (type, n_props, props); |
|
167 priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (GABBLE_ROOMLIST_CHANNEL (obj)); |
|
168 |
|
169 bus = tp_get_bus (); |
|
170 dbus_g_connection_register_g_object (bus, priv->object_path, obj); |
|
171 |
|
172 return obj; |
|
173 } |
|
174 |
|
175 static void |
|
176 gabble_roomlist_channel_get_property (GObject *object, |
|
177 guint property_id, |
|
178 GValue *value, |
|
179 GParamSpec *pspec) |
|
180 { |
|
181 GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object); |
|
182 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan); |
|
183 |
|
184 switch (property_id) { |
|
185 case PROP_OBJECT_PATH: |
|
186 g_value_set_string (value, priv->object_path); |
|
187 break; |
|
188 case PROP_CHANNEL_TYPE: |
|
189 g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_ROOM_LIST); |
|
190 break; |
|
191 case PROP_HANDLE_TYPE: |
|
192 g_value_set_uint (value, TP_HANDLE_TYPE_NONE); |
|
193 break; |
|
194 case PROP_HANDLE: |
|
195 g_value_set_uint (value, 0); |
|
196 break; |
|
197 case PROP_CONNECTION: |
|
198 g_value_set_object (value, priv->conn); |
|
199 break; |
|
200 case PROP_CONFERENCE_SERVER: |
|
201 g_value_set_string (value, priv->conference_server); |
|
202 break; |
|
203 default: |
|
204 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
|
205 break; |
|
206 } |
|
207 } |
|
208 |
|
209 static void |
|
210 gabble_roomlist_channel_set_property (GObject *object, |
|
211 guint property_id, |
|
212 const GValue *value, |
|
213 GParamSpec *pspec) |
|
214 { |
|
215 GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object); |
|
216 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan); |
|
217 GabbleHandleSet *new_signalled_rooms; |
|
218 |
|
219 switch (property_id) { |
|
220 case PROP_OBJECT_PATH: |
|
221 g_free (priv->object_path); |
|
222 priv->object_path = g_value_dup_string (value); |
|
223 break; |
|
224 case PROP_HANDLE: |
|
225 /* this property is writable in the interface, but not actually |
|
226 * meaningfully changable on this channel, so we do nothing */ |
|
227 break; |
|
228 case PROP_CONNECTION: |
|
229 priv->conn = g_value_get_object (value); |
|
230 new_signalled_rooms = handle_set_new (priv->conn->handles, TP_HANDLE_TYPE_ROOM); |
|
231 if (priv->signalled_rooms != NULL) |
|
232 { |
|
233 const GIntSet *add; |
|
234 GIntSet *tmp; |
|
235 add = handle_set_peek (priv->signalled_rooms); |
|
236 tmp = handle_set_update (new_signalled_rooms, add); |
|
237 handle_set_destroy (priv->signalled_rooms); |
|
238 g_intset_destroy (tmp); |
|
239 } |
|
240 priv->signalled_rooms = new_signalled_rooms; |
|
241 break; |
|
242 case PROP_CONFERENCE_SERVER: |
|
243 g_free (priv->conference_server); |
|
244 priv->conference_server = g_value_dup_string (value); |
|
245 break; |
|
246 default: |
|
247 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
|
248 break; |
|
249 } |
|
250 } |
|
251 |
|
252 static void gabble_roomlist_channel_dispose (GObject *object); |
|
253 static void gabble_roomlist_channel_finalize (GObject *object); |
|
254 |
|
255 static void |
|
256 gabble_roomlist_channel_class_init (GabbleRoomlistChannelClass *gabble_roomlist_channel_class) |
|
257 { |
|
258 GObjectClass *object_class = G_OBJECT_CLASS (gabble_roomlist_channel_class); |
|
259 GParamSpec *param_spec; |
|
260 |
|
261 g_type_class_add_private (gabble_roomlist_channel_class, sizeof (GabbleRoomlistChannelPrivate)); |
|
262 |
|
263 object_class->constructor = gabble_roomlist_channel_constructor; |
|
264 |
|
265 object_class->get_property = gabble_roomlist_channel_get_property; |
|
266 object_class->set_property = gabble_roomlist_channel_set_property; |
|
267 |
|
268 object_class->dispose = gabble_roomlist_channel_dispose; |
|
269 object_class->finalize = gabble_roomlist_channel_finalize; |
|
270 |
|
271 g_object_class_override_property (object_class, PROP_OBJECT_PATH, "object-path"); |
|
272 g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, "channel-type"); |
|
273 g_object_class_override_property (object_class, PROP_HANDLE_TYPE, "handle-type"); |
|
274 g_object_class_override_property (object_class, PROP_HANDLE, "handle"); |
|
275 |
|
276 param_spec = g_param_spec_object ("connection", "GabbleConnection object", |
|
277 "Gabble connection object that owns this " |
|
278 "room list channel object.", |
|
279 GABBLE_TYPE_CONNECTION, |
|
280 G_PARAM_CONSTRUCT_ONLY | |
|
281 G_PARAM_READWRITE | |
|
282 G_PARAM_STATIC_NICK | |
|
283 G_PARAM_STATIC_BLURB); |
|
284 g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); |
|
285 |
|
286 param_spec = g_param_spec_string ("conference-server", |
|
287 "Name of conference server to use", |
|
288 "Name of the XMPP conference server " |
|
289 "on which to list rooms", |
|
290 "", |
|
291 G_PARAM_CONSTRUCT_ONLY | |
|
292 G_PARAM_WRITABLE | |
|
293 G_PARAM_STATIC_NAME | |
|
294 G_PARAM_STATIC_BLURB); |
|
295 g_object_class_install_property (object_class, PROP_CONFERENCE_SERVER, |
|
296 param_spec); |
|
297 |
|
298 signals[CLOSED] = |
|
299 g_signal_new ("closed", |
|
300 G_OBJECT_CLASS_TYPE (gabble_roomlist_channel_class), |
|
301 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
302 0, |
|
303 NULL, NULL, |
|
304 g_cclosure_marshal_VOID__VOID, |
|
305 G_TYPE_NONE, 0); |
|
306 |
|
307 signals[GOT_ROOMS] = |
|
308 g_signal_new ("got-rooms", |
|
309 G_OBJECT_CLASS_TYPE (gabble_roomlist_channel_class), |
|
310 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
311 0, |
|
312 NULL, NULL, |
|
313 g_cclosure_marshal_VOID__BOXED, |
|
314 G_TYPE_NONE, 1, (dbus_g_type_get_collection ("GPtrArray", (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)), G_TYPE_INVALID))))); |
|
315 |
|
316 signals[LISTING_ROOMS] = |
|
317 g_signal_new ("listing-rooms", |
|
318 G_OBJECT_CLASS_TYPE (gabble_roomlist_channel_class), |
|
319 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
320 0, |
|
321 NULL, NULL, |
|
322 g_cclosure_marshal_VOID__BOOLEAN, |
|
323 G_TYPE_NONE, 1, G_TYPE_BOOLEAN); |
|
324 |
|
325 dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (gabble_roomlist_channel_class), &dbus_glib_gabble_roomlist_channel_object_info); |
|
326 } |
|
327 |
|
328 void |
|
329 gabble_roomlist_channel_dispose (GObject *object) |
|
330 { |
|
331 GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object); |
|
332 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self); |
|
333 |
|
334 if (priv->dispose_has_run) |
|
335 return; |
|
336 |
|
337 priv->dispose_has_run = TRUE; |
|
338 |
|
339 if (priv->listing) |
|
340 { |
|
341 emit_room_signal (object); |
|
342 g_signal_emit (object, signals [LISTING_ROOMS], 0, FALSE); |
|
343 priv->listing = FALSE; |
|
344 } |
|
345 |
|
346 if (!priv->closed) |
|
347 { |
|
348 g_signal_emit (object, signals[CLOSED], 0); |
|
349 priv->closed = TRUE; |
|
350 } |
|
351 |
|
352 if (priv->disco_pipeline != NULL) |
|
353 { |
|
354 gabble_disco_pipeline_destroy (priv->disco_pipeline); |
|
355 priv->disco_pipeline = NULL; |
|
356 } |
|
357 |
|
358 if (priv->timer_source_id) |
|
359 { |
|
360 g_source_remove (priv->timer_source_id); |
|
361 priv->timer_source_id = 0; |
|
362 } |
|
363 |
|
364 g_assert (priv->pending_room_signals != NULL); |
|
365 g_assert (priv->pending_room_signals->len == 0); |
|
366 g_ptr_array_free (priv->pending_room_signals, TRUE); |
|
367 priv->pending_room_signals = NULL; |
|
368 |
|
369 if (G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose) |
|
370 G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose (object); |
|
371 } |
|
372 |
|
373 void |
|
374 gabble_roomlist_channel_finalize (GObject *object) |
|
375 { |
|
376 GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object); |
|
377 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self); |
|
378 |
|
379 /* free any data held directly by the object here */ |
|
380 |
|
381 g_free (priv->object_path); |
|
382 g_free (priv->conference_server); |
|
383 |
|
384 if (priv->signalled_rooms != NULL) |
|
385 handle_set_destroy (priv->signalled_rooms); |
|
386 |
|
387 G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->finalize (object); |
|
388 } |
|
389 |
|
390 GabbleRoomlistChannel * |
|
391 _gabble_roomlist_channel_new (GabbleConnection *conn, |
|
392 const gchar *object_path, |
|
393 const gchar *conference_server) |
|
394 { |
|
395 g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); |
|
396 g_return_val_if_fail (object_path != NULL, NULL); |
|
397 g_return_val_if_fail (conference_server != NULL, NULL); |
|
398 |
|
399 return GABBLE_ROOMLIST_CHANNEL ( |
|
400 g_object_new (GABBLE_TYPE_ROOMLIST_CHANNEL, |
|
401 "connection", conn, |
|
402 "object-path", object_path, |
|
403 "conference-server", conference_server, NULL)); |
|
404 } |
|
405 |
|
406 static gboolean |
|
407 emit_room_signal (gpointer data) |
|
408 { |
|
409 GabbleRoomlistChannel *chan = data; |
|
410 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan); |
|
411 |
|
412 if (!priv->listing) |
|
413 return FALSE; |
|
414 |
|
415 if (priv->pending_room_signals->len == 0) |
|
416 return TRUE; |
|
417 |
|
418 g_signal_emit (chan, signals[GOT_ROOMS], 0, priv->pending_room_signals); |
|
419 |
|
420 while (priv->pending_room_signals->len != 0) |
|
421 { |
|
422 gpointer boxed = g_ptr_array_index (priv->pending_room_signals, 0); |
|
423 g_boxed_free (TP_TYPE_ROOM_STRUCT, boxed); |
|
424 g_ptr_array_remove_index_fast (priv->pending_room_signals, 0); |
|
425 } |
|
426 |
|
427 return TRUE; |
|
428 } |
|
429 |
|
430 /** |
|
431 * destroy_value: |
|
432 * @data: a GValue to destroy |
|
433 * |
|
434 * destroys a GValue allocated on the heap |
|
435 */ |
|
436 static void |
|
437 destroy_value (GValue *value) |
|
438 { |
|
439 g_value_unset (value); |
|
440 g_free (value); |
|
441 } |
|
442 |
|
443 static void |
|
444 room_info_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data) |
|
445 { |
|
446 GabbleRoomlistChannel *chan = user_data; |
|
447 GabbleRoomlistChannelPrivate *priv; |
|
448 const char *jid, *category, *type, *var, *name; |
|
449 GabbleHandle handle; |
|
450 GHashTable *keys; |
|
451 GValue room = {0,}; |
|
452 GValue *tmp; |
|
453 gpointer k, v; |
|
454 |
|
455 #define INSERT_KEY(hash, name, type, type2, value) \ |
|
456 do {\ |
|
457 tmp = g_new0 (GValue, 1); \ |
|
458 g_value_init (tmp, (type)); \ |
|
459 g_value_set_##type2 (tmp, (value)); \ |
|
460 g_hash_table_insert (hash, (name), tmp); \ |
|
461 } while (0) |
|
462 |
|
463 g_assert (GABBLE_IS_ROOMLIST_CHANNEL (chan)); |
|
464 priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan); |
|
465 |
|
466 jid = item->jid; |
|
467 name = item->name; |
|
468 category = item->category; |
|
469 type = item->type; |
|
470 |
|
471 if (0 != strcmp (category, "conference") || |
|
472 0 != strcmp (type, "text")) |
|
473 return; |
|
474 |
|
475 if (!g_hash_table_lookup_extended (item->features, "http://jabber.org/protocol/muc", &k, &v)) |
|
476 { |
|
477 /* not muc */ |
|
478 return; |
|
479 } |
|
480 |
|
481 gabble_debug (DEBUG_FLAG, "got room identity, name=%s, category=%s, type=%s", name, category, type); |
|
482 |
|
483 keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, |
|
484 (GDestroyNotify) destroy_value); |
|
485 |
|
486 INSERT_KEY (keys, "name", G_TYPE_STRING, string, name); |
|
487 |
|
488 if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v)) |
|
489 INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, TRUE); |
|
490 if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v)) |
|
491 INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, FALSE); |
|
492 if (g_hash_table_lookup_extended (item->features, "muc_passwordprotected", &k, &v)) |
|
493 INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, TRUE); |
|
494 if (g_hash_table_lookup_extended (item->features, "muc_unsecure", &k, &v)) |
|
495 INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE); |
|
496 if (g_hash_table_lookup_extended (item->features, "muc_unsecured", &k, &v)) |
|
497 INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE); |
|
498 if (g_hash_table_lookup_extended (item->features, "muc_hidden", &k, &v)) |
|
499 INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, TRUE); |
|
500 if (g_hash_table_lookup_extended (item->features, "muc_public", &k, &v)) |
|
501 INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, FALSE); |
|
502 if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v)) |
|
503 INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, TRUE); |
|
504 if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v)) |
|
505 INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, FALSE); |
|
506 if (g_hash_table_lookup_extended (item->features, "muc_moderated", &k, &v)) |
|
507 INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, TRUE); |
|
508 if (g_hash_table_lookup_extended (item->features, "muc_unmoderated", &k, &v)) |
|
509 INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, FALSE); |
|
510 if (g_hash_table_lookup_extended (item->features, "muc_nonanonymous", &k, &v)) |
|
511 INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE); |
|
512 if (g_hash_table_lookup_extended (item->features, "muc_anonymous", &k, &v)) |
|
513 INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, TRUE); |
|
514 if (g_hash_table_lookup_extended (item->features, "muc_semianonymous", &k, &v)) |
|
515 INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE); |
|
516 if (g_hash_table_lookup_extended (item->features, "muc_persistent", &k, &v)) |
|
517 INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, TRUE); |
|
518 if (g_hash_table_lookup_extended (item->features, "muc_temporary", &k, &v)) |
|
519 INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, FALSE); |
|
520 |
|
521 var = g_hash_table_lookup (item->features, "muc#roominfo_description"); |
|
522 if (var != NULL) |
|
523 INSERT_KEY (keys, "description", G_TYPE_STRING, string, var); |
|
524 |
|
525 var = g_hash_table_lookup (item->features, "muc#roominfo_occupants"); |
|
526 if (var != NULL) |
|
527 INSERT_KEY (keys, "members", G_TYPE_UINT, uint, |
|
528 (guint) g_ascii_strtoull (var, NULL, 10)); |
|
529 |
|
530 var = g_hash_table_lookup (item->features, "muc#roominfo_lang"); |
|
531 if (var != NULL) |
|
532 INSERT_KEY (keys, "language", G_TYPE_STRING, string, var); |
|
533 |
|
534 handle = gabble_handle_for_room (priv->conn->handles, jid); |
|
535 |
|
536 handle_set_add (priv->signalled_rooms, handle); |
|
537 |
|
538 g_value_init (&room, TP_TYPE_ROOM_STRUCT); |
|
539 g_value_take_boxed (&room, |
|
540 dbus_g_type_specialized_construct (TP_TYPE_ROOM_STRUCT)); |
|
541 |
|
542 dbus_g_type_struct_set (&room, |
|
543 0, handle, |
|
544 1, "org.freedesktop.Telepathy.Channel.Type.Text", |
|
545 2, keys, |
|
546 G_MAXUINT); |
|
547 |
|
548 gabble_debug (DEBUG_FLAG, "adding new room signal data to pending: %s", jid); |
|
549 g_ptr_array_add (priv->pending_room_signals, g_value_get_boxed (&room)); |
|
550 g_hash_table_destroy (keys); |
|
551 } |
|
552 |
|
553 static void |
|
554 rooms_end_cb (gpointer data, gpointer user_data) |
|
555 { |
|
556 GabbleRoomlistChannel *chan = user_data; |
|
557 GabbleRoomlistChannelPrivate *priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (chan); |
|
558 |
|
559 emit_room_signal (chan); |
|
560 |
|
561 priv->listing = FALSE; |
|
562 g_signal_emit (chan, signals[LISTING_ROOMS], 0, FALSE); |
|
563 |
|
564 g_source_remove (priv->timer_source_id); |
|
565 priv->timer_source_id = 0; |
|
566 } |
|
567 |
|
568 |
|
569 /************************* D-Bus Method definitions **************************/ |
|
570 |
|
571 /** |
|
572 * gabble_roomlist_channel_close |
|
573 * |
|
574 * Implements D-Bus method Close |
|
575 * on interface org.freedesktop.Telepathy.Channel |
|
576 * |
|
577 * @error: Used to return a pointer to a GError detailing any error |
|
578 * that occurred, D-Bus will throw the error only if this |
|
579 * function returns FALSE. |
|
580 * |
|
581 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
582 */ |
|
583 gboolean |
|
584 gabble_roomlist_channel_close (GabbleRoomlistChannel *self, |
|
585 GError **error) |
|
586 { |
|
587 g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); |
|
588 |
|
589 gabble_debug (DEBUG_FLAG, "called on %p", self); |
|
590 |
|
591 g_object_run_dispose (G_OBJECT (self)); |
|
592 |
|
593 return TRUE; |
|
594 } |
|
595 |
|
596 |
|
597 /** |
|
598 * gabble_roomlist_channel_get_channel_type |
|
599 * |
|
600 * Implements D-Bus method GetChannelType |
|
601 * on interface org.freedesktop.Telepathy.Channel |
|
602 * |
|
603 * @error: Used to return a pointer to a GError detailing any error |
|
604 * that occurred, D-Bus will throw the error only if this |
|
605 * function returns FALSE. |
|
606 * |
|
607 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
608 */ |
|
609 gboolean |
|
610 gabble_roomlist_channel_get_channel_type (GabbleRoomlistChannel *self, |
|
611 gchar **ret, |
|
612 GError **error) |
|
613 { |
|
614 *ret = g_strdup (TP_IFACE_CHANNEL_TYPE_ROOM_LIST); |
|
615 return TRUE; |
|
616 } |
|
617 |
|
618 |
|
619 /** |
|
620 * gabble_roomlist_channel_get_handle |
|
621 * |
|
622 * Implements D-Bus method GetHandle |
|
623 * on interface org.freedesktop.Telepathy.Channel |
|
624 * |
|
625 * @error: Used to return a pointer to a GError detailing any error |
|
626 * that occurred, D-Bus will throw the error only if this |
|
627 * function returns FALSE. |
|
628 * |
|
629 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
630 */ |
|
631 gboolean |
|
632 gabble_roomlist_channel_get_handle (GabbleRoomlistChannel *self, |
|
633 guint *ret, |
|
634 guint *ret1, |
|
635 GError **error) |
|
636 { |
|
637 g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); |
|
638 |
|
639 *ret = 0; |
|
640 *ret1 = 0; |
|
641 |
|
642 return TRUE; |
|
643 } |
|
644 |
|
645 |
|
646 /** |
|
647 * gabble_roomlist_channel_get_interfaces |
|
648 * |
|
649 * Implements D-Bus method GetInterfaces |
|
650 * on interface org.freedesktop.Telepathy.Channel |
|
651 * |
|
652 * @error: Used to return a pointer to a GError detailing any error |
|
653 * that occurred, D-Bus will throw the error only if this |
|
654 * function returns FALSE. |
|
655 * |
|
656 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
657 */ |
|
658 gboolean |
|
659 gabble_roomlist_channel_get_interfaces (GabbleRoomlistChannel *self, |
|
660 gchar ***ret, |
|
661 GError **error) |
|
662 { |
|
663 const char *interfaces[] = { NULL }; |
|
664 |
|
665 *ret = g_strdupv ((gchar **) interfaces); |
|
666 |
|
667 return TRUE; |
|
668 } |
|
669 |
|
670 |
|
671 /** |
|
672 * gabble_roomlist_channel_get_listing_rooms |
|
673 * |
|
674 * Implements D-Bus method GetListingRooms |
|
675 * on interface org.freedesktop.Telepathy.Channel.Type.RoomList |
|
676 * |
|
677 * @error: Used to return a pointer to a GError detailing any error |
|
678 * that occurred, D-Bus will throw the error only if this |
|
679 * function returns FALSE. |
|
680 * |
|
681 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
682 */ |
|
683 gboolean |
|
684 gabble_roomlist_channel_get_listing_rooms (GabbleRoomlistChannel *self, |
|
685 gboolean *ret, |
|
686 GError **error) |
|
687 { |
|
688 GabbleRoomlistChannelPrivate *priv; |
|
689 |
|
690 g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); |
|
691 |
|
692 priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self); |
|
693 *ret = priv->listing; |
|
694 return TRUE; |
|
695 } |
|
696 |
|
697 |
|
698 /** |
|
699 * gabble_roomlist_channel_list_rooms |
|
700 * |
|
701 * Implements D-Bus method ListRooms |
|
702 * on interface org.freedesktop.Telepathy.Channel.Type.RoomList |
|
703 * |
|
704 * @error: Used to return a pointer to a GError detailing any error |
|
705 * that occurred, D-Bus will throw the error only if this |
|
706 * function returns FALSE. |
|
707 * |
|
708 * Returns: TRUE if successful, FALSE if an error was thrown. |
|
709 */ |
|
710 gboolean |
|
711 gabble_roomlist_channel_list_rooms (GabbleRoomlistChannel *self, |
|
712 GError **error) |
|
713 { |
|
714 GabbleRoomlistChannelPrivate *priv; |
|
715 |
|
716 g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); |
|
717 |
|
718 priv = GABBLE_ROOMLIST_CHANNEL_GET_PRIVATE (self); |
|
719 |
|
720 priv->listing = TRUE; |
|
721 g_signal_emit (self, signals[LISTING_ROOMS], 0, TRUE); |
|
722 |
|
723 if (priv->disco_pipeline == NULL) |
|
724 priv->disco_pipeline = gabble_disco_pipeline_init (priv->conn->disco, |
|
725 room_info_cb, rooms_end_cb, self); |
|
726 |
|
727 gabble_disco_pipeline_run (priv->disco_pipeline, priv->conference_server); |
|
728 |
|
729 priv->timer_source_id = g_timeout_add (ROOM_SIGNAL_INTERVAL, |
|
730 emit_room_signal, self); |
|
731 |
|
732 return TRUE; |
|
733 } |
|
734 |
|