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-marshal.h"
33 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
34 EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupPriv))
36 #define DEBUG_DOMAIN "TpGroup"
38 struct _EmpathyTpGroupPriv {
39 DBusGProxy *group_iface;
45 static void empathy_tp_group_class_init (EmpathyTpGroupClass *klass);
46 static void empathy_tp_group_init (EmpathyTpGroup *group);
47 static void tp_group_finalize (GObject *object);
48 static void tp_group_destroy_cb (DBusGProxy *proxy,
49 EmpathyTpGroup *group);
50 static void tp_group_members_changed_cb (DBusGProxy *group_iface,
54 GArray *local_pending,
55 GArray *remote_pending,
58 EmpathyTpGroup *group);
68 static guint signals[LAST_SIGNAL];
70 G_DEFINE_TYPE (EmpathyTpGroup, empathy_tp_group, G_TYPE_OBJECT);
73 empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
75 GObjectClass *object_class = G_OBJECT_CLASS (klass);
77 object_class->finalize = tp_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 (EmpathyTpGroupPriv));
123 empathy_tp_group_init (EmpathyTpGroup *group)
128 tp_group_finalize (GObject *object)
130 EmpathyTpGroupPriv *priv;
132 priv = GET_PRIV (object);
134 if (priv->group_iface) {
135 g_signal_handlers_disconnect_by_func (priv->group_iface,
138 dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
139 G_CALLBACK (tp_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 (empathy_tp_group_parent_class)->finalize (object);
158 empathy_tp_group_new (TpChan *tp_chan,
161 EmpathyTpGroup *group;
162 EmpathyTpGroupPriv *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 (EMPATHY_TYPE_TP_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 (tp_group_members_changed_cb),
181 g_signal_connect (group_iface, "destroy",
182 G_CALLBACK (tp_group_destroy_cb),
189 empathy_tp_group_add_members (EmpathyTpGroup *group,
191 const gchar *message)
193 EmpathyTpGroupPriv *priv;
194 GError *error = NULL;
196 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
197 g_return_if_fail (handles != NULL);
199 priv = GET_PRIV (group);
201 if (!tp_chan_iface_group_add_members (priv->group_iface,
205 empathy_debug (DEBUG_DOMAIN,
206 "Failed to add members: %s",
207 error ? error->message : "No error given");
208 g_clear_error (&error);
213 empathy_tp_group_add_member (EmpathyTpGroup *group,
215 const gchar *message)
219 handles = g_array_new (FALSE, FALSE, sizeof (guint));
220 g_array_append_val (handles, handle);
222 empathy_tp_group_add_members (group, handles, message);
224 g_array_free (handles, TRUE);
228 empathy_tp_group_remove_members (EmpathyTpGroup *group,
230 const gchar *message)
232 EmpathyTpGroupPriv *priv;
233 GError *error = NULL;
235 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
237 priv = GET_PRIV (group);
239 if (!tp_chan_iface_group_remove_members (priv->group_iface,
243 empathy_debug (DEBUG_DOMAIN,
244 "Failed to remove members: %s",
245 error ? error->message : "No error given");
246 g_clear_error (&error);
251 empathy_tp_group_remove_member (EmpathyTpGroup *group,
253 const gchar *message)
257 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
259 handles = g_array_new (FALSE, FALSE, sizeof (guint));
260 g_array_append_val (handles, handle);
262 empathy_tp_group_remove_members (group, handles, message);
264 g_array_free (handles, TRUE);
268 empathy_tp_group_get_members (EmpathyTpGroup *group)
270 EmpathyTpGroupPriv *priv;
272 GError *error = NULL;
274 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
276 priv = GET_PRIV (group);
278 if (!tp_chan_iface_group_get_members (priv->group_iface,
281 empathy_debug (DEBUG_DOMAIN,
282 "Couldn't get members: %s",
283 error ? error->message : "No error given");
284 g_clear_error (&error);
292 empathy_tp_group_get_all_members (EmpathyTpGroup *group,
294 GArray **local_pending,
295 GArray **remote_pending)
297 EmpathyTpGroupPriv *priv;
298 GError *error = NULL;
300 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
302 priv = GET_PRIV (group);
304 if (!tp_chan_iface_group_get_all_members (priv->group_iface,
309 empathy_debug (DEBUG_DOMAIN,
310 "Couldn't get all members: %s",
311 error ? error->message : "No error given");
312 g_clear_error (&error);
317 empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group)
319 EmpathyTpGroupPriv *priv;
323 GError *error = NULL;
325 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
327 priv = GET_PRIV (group);
329 if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
332 empathy_debug (DEBUG_DOMAIN,
333 "GetLocalPendingMembersWithInfo failed: %s",
334 error ? error->message : "No error given");
335 g_clear_error (&error);
341 /* This happens with butterfly because
342 * GetLocalPendingMembersWithInfo is not
347 for (i = 0; array->len > i; i++) {
348 GValueArray *pending_struct;
349 EmpathyTpGroupInfo *info;
350 const gchar *message;
352 info = g_slice_new (EmpathyTpGroupInfo);
354 pending_struct = g_ptr_array_index (array, i);
355 info->member = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
356 info->actor = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
357 info->reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
358 message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
359 info->message = g_strdup (message);
360 g_value_array_free (pending_struct);
362 infos = g_list_prepend (infos, info);
364 g_ptr_array_free (array, TRUE);
370 empathy_tp_group_info_list_free (GList *infos)
374 for (l = infos; l; l = l->next) {
375 EmpathyTpGroupInfo *info;
379 g_free (info->message);
380 g_slice_free (EmpathyTpGroupInfo, info);
387 tp_group_destroy_cb (DBusGProxy *proxy,
388 EmpathyTpGroup *group)
390 EmpathyTpGroupPriv *priv;
392 priv = GET_PRIV (group);
394 g_object_unref (priv->group_iface);
395 g_object_unref (priv->tp_conn);
396 g_object_unref (priv->tp_chan);
397 priv->group_iface = NULL;
398 priv->tp_chan = NULL;
399 priv->tp_conn = 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 TelepathyHandleType handle_type;
440 guint channel_handle;
441 GArray *group_handles;
443 GError *error = NULL;
445 EmpathyTpGroupPriv *priv;
447 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
449 priv = GET_PRIV (group);
451 /* Lazy initialisation */
452 if (priv->group_name) {
453 return priv->group_name;
456 if (!tp_chan_get_handle (DBUS_G_PROXY (priv->tp_chan),
460 empathy_debug (DEBUG_DOMAIN,
461 "Couldn't retreive channel handle for group: %s",
462 error ? error->message : "No error given");
463 g_clear_error (&error);
467 group_handles = g_array_new (FALSE, FALSE, sizeof (guint));
468 g_array_append_val (group_handles, channel_handle);
469 if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
474 empathy_debug (DEBUG_DOMAIN,
475 "Couldn't get group name: %s",
476 error ? error->message : "No error given");
477 g_clear_error (&error);
478 g_array_free (group_handles, TRUE);
482 priv->group_name = *group_names;
483 g_array_free (group_handles, TRUE);
484 g_free (group_names);
486 return priv->group_name;
490 empathy_tp_group_get_self_handle (EmpathyTpGroup *group)
492 EmpathyTpGroupPriv *priv;
494 GError *error = NULL;
496 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), 0 );
498 priv = GET_PRIV (group);
500 if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
501 empathy_debug (DEBUG_DOMAIN,
502 "Failed to get self handle: %s",
503 error ? error->message : "No error given");
504 g_clear_error (&error);
512 empathy_tp_group_get_object_path (EmpathyTpGroup *group)
514 EmpathyTpGroupPriv *priv;
516 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
518 priv = GET_PRIV (group);
520 return dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan));
524 empathy_tp_group_is_member (EmpathyTpGroup *group,
529 gboolean found = FALSE;
531 members = empathy_tp_group_get_members (group);
532 for (i = 0; i < members->len; i++) {
533 if (g_array_index (members, guint, i) == handle) {
538 g_array_free (members, TRUE);