|
1 /* |
|
2 * search-factory.c - Source for GabbleSearchFactory |
|
3 * Copyright (C) 2006 Collabora Ltd. |
|
4 * |
|
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. |
|
9 * |
|
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. |
|
14 * |
|
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 |
|
18 */ |
|
19 |
|
20 |
|
21 #include <stdlib.h> |
|
22 #include <string.h> |
|
23 #include <time.h> |
|
24 |
|
25 #include <glib.h> |
|
26 #include <glib-object.h> |
|
27 |
|
28 #include <dbus/dbus-glib.h> |
|
29 #include <dbus/dbus-glib-lowlevel.h> |
|
30 |
|
31 #include "loudmouth/loudmouth.h" |
|
32 |
|
33 #include "debug.h" |
|
34 #include "gabble-connection.h" |
|
35 #include "telepathy-interfaces.h" |
|
36 #include "tp-channel-factory-iface.h" |
|
37 |
|
38 #include "search-mixin.h" |
|
39 #include "gabble-search-channel.h" |
|
40 |
|
41 #include "search-factory.h" |
|
42 |
|
43 static void gabble_search_factory_iface_init (gpointer g_iface, gpointer iface_data); |
|
44 |
|
45 #ifndef EMULATOR |
|
46 G_DEFINE_TYPE_WITH_CODE (GabbleSearchFactory, gabble_search_factory, G_TYPE_OBJECT, |
|
47 G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE, gabble_search_factory_iface_init)); |
|
48 #endif |
|
49 |
|
50 #ifdef EMULATOR |
|
51 #include "libgabble_wsd_solution.h" |
|
52 |
|
53 GET_STATIC_VAR_FROM_TLS(gabble_search_factory_parent_class,search_factory,gpointer) |
|
54 #define gabble_search_factory_parent_class (*GET_WSD_VAR_NAME(gabble_search_factory_parent_class,search_factory,s)()) |
|
55 |
|
56 GET_STATIC_VAR_FROM_TLS(g_define_type_id,search_factory,GType) |
|
57 #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,search_factory,s)()) |
|
58 |
|
59 static void gabble_search_factory_init (GabbleSearchFactory *self); |
|
60 static void gabble_search_factory_class_init (GabbleSearchFactoryClass *klass); |
|
61 static void gabble_search_factory_class_intern_init (gpointer klass) |
|
62 { |
|
63 gabble_search_factory_parent_class = g_type_class_peek_parent (klass); |
|
64 gabble_search_factory_class_init ((GabbleSearchFactoryClass*) klass); |
|
65 } |
|
66 EXPORT_C GType gabble_search_factory_get_type (void) |
|
67 { |
|
68 if ((g_define_type_id == 0)) { static const GTypeInfo g_define_type_info = { sizeof (GabbleSearchFactoryClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_search_factory_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleSearchFactory), 0, (GInstanceInitFunc) gabble_search_factory_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleSearchFactory"), &g_define_type_info, (GTypeFlags) 0); { { static const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc) gabble_search_factory_iface_init }; g_type_add_interface_static (g_define_type_id, tp_channel_factory_iface_get_type(), &g_implement_interface_info); } ; } } return g_define_type_id; } ; |
|
69 |
|
70 #endif |
|
71 |
|
72 #define DBUS_API_SUBJECT_TO_CHANGE |
|
73 #define DEBUG_FLAG GABBLE_DEBUG_IM |
|
74 |
|
75 #ifdef DEBUG_FLAG |
|
76 //#define DEBUG(format, ...) |
|
77 #define DEBUGGING 0 |
|
78 #define NODE_DEBUG(n, s) |
|
79 #endif /* DEBUG_FLAG */ |
|
80 |
|
81 /* properties */ |
|
82 enum |
|
83 { |
|
84 PROP_CONNECTION = 1, |
|
85 LAST_PROPERTY |
|
86 }; |
|
87 |
|
88 typedef struct _GabbleSearchFactoryPrivate GabbleSearchFactoryPrivate; |
|
89 struct _GabbleSearchFactoryPrivate |
|
90 { |
|
91 GabbleConnection *conn; |
|
92 GArray *channels; |
|
93 gboolean dispose_has_run; |
|
94 }; |
|
95 |
|
96 #define GABBLE_SEARCH_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_SEARCH_FACTORY, GabbleSearchFactoryPrivate)) |
|
97 |
|
98 static GObject *gabble_search_factory_constructor (GType type, guint n_props, GObjectConstructParam *props); |
|
99 |
|
100 static void |
|
101 gabble_search_factory_init (GabbleSearchFactory *fac) |
|
102 { |
|
103 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
104 |
|
105 priv->channels = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); |
|
106 priv->conn = NULL; |
|
107 priv->dispose_has_run = FALSE; |
|
108 } |
|
109 |
|
110 static GObject * |
|
111 gabble_search_factory_constructor (GType type, guint n_props, |
|
112 GObjectConstructParam *props) |
|
113 { |
|
114 GObject *obj; |
|
115 /* GabbleSearchFactoryPrivate *priv; */ |
|
116 |
|
117 obj = G_OBJECT_CLASS (gabble_search_factory_parent_class)-> |
|
118 constructor (type, n_props, props); |
|
119 /* priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (obj); */ |
|
120 |
|
121 return obj; |
|
122 } |
|
123 |
|
124 |
|
125 static void |
|
126 gabble_search_factory_dispose (GObject *object) |
|
127 { |
|
128 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (object); |
|
129 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
130 |
|
131 if (priv->dispose_has_run) |
|
132 return; |
|
133 |
|
134 gabble_debug (DEBUG_FLAG, "dispose called"); |
|
135 priv->dispose_has_run = TRUE; |
|
136 |
|
137 tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object)); |
|
138 g_assert (priv->channels == NULL); |
|
139 |
|
140 if (G_OBJECT_CLASS (gabble_search_factory_parent_class)->dispose) |
|
141 G_OBJECT_CLASS (gabble_search_factory_parent_class)->dispose (object); |
|
142 } |
|
143 |
|
144 static void |
|
145 gabble_search_factory_get_property (GObject *object, |
|
146 guint property_id, |
|
147 GValue *value, |
|
148 GParamSpec *pspec) |
|
149 { |
|
150 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (object); |
|
151 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
152 |
|
153 switch (property_id) { |
|
154 case PROP_CONNECTION: |
|
155 g_value_set_object (value, priv->conn); |
|
156 break; |
|
157 default: |
|
158 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
|
159 break; |
|
160 } |
|
161 } |
|
162 |
|
163 static void |
|
164 gabble_search_factory_set_property (GObject *object, |
|
165 guint property_id, |
|
166 const GValue *value, |
|
167 GParamSpec *pspec) |
|
168 { |
|
169 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (object); |
|
170 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
171 |
|
172 switch (property_id) { |
|
173 case PROP_CONNECTION: |
|
174 priv->conn = g_value_get_object (value); |
|
175 break; |
|
176 default: |
|
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
|
178 break; |
|
179 } |
|
180 } |
|
181 |
|
182 static void |
|
183 gabble_search_factory_class_init (GabbleSearchFactoryClass *gabble_search_factory_class) |
|
184 { |
|
185 GObjectClass *object_class = G_OBJECT_CLASS (gabble_search_factory_class); |
|
186 GParamSpec *param_spec; |
|
187 |
|
188 g_type_class_add_private (gabble_search_factory_class, sizeof (GabbleSearchFactoryPrivate)); |
|
189 |
|
190 object_class->constructor = gabble_search_factory_constructor; |
|
191 object_class->dispose = gabble_search_factory_dispose; |
|
192 |
|
193 object_class->get_property = gabble_search_factory_get_property; |
|
194 object_class->set_property = gabble_search_factory_set_property; |
|
195 |
|
196 |
|
197 param_spec = g_param_spec_object ("connection", "GabbleConnection object", |
|
198 "Gabble connection object that owns this " |
|
199 "Search channel factory object.", |
|
200 GABBLE_TYPE_CONNECTION, |
|
201 G_PARAM_CONSTRUCT_ONLY | |
|
202 G_PARAM_READWRITE | |
|
203 G_PARAM_STATIC_NICK | |
|
204 G_PARAM_STATIC_BLURB); |
|
205 g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); |
|
206 |
|
207 } |
|
208 |
|
209 static GabbleSearchChannel *new_search_channel (GabbleSearchFactory *fac, GabbleHandle handle); |
|
210 |
|
211 static void search_channel_closed_cb (GabbleSearchChannel *chan, gpointer user_data); |
|
212 |
|
213 |
|
214 |
|
215 /** |
|
216 * search_channel_closed_cb: |
|
217 * |
|
218 * Signal callback for when search channel is closed. Removes the references |
|
219 * that #GabbleConnection holds to them. |
|
220 */ |
|
221 static void |
|
222 search_channel_closed_cb (GabbleSearchChannel *chan, gpointer user_data) |
|
223 { |
|
224 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (user_data); |
|
225 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
226 g_message("in search_channel_closed_cb"); |
|
227 if (priv->channels) |
|
228 { |
|
229 g_array_remove_index( priv->channels, chan->channel_index ); |
|
230 } |
|
231 |
|
232 lm_connection_unregister_message_handler (priv->conn->lmconn, chan->iq_cb, |
|
233 LM_MESSAGE_TYPE_IQ); |
|
234 lm_message_handler_unref (chan->iq_cb); |
|
235 chan->iq_cb = NULL; |
|
236 g_object_unref (chan); |
|
237 chan = NULL; |
|
238 } |
|
239 |
|
240 /** |
|
241 * new_search_channel |
|
242 */ |
|
243 static GabbleSearchChannel * |
|
244 new_search_channel (GabbleSearchFactory *fac, GabbleHandle handle) |
|
245 { |
|
246 GabbleSearchFactoryPrivate *priv; |
|
247 GabbleSearchChannel *chan; |
|
248 char *object_path; |
|
249 |
|
250 g_assert (GABBLE_IS_SEARCH_FACTORY (fac)); |
|
251 |
|
252 priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
253 |
|
254 g_message("in new_search_channel:handle %u\n",handle); |
|
255 |
|
256 object_path = g_strdup_printf ("%s/SearchChannel%u", priv->conn->object_path, handle); |
|
257 |
|
258 gabble_debug (DEBUG_FLAG, "object path %s", object_path); |
|
259 |
|
260 |
|
261 |
|
262 // handle type should be none and handle value should be zero |
|
263 // so handle passed in g_object_new |
|
264 chan = g_object_new (GABBLE_TYPE_SEARCH_CHANNEL, |
|
265 "connection", priv->conn, |
|
266 "object-path", object_path, |
|
267 "handle", handle, |
|
268 NULL); |
|
269 |
|
270 g_message("in new_search_channel: chan is %u\n", chan); |
|
271 |
|
272 g_array_append_val(priv->channels, chan); |
|
273 |
|
274 g_signal_connect (chan, "closed", (GCallback) search_channel_closed_cb,fac); |
|
275 |
|
276 |
|
277 g_signal_emit_by_name (fac, "new-channel", chan); |
|
278 |
|
279 g_free (object_path); |
|
280 chan->channel_index = priv->channels->len - 1; |
|
281 |
|
282 //added for search as chan need to be passed as userdata in search_channel_iq_cb |
|
283 chan->iq_cb = lm_message_handler_new (search_channel_iq_cb, chan , NULL); |
|
284 lm_connection_register_message_handler (priv->conn->lmconn, chan->iq_cb, |
|
285 LM_MESSAGE_TYPE_IQ, |
|
286 LM_HANDLER_PRIORITY_NORMAL); |
|
287 |
|
288 return chan; |
|
289 } |
|
290 |
|
291 static void |
|
292 gabble_search_factory_iface_close_all (TpChannelFactoryIface *iface) |
|
293 { |
|
294 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (iface); |
|
295 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
296 |
|
297 gabble_debug (DEBUG_FLAG, "closing channels"); |
|
298 |
|
299 if (priv->channels) |
|
300 { |
|
301 g_array_free ( priv->channels, TRUE); |
|
302 priv->channels = NULL; |
|
303 } |
|
304 } |
|
305 |
|
306 static void |
|
307 gabble_search_factory_iface_connecting (TpChannelFactoryIface *iface) |
|
308 { |
|
309 /* nothing to do */ |
|
310 } |
|
311 |
|
312 |
|
313 |
|
314 static void |
|
315 gabble_search_factory_iface_connected (TpChannelFactoryIface *iface) |
|
316 { |
|
317 /* nothing to do */ |
|
318 } |
|
319 |
|
320 static void |
|
321 gabble_search_factory_iface_disconnected (TpChannelFactoryIface *iface) |
|
322 { |
|
323 // free any object here |
|
324 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (iface); |
|
325 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
326 |
|
327 if (priv->channels) |
|
328 { |
|
329 g_array_free ( priv->channels, TRUE); |
|
330 priv->channels = NULL; |
|
331 } |
|
332 } |
|
333 |
|
334 struct _ForeachData |
|
335 { |
|
336 TpChannelFunc foreach; |
|
337 gpointer user_data; |
|
338 }; |
|
339 |
|
340 static void |
|
341 _foreach_slave ( gpointer value, gpointer user_data ) |
|
342 { |
|
343 struct _ForeachData *data = (struct _ForeachData *) user_data; |
|
344 TpChannelIface *chan = TP_CHANNEL_IFACE (value); |
|
345 |
|
346 data->foreach (chan, data->user_data); |
|
347 } |
|
348 |
|
349 |
|
350 static void |
|
351 gabble_search_factory_iface_foreach (TpChannelFactoryIface *iface, TpChannelFunc foreach, gpointer user_data) |
|
352 { |
|
353 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (iface); |
|
354 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
355 struct _ForeachData data; |
|
356 guint i = 0; |
|
357 GabbleSearchChannel *chan = NULL; |
|
358 |
|
359 data.user_data = user_data; |
|
360 data.foreach = foreach; |
|
361 |
|
362 for( i = 0; i< priv->channels->len ; i++ ) |
|
363 { |
|
364 chan = GABBLE_SEARCH_CHANNEL ( g_array_index(priv->channels,guint,i) ); |
|
365 _foreach_slave(chan, &data); |
|
366 } |
|
367 |
|
368 } |
|
369 |
|
370 static TpChannelFactoryRequestStatus |
|
371 gabble_search_factory_iface_request (TpChannelFactoryIface *iface, |
|
372 const gchar *chan_type, |
|
373 TpHandleType handle_type, |
|
374 guint handle, |
|
375 TpChannelIface **ret, |
|
376 GError **error) |
|
377 { |
|
378 GabbleSearchFactory *fac = GABBLE_SEARCH_FACTORY (iface); |
|
379 GabbleSearchFactoryPrivate *priv = GABBLE_SEARCH_FACTORY_GET_PRIVATE (fac); |
|
380 GabbleSearchChannel *chan; |
|
381 |
|
382 if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH)) |
|
383 return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED; |
|
384 |
|
385 // should always pass handle type as none and handle as zero |
|
386 |
|
387 if ((handle_type != TP_HANDLE_TYPE_NONE) || handle ) |
|
388 return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE; |
|
389 |
|
390 |
|
391 g_message("in gabble_search_factory_iface_request:handle %u\n",handle); |
|
392 |
|
393 chan = new_search_channel (fac, handle); |
|
394 g_assert (chan); |
|
395 *ret = TP_CHANNEL_IFACE (chan); |
|
396 return TP_CHANNEL_FACTORY_REQUEST_STATUS_DONE; |
|
397 } |
|
398 |
|
399 static void |
|
400 gabble_search_factory_iface_init (gpointer g_iface, |
|
401 gpointer iface_data) |
|
402 { |
|
403 TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface; |
|
404 |
|
405 klass->close_all = gabble_search_factory_iface_close_all; |
|
406 klass->connecting = gabble_search_factory_iface_connecting; |
|
407 klass->connected = gabble_search_factory_iface_connected; |
|
408 klass->disconnected = gabble_search_factory_iface_disconnected; |
|
409 klass->foreach = gabble_search_factory_iface_foreach; |
|
410 klass->request = gabble_search_factory_iface_request; |
|
411 } |
|
412 |