1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
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.
23 #include <dbus/dbus-glib.h>
24 #include <libtelepathy/tp-chan.h>
25 #include <libtelepathy/tp-chan-iface-group-gen.h>
26 #include <libtelepathy/tp-constants.h>
27 #include <libtelepathy/tp-conn.h>
29 #include "gossip-debug.h"
30 #include "gossip-telepathy-group.h"
31 #include "empathy-marshal.h"
33 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
34 GOSSIP_TYPE_TELEPATHY_GROUP, GossipTelepathyGroupPriv))
36 #define DEBUG_DOMAIN "TelepathyGroup"
38 struct _GossipTelepathyGroupPriv {
39 DBusGProxy *group_iface;
45 static void gossip_telepathy_group_class_init (GossipTelepathyGroupClass *klass);
46 static void gossip_telepathy_group_init (GossipTelepathyGroup *group);
47 static void telepathy_group_finalize (GObject *object);
48 static void telepathy_group_destroy_cb (DBusGProxy *proxy,
49 GossipTelepathyGroup *group);
50 static void telepathy_group_members_changed_cb (DBusGProxy *group_iface,
54 GArray *local_pending,
55 GArray *remote_pending,
58 GossipTelepathyGroup *group);
68 static guint signals[LAST_SIGNAL];
70 G_DEFINE_TYPE (GossipTelepathyGroup, gossip_telepathy_group, G_TYPE_OBJECT);
73 gossip_telepathy_group_class_init (GossipTelepathyGroupClass *klass)
75 GObjectClass *object_class = G_OBJECT_CLASS (klass);
77 object_class->finalize = telepathy_group_finalize;
79 signals[MEMBERS_ADDED] =
80 g_signal_new ("members-added",
81 G_TYPE_FROM_CLASS (klass),
85 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
87 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
89 signals[MEMBERS_REMOVED] =
90 g_signal_new ("members-removed",
91 G_TYPE_FROM_CLASS (klass),
95 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
97 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
99 signals[LOCAL_PENDING] =
100 g_signal_new ("local-pending",
101 G_TYPE_FROM_CLASS (klass),
105 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
107 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
109 signals[REMOTE_PENDING] =
110 g_signal_new ("remote-pending",
111 G_TYPE_FROM_CLASS (klass),
115 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
117 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
119 g_type_class_add_private (object_class, sizeof (GossipTelepathyGroupPriv));
123 gossip_telepathy_group_init (GossipTelepathyGroup *group)
128 telepathy_group_finalize (GObject *object)
130 GossipTelepathyGroupPriv *priv;
132 priv = GET_PRIV (object);
134 if (priv->group_iface) {
135 g_signal_handlers_disconnect_by_func (priv->group_iface,
136 telepathy_group_destroy_cb,
138 dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
139 G_CALLBACK (telepathy_group_members_changed_cb),
141 g_object_unref (priv->group_iface);
145 g_object_unref (priv->tp_conn);
149 g_object_unref (priv->tp_chan);
152 g_free (priv->group_name);
154 G_OBJECT_CLASS (gossip_telepathy_group_parent_class)->finalize (object);
157 GossipTelepathyGroup *
158 gossip_telepathy_group_new (TpChan *tp_chan,
161 GossipTelepathyGroup *group;
162 GossipTelepathyGroupPriv *priv;
163 DBusGProxy *group_iface;
165 g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
167 group_iface = tp_chan_get_interface (tp_chan,
168 TELEPATHY_CHAN_IFACE_GROUP_QUARK);
169 g_return_val_if_fail (group_iface != NULL, NULL);
171 group = g_object_new (GOSSIP_TYPE_TELEPATHY_GROUP, NULL);
172 priv = GET_PRIV (group);
174 priv->tp_conn = g_object_ref (tp_conn);
175 priv->tp_chan = g_object_ref (tp_chan);
176 priv->group_iface = g_object_ref (group_iface);
178 dbus_g_proxy_connect_signal (priv->group_iface, "MembersChanged",
179 G_CALLBACK (telepathy_group_members_changed_cb),
181 g_signal_connect (group_iface, "destroy",
182 G_CALLBACK (telepathy_group_destroy_cb),
190 gossip_telepathy_group_add_members (GossipTelepathyGroup *group,
192 const gchar *message)
194 GossipTelepathyGroupPriv *priv;
195 GError *error = NULL;
197 g_return_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group));
198 g_return_if_fail (handles != NULL);
200 priv = GET_PRIV (group);
202 if (!tp_chan_iface_group_add_members (priv->group_iface,
206 gossip_debug (DEBUG_DOMAIN,
207 "Failed to add members: %s",
208 error ? error->message : "No error given");
209 g_clear_error (&error);
214 gossip_telepathy_group_add_member (GossipTelepathyGroup *group,
216 const gchar *message)
220 handles = g_array_new (FALSE, FALSE, sizeof (guint));
221 g_array_append_val (handles, handle);
223 gossip_telepathy_group_add_members (group, handles, message);
225 g_array_free (handles, TRUE);
229 gossip_telepathy_group_remove_members (GossipTelepathyGroup *group,
231 const gchar *message)
233 GossipTelepathyGroupPriv *priv;
234 GError *error = NULL;
236 g_return_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group));
238 priv = GET_PRIV (group);
240 if (!tp_chan_iface_group_remove_members (priv->group_iface,
244 gossip_debug (DEBUG_DOMAIN,
245 "Failed to remove members: %s",
246 error ? error->message : "No error given");
247 g_clear_error (&error);
252 gossip_telepathy_group_remove_member (GossipTelepathyGroup *group,
254 const gchar *message)
258 g_return_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group));
260 handles = g_array_new (FALSE, FALSE, sizeof (guint));
261 g_array_append_val (handles, handle);
263 gossip_telepathy_group_remove_members (group, handles, message);
265 g_array_free (handles, TRUE);
269 gossip_telepathy_group_get_members (GossipTelepathyGroup *group)
271 GossipTelepathyGroupPriv *priv;
273 GError *error = NULL;
275 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
277 priv = GET_PRIV (group);
279 if (!tp_chan_iface_group_get_members (priv->group_iface,
282 gossip_debug (DEBUG_DOMAIN,
283 "Couldn't get members: %s",
284 error ? error->message : "No error given");
285 g_clear_error (&error);
293 gossip_telepathy_group_get_all_members (GossipTelepathyGroup *group,
295 GArray **local_pending,
296 GArray **remote_pending)
298 GossipTelepathyGroupPriv *priv;
299 GError *error = NULL;
301 g_return_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group));
303 priv = GET_PRIV (group);
305 if (!tp_chan_iface_group_get_all_members (priv->group_iface,
310 gossip_debug (DEBUG_DOMAIN,
311 "Couldn't get all members: %s",
312 error ? error->message : "No error given");
313 g_clear_error (&error);
318 gossip_telepathy_group_get_local_pending_members_with_info (GossipTelepathyGroup *group)
320 GossipTelepathyGroupPriv *priv;
321 GPtrArray *info = NULL;
322 GError *error = NULL;
324 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
326 priv = GET_PRIV (group);
328 if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
331 gossip_debug (DEBUG_DOMAIN,
332 "GetLocalPendingMembersWithInfo failed: %s",
333 error ? error->message : "No error given");
334 g_clear_error (&error);
341 telepathy_group_destroy_cb (DBusGProxy *proxy,
342 GossipTelepathyGroup *group)
344 GossipTelepathyGroupPriv *priv;
346 priv = GET_PRIV (group);
348 g_object_unref (priv->group_iface);
349 g_object_unref (priv->tp_conn);
350 g_object_unref (priv->tp_chan);
351 priv->group_iface = NULL;
352 priv->tp_chan = NULL;
353 priv->tp_conn = NULL;
357 telepathy_group_members_changed_cb (DBusGProxy *group_iface,
361 GArray *local_pending,
362 GArray *remote_pending,
365 GossipTelepathyGroup *group)
367 GossipTelepathyGroupPriv *priv;
369 priv = GET_PRIV (group);
372 if (added->len > 0) {
373 g_signal_emit (group, signals[MEMBERS_ADDED], 0,
374 added, actor, reason, message);
376 if (removed->len > 0) {
377 g_signal_emit (group, signals[MEMBERS_REMOVED], 0,
378 removed, actor, reason, message);
380 if (local_pending->len > 0) {
381 g_signal_emit (group, signals[LOCAL_PENDING], 0,
382 local_pending, actor, reason, message);
384 if (remote_pending->len > 0) {
385 g_signal_emit (group, signals[REMOTE_PENDING], 0,
386 remote_pending, actor, reason, message);
391 gossip_telepathy_group_get_name (GossipTelepathyGroup *group)
393 TelepathyHandleType handle_type;
394 guint channel_handle;
395 GArray *group_handles;
397 GError *error = NULL;
399 GossipTelepathyGroupPriv *priv;
401 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
403 priv = GET_PRIV (group);
405 /* Lazy initialisation */
406 if (priv->group_name) {
407 return priv->group_name;
410 if (!tp_chan_get_handle (DBUS_G_PROXY (priv->tp_chan),
414 gossip_debug (DEBUG_DOMAIN,
415 "Couldn't retreive channel handle for group: %s",
416 error ? error->message : "No error given");
417 g_clear_error (&error);
421 group_handles = g_array_new (FALSE, FALSE, sizeof (guint));
422 g_array_append_val (group_handles, channel_handle);
423 if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
428 gossip_debug (DEBUG_DOMAIN,
429 "Couldn't get group name: %s",
430 error ? error->message : "No error given");
431 g_clear_error (&error);
432 g_array_free (group_handles, TRUE);
436 priv->group_name = *group_names;
437 g_array_free (group_handles, TRUE);
438 g_free (group_names);
440 return priv->group_name;
444 gossip_telepathy_group_get_self_handle (GossipTelepathyGroup *group)
446 GossipTelepathyGroupPriv *priv;
448 GError *error = NULL;
450 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), 0 );
452 priv = GET_PRIV (group);
454 if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
455 gossip_debug (DEBUG_DOMAIN,
456 "Failed to get self handle: %s",
457 error ? error->message : "No error given");
458 g_clear_error (&error);
466 gossip_telepathy_group_get_object_path (GossipTelepathyGroup *group)
468 GossipTelepathyGroupPriv *priv;
470 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
472 priv = GET_PRIV (group);
474 return dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan));
478 gossip_telepathy_group_is_member (GossipTelepathyGroup *group,
483 gboolean found = FALSE;
485 members = gossip_telepathy_group_get_members (group);
486 for (i = 0; i < members->len; i++) {
487 if (g_array_index (members, guint, i) == handle) {
492 g_array_free (members, TRUE);