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;
324 GError *error = NULL;
326 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
328 priv = GET_PRIV (group);
330 if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
333 gossip_debug (DEBUG_DOMAIN,
334 "GetLocalPendingMembersWithInfo failed: %s",
335 error ? error->message : "No error given");
336 g_clear_error (&error);
342 /* This happens with butterfly because
343 * GetLocalPendingMembersWithInfo is not
348 for (i = 0; array->len > i; i++) {
349 GValueArray *pending_struct;
350 GossipTpGroupInfo *info;
351 const gchar *message;
353 info = g_slice_new (GossipTpGroupInfo);
355 pending_struct = g_ptr_array_index (array, i);
356 info->member = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
357 info->actor = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
358 info->reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
359 message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
360 info->message = g_strdup (message);
361 g_value_array_free (pending_struct);
363 infos = g_list_prepend (infos, info);
365 g_ptr_array_free (array, TRUE);
371 gossip_telepathy_group_info_list_free (GList *infos)
375 for (l = infos; l; l = l->next) {
376 GossipTpGroupInfo *info;
380 g_free (info->message);
381 g_slice_free (GossipTpGroupInfo, info);
388 telepathy_group_destroy_cb (DBusGProxy *proxy,
389 GossipTelepathyGroup *group)
391 GossipTelepathyGroupPriv *priv;
393 priv = GET_PRIV (group);
395 g_object_unref (priv->group_iface);
396 g_object_unref (priv->tp_conn);
397 g_object_unref (priv->tp_chan);
398 priv->group_iface = NULL;
399 priv->tp_chan = NULL;
400 priv->tp_conn = NULL;
404 telepathy_group_members_changed_cb (DBusGProxy *group_iface,
408 GArray *local_pending,
409 GArray *remote_pending,
412 GossipTelepathyGroup *group)
414 GossipTelepathyGroupPriv *priv;
416 priv = GET_PRIV (group);
419 if (added->len > 0) {
420 g_signal_emit (group, signals[MEMBERS_ADDED], 0,
421 added, actor, reason, message);
423 if (removed->len > 0) {
424 g_signal_emit (group, signals[MEMBERS_REMOVED], 0,
425 removed, actor, reason, message);
427 if (local_pending->len > 0) {
428 g_signal_emit (group, signals[LOCAL_PENDING], 0,
429 local_pending, actor, reason, message);
431 if (remote_pending->len > 0) {
432 g_signal_emit (group, signals[REMOTE_PENDING], 0,
433 remote_pending, actor, reason, message);
438 gossip_telepathy_group_get_name (GossipTelepathyGroup *group)
440 TelepathyHandleType handle_type;
441 guint channel_handle;
442 GArray *group_handles;
444 GError *error = NULL;
446 GossipTelepathyGroupPriv *priv;
448 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
450 priv = GET_PRIV (group);
452 /* Lazy initialisation */
453 if (priv->group_name) {
454 return priv->group_name;
457 if (!tp_chan_get_handle (DBUS_G_PROXY (priv->tp_chan),
461 gossip_debug (DEBUG_DOMAIN,
462 "Couldn't retreive channel handle for group: %s",
463 error ? error->message : "No error given");
464 g_clear_error (&error);
468 group_handles = g_array_new (FALSE, FALSE, sizeof (guint));
469 g_array_append_val (group_handles, channel_handle);
470 if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
475 gossip_debug (DEBUG_DOMAIN,
476 "Couldn't get group name: %s",
477 error ? error->message : "No error given");
478 g_clear_error (&error);
479 g_array_free (group_handles, TRUE);
483 priv->group_name = *group_names;
484 g_array_free (group_handles, TRUE);
485 g_free (group_names);
487 return priv->group_name;
491 gossip_telepathy_group_get_self_handle (GossipTelepathyGroup *group)
493 GossipTelepathyGroupPriv *priv;
495 GError *error = NULL;
497 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), 0 );
499 priv = GET_PRIV (group);
501 if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
502 gossip_debug (DEBUG_DOMAIN,
503 "Failed to get self handle: %s",
504 error ? error->message : "No error given");
505 g_clear_error (&error);
513 gossip_telepathy_group_get_object_path (GossipTelepathyGroup *group)
515 GossipTelepathyGroupPriv *priv;
517 g_return_val_if_fail (GOSSIP_IS_TELEPATHY_GROUP (group), NULL);
519 priv = GET_PRIV (group);
521 return dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan));
525 gossip_telepathy_group_is_member (GossipTelepathyGroup *group,
530 gboolean found = FALSE;
532 members = gossip_telepathy_group_get_members (group);
533 for (i = 0; i < members->len; i++) {
534 if (g_array_index (members, guint, i) == handle) {
539 g_array_free (members, TRUE);