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);
166 g_return_val_if_fail (TELEPATHY_IS_CONN (tp_conn), NULL);
168 group_iface = tp_chan_get_interface (tp_chan,
169 TELEPATHY_CHAN_IFACE_GROUP_QUARK);
170 g_return_val_if_fail (group_iface != NULL, NULL);
172 group = g_object_new (EMPATHY_TYPE_TP_GROUP, NULL);
173 priv = GET_PRIV (group);
175 priv->tp_conn = g_object_ref (tp_conn);
176 priv->tp_chan = g_object_ref (tp_chan);
177 priv->group_iface = g_object_ref (group_iface);
179 dbus_g_proxy_connect_signal (priv->group_iface, "MembersChanged",
180 G_CALLBACK (tp_group_members_changed_cb),
182 g_signal_connect (group_iface, "destroy",
183 G_CALLBACK (tp_group_destroy_cb),
190 empathy_tp_group_add_members (EmpathyTpGroup *group,
192 const gchar *message)
194 EmpathyTpGroupPriv *priv;
195 GError *error = NULL;
197 g_return_if_fail (EMPATHY_IS_TP_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 empathy_debug (DEBUG_DOMAIN,
207 "Failed to add members: %s",
208 error ? error->message : "No error given");
209 g_clear_error (&error);
214 empathy_tp_group_add_member (EmpathyTpGroup *group,
216 const gchar *message)
220 handles = g_array_new (FALSE, FALSE, sizeof (guint));
221 g_array_append_val (handles, handle);
223 empathy_tp_group_add_members (group, handles, message);
225 g_array_free (handles, TRUE);
229 empathy_tp_group_remove_members (EmpathyTpGroup *group,
231 const gchar *message)
233 EmpathyTpGroupPriv *priv;
234 GError *error = NULL;
236 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
238 priv = GET_PRIV (group);
240 if (!tp_chan_iface_group_remove_members (priv->group_iface,
244 empathy_debug (DEBUG_DOMAIN,
245 "Failed to remove members: %s",
246 error ? error->message : "No error given");
247 g_clear_error (&error);
252 empathy_tp_group_remove_member (EmpathyTpGroup *group,
254 const gchar *message)
258 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
260 handles = g_array_new (FALSE, FALSE, sizeof (guint));
261 g_array_append_val (handles, handle);
263 empathy_tp_group_remove_members (group, handles, message);
265 g_array_free (handles, TRUE);
269 empathy_tp_group_get_members (EmpathyTpGroup *group)
271 EmpathyTpGroupPriv *priv;
273 GError *error = NULL;
275 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
277 priv = GET_PRIV (group);
279 if (!tp_chan_iface_group_get_members (priv->group_iface,
282 empathy_debug (DEBUG_DOMAIN,
283 "Couldn't get members: %s",
284 error ? error->message : "No error given");
285 g_clear_error (&error);
293 empathy_tp_group_get_all_members (EmpathyTpGroup *group,
295 GArray **local_pending,
296 GArray **remote_pending)
298 EmpathyTpGroupPriv *priv;
299 GError *error = NULL;
301 g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
303 priv = GET_PRIV (group);
305 if (!tp_chan_iface_group_get_all_members (priv->group_iface,
310 empathy_debug (DEBUG_DOMAIN,
311 "Couldn't get all members: %s",
312 error ? error->message : "No error given");
313 g_clear_error (&error);
318 empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group)
320 EmpathyTpGroupPriv *priv;
324 GError *error = NULL;
326 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
328 priv = GET_PRIV (group);
330 if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
333 empathy_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 EmpathyTpGroupInfo *info;
351 const gchar *message;
353 info = g_slice_new (EmpathyTpGroupInfo);
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 empathy_tp_group_info_list_free (GList *infos)
375 for (l = infos; l; l = l->next) {
376 EmpathyTpGroupInfo *info;
380 g_free (info->message);
381 g_slice_free (EmpathyTpGroupInfo, info);
388 tp_group_destroy_cb (DBusGProxy *proxy,
389 EmpathyTpGroup *group)
391 EmpathyTpGroupPriv *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 tp_group_members_changed_cb (DBusGProxy *group_iface,
408 GArray *local_pending,
409 GArray *remote_pending,
412 EmpathyTpGroup *group)
414 EmpathyTpGroupPriv *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 empathy_tp_group_get_name (EmpathyTpGroup *group)
440 TelepathyHandleType handle_type;
441 guint channel_handle;
442 GArray *group_handles;
444 GError *error = NULL;
446 EmpathyTpGroupPriv *priv;
448 g_return_val_if_fail (EMPATHY_IS_TP_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 empathy_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 empathy_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 empathy_tp_group_get_self_handle (EmpathyTpGroup *group)
493 EmpathyTpGroupPriv *priv;
495 GError *error = NULL;
497 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), 0 );
499 priv = GET_PRIV (group);
501 if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
502 empathy_debug (DEBUG_DOMAIN,
503 "Failed to get self handle: %s",
504 error ? error->message : "No error given");
505 g_clear_error (&error);
513 empathy_tp_group_get_object_path (EmpathyTpGroup *group)
515 EmpathyTpGroupPriv *priv;
517 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
519 priv = GET_PRIV (group);
521 return dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan));
525 empathy_tp_group_is_member (EmpathyTpGroup *group,
530 gboolean found = FALSE;
532 members = empathy_tp_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);