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 "empathy-debug.h"
30 #include "empathy-tp-group.h"
31 #include "empathy-utils.h"
32 #include "empathy-marshal.h"
34 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
35 EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupPriv))
37 #define DEBUG_DOMAIN "TpGroup"
39 struct _EmpathyTpGroupPriv {
41 DBusGProxy *group_iface;
46 static void empathy_tp_group_class_init (EmpathyTpGroupClass *klass);
47 static void empathy_tp_group_init (EmpathyTpGroup *group);
48 static void tp_group_finalize (GObject *object);
49 static void tp_group_destroy_cb (DBusGProxy *proxy,
50 EmpathyTpGroup *group);
51 static void tp_group_members_changed_cb (DBusGProxy *group_iface,
55 GArray *local_pending,
56 GArray *remote_pending,
59 EmpathyTpGroup *group);
69 static guint signals[LAST_SIGNAL];
71 G_DEFINE_TYPE (EmpathyTpGroup, empathy_tp_group, G_TYPE_OBJECT);
74 empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
76 GObjectClass *object_class = G_OBJECT_CLASS (klass);
78 object_class->finalize = tp_group_finalize;
80 signals[MEMBERS_ADDED] =
81 g_signal_new ("members-added",
82 G_TYPE_FROM_CLASS (klass),
86 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
88 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
90 signals[MEMBERS_REMOVED] =
91 g_signal_new ("members-removed",
92 G_TYPE_FROM_CLASS (klass),
96 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
98 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
100 signals[LOCAL_PENDING] =
101 g_signal_new ("local-pending",
102 G_TYPE_FROM_CLASS (klass),
106 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
108 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
110 signals[REMOTE_PENDING] =
111 g_signal_new ("remote-pending",
112 G_TYPE_FROM_CLASS (klass),
116 empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
118 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
120 g_type_class_add_private (object_class, sizeof (EmpathyTpGroupPriv));
124 empathy_tp_group_init (EmpathyTpGroup *group)
129 tp_group_finalize (GObject *object)
131 EmpathyTpGroupPriv *priv;
133 priv = GET_PRIV (object);
135 if (priv->group_iface) {
136 g_signal_handlers_disconnect_by_func (priv->group_iface,
139 dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
140 G_CALLBACK (tp_group_members_changed_cb),
142 g_object_unref (priv->group_iface);
146 g_object_unref (priv->account);
150 g_object_unref (priv->tp_chan);
153 g_free (priv->group_name);
155 G_OBJECT_CLASS (empathy_tp_group_parent_class)->finalize (object);
159 empathy_tp_group_new (McAccount *account,
162 EmpathyTpGroup *group;
163 EmpathyTpGroupPriv *priv;
164 DBusGProxy *group_iface;
166 g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
167 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
169 group_iface = tp_chan_get_interface (tp_chan,
170 TELEPATHY_CHAN_IFACE_GROUP_QUARK);
171 g_return_val_if_fail (group_iface != NULL, NULL);
173 group = g_object_new (EMPATHY_TYPE_TP_GROUP, NULL);
174 priv = GET_PRIV (group);
176 priv->account = g_object_ref (account);
177 priv->tp_chan = g_object_ref (tp_chan);
178 priv->group_iface = g_object_ref (group_iface);
180 dbus_g_proxy_connect_signal (priv->group_iface, "MembersChanged",
181 G_CALLBACK (tp_group_members_changed_cb),
183 g_signal_connect (group_iface, "destroy",
184 G_CALLBACK (tp_group_destroy_cb),
191 empathy_tp_group_add_members (EmpathyTpGroup *group,
193 const gchar *message)
195 EmpathyTpGroupPriv *priv;
196 GError *error = NULL;
198 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
199 g_return_if_fail (handles != NULL);
201 priv = GET_PRIV (group);
203 if (!tp_chan_iface_group_add_members (priv->group_iface,
207 empathy_debug (DEBUG_DOMAIN,
208 "Failed to add members: %s",
209 error ? error->message : "No error given");
210 g_clear_error (&error);
215 empathy_tp_group_add_member (EmpathyTpGroup *group,
217 const gchar *message)
221 handles = g_array_new (FALSE, FALSE, sizeof (guint));
222 g_array_append_val (handles, handle);
224 empathy_tp_group_add_members (group, handles, message);
226 g_array_free (handles, TRUE);
230 empathy_tp_group_remove_members (EmpathyTpGroup *group,
232 const gchar *message)
234 EmpathyTpGroupPriv *priv;
235 GError *error = NULL;
237 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
239 priv = GET_PRIV (group);
241 if (!tp_chan_iface_group_remove_members (priv->group_iface,
245 empathy_debug (DEBUG_DOMAIN,
246 "Failed to remove members: %s",
247 error ? error->message : "No error given");
248 g_clear_error (&error);
253 empathy_tp_group_remove_member (EmpathyTpGroup *group,
255 const gchar *message)
259 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
261 handles = g_array_new (FALSE, FALSE, sizeof (guint));
262 g_array_append_val (handles, handle);
264 empathy_tp_group_remove_members (group, handles, message);
266 g_array_free (handles, TRUE);
270 empathy_tp_group_get_members (EmpathyTpGroup *group)
272 EmpathyTpGroupPriv *priv;
274 GError *error = NULL;
276 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
278 priv = GET_PRIV (group);
280 if (!tp_chan_iface_group_get_members (priv->group_iface,
283 empathy_debug (DEBUG_DOMAIN,
284 "Couldn't get members: %s",
285 error ? error->message : "No error given");
286 g_clear_error (&error);
294 empathy_tp_group_get_all_members (EmpathyTpGroup *group,
296 GArray **local_pending,
297 GArray **remote_pending)
299 EmpathyTpGroupPriv *priv;
300 GError *error = NULL;
302 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
304 priv = GET_PRIV (group);
306 if (!tp_chan_iface_group_get_all_members (priv->group_iface,
311 empathy_debug (DEBUG_DOMAIN,
312 "Couldn't get all members: %s",
313 error ? error->message : "No error given");
314 g_clear_error (&error);
319 empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group)
321 EmpathyTpGroupPriv *priv;
325 GError *error = NULL;
327 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
329 priv = GET_PRIV (group);
331 if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
334 empathy_debug (DEBUG_DOMAIN,
335 "GetLocalPendingMembersWithInfo failed: %s",
336 error ? error->message : "No error given");
337 g_clear_error (&error);
343 /* This happens with butterfly because
344 * GetLocalPendingMembersWithInfo is not
349 for (i = 0; array->len > i; i++) {
350 GValueArray *pending_struct;
351 EmpathyTpGroupInfo *info;
352 const gchar *message;
354 info = g_slice_new (EmpathyTpGroupInfo);
356 pending_struct = g_ptr_array_index (array, i);
357 info->member = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
358 info->actor = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
359 info->reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
360 message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
361 info->message = g_strdup (message);
362 g_value_array_free (pending_struct);
364 infos = g_list_prepend (infos, info);
366 g_ptr_array_free (array, TRUE);
372 empathy_tp_group_info_list_free (GList *infos)
376 for (l = infos; l; l = l->next) {
377 EmpathyTpGroupInfo *info;
381 g_free (info->message);
382 g_slice_free (EmpathyTpGroupInfo, info);
389 tp_group_destroy_cb (DBusGProxy *proxy,
390 EmpathyTpGroup *group)
392 EmpathyTpGroupPriv *priv;
394 priv = GET_PRIV (group);
396 g_object_unref (priv->group_iface);
397 g_object_unref (priv->tp_chan);
398 priv->group_iface = NULL;
399 priv->tp_chan = NULL;
403 tp_group_members_changed_cb (DBusGProxy *group_iface,
407 GArray *local_pending,
408 GArray *remote_pending,
411 EmpathyTpGroup *group)
413 EmpathyTpGroupPriv *priv;
415 priv = GET_PRIV (group);
418 if (added->len > 0) {
419 g_signal_emit (group, signals[MEMBERS_ADDED], 0,
420 added, actor, reason, message);
422 if (removed->len > 0) {
423 g_signal_emit (group, signals[MEMBERS_REMOVED], 0,
424 removed, actor, reason, message);
426 if (local_pending->len > 0) {
427 g_signal_emit (group, signals[LOCAL_PENDING], 0,
428 local_pending, actor, reason, message);
430 if (remote_pending->len > 0) {
431 g_signal_emit (group, signals[REMOTE_PENDING], 0,
432 remote_pending, actor, reason, message);
437 empathy_tp_group_get_name (EmpathyTpGroup *group)
439 EmpathyTpGroupPriv *priv;
441 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
443 priv = GET_PRIV (group);
445 /* Lazy initialisation */
446 if (priv->group_name) {
447 return priv->group_name;
450 priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
452 return priv->group_name;
456 empathy_tp_group_get_self_handle (EmpathyTpGroup *group)
458 EmpathyTpGroupPriv *priv;
460 GError *error = NULL;
462 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), 0 );
464 priv = GET_PRIV (group);
466 if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
467 empathy_debug (DEBUG_DOMAIN,
468 "Failed to get self handle: %s",
469 error ? error->message : "No error given");
470 g_clear_error (&error);
478 empathy_tp_group_get_object_path (EmpathyTpGroup *group)
480 EmpathyTpGroupPriv *priv;
482 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
484 priv = GET_PRIV (group);
486 return dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan));
490 empathy_tp_group_is_member (EmpathyTpGroup *group,
495 gboolean found = FALSE;
497 members = empathy_tp_group_get_members (group);
498 for (i = 0; i < members->len; i++) {
499 if (g_array_index (members, guint, i) == handle) {
504 g_array_free (members, TRUE);