1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
4 * Copyright (C) 2007-2008 Collabora Ltd.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
25 #include <libmissioncontrol/mc-account.h>
27 #include <telepathy-glib/channel.h>
28 #include <telepathy-glib/util.h>
29 #include <telepathy-glib/interfaces.h>
31 #include "empathy-tp-group.h"
32 #include "empathy-contact-factory.h"
33 #include "empathy-utils.h"
34 #include "empathy-marshal.h"
36 #define DEBUG_FLAG EMPATHY_DEBUG_TP
37 #include "empathy-debug.h"
39 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpGroup)
44 EmpathyContactFactory
*factory
;
49 GList
*local_pendings
;
50 GList
*remote_pendings
;
68 static guint signals
[LAST_SIGNAL
];
70 G_DEFINE_TYPE (EmpathyTpGroup
, empathy_tp_group
, G_TYPE_OBJECT
);
72 static EmpathyContact
*
73 tp_group_get_contact (EmpathyTpGroup
*group
,
76 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
77 EmpathyContact
*contact
= NULL
;
80 contact
= empathy_contact_factory_get_from_handle (priv
->factory
,
85 if (contact
&& handle
== priv
->self_handle
) {
86 empathy_contact_set_is_user (contact
, TRUE
);
93 tp_group_get_contacts (EmpathyTpGroup
*group
,
94 const GArray
*handles
)
96 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
103 contacts
= empathy_contact_factory_get_from_handles (priv
->factory
,
107 /* FIXME: Only useful if the group has a different self handle than
108 * the connection, otherwise the contact factory already set that
109 * property. That can be known using group flags. */
110 for (l
= contacts
; l
; l
= l
->next
) {
111 if (empathy_contact_get_handle (l
->data
) == priv
->self_handle
) {
112 empathy_contact_set_is_user (l
->data
, TRUE
);
120 empathy_pending_info_new (EmpathyContact
*member
,
121 EmpathyContact
*actor
,
122 const gchar
*message
)
124 EmpathyPendingInfo
*info
;
126 info
= g_slice_new0 (EmpathyPendingInfo
);
129 info
->member
= g_object_ref (member
);
132 info
->actor
= g_object_ref (actor
);
135 info
->message
= g_strdup (message
);
142 empathy_pending_info_free (EmpathyPendingInfo
*info
)
149 g_object_unref (info
->member
);
152 g_object_unref (info
->actor
);
154 g_free (info
->message
);
156 g_slice_free (EmpathyPendingInfo
, info
);
160 tp_group_local_pending_find (gconstpointer a
,
163 const EmpathyPendingInfo
*info
= a
;
165 return (info
->member
!= b
);
169 tp_group_remove_from_pendings (EmpathyTpGroup
*group
,
170 EmpathyContact
*contact
)
172 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
176 l
= g_list_find_custom (priv
->local_pendings
,
178 tp_group_local_pending_find
);
180 empathy_pending_info_free (l
->data
);
181 priv
->local_pendings
= g_list_delete_link (priv
->local_pendings
, l
);
185 l
= g_list_find (priv
->remote_pendings
, contact
);
187 g_object_unref (l
->data
);
188 priv
->remote_pendings
= g_list_delete_link (priv
->remote_pendings
, l
);
193 tp_group_update_members (EmpathyTpGroup
*group
,
194 const gchar
*message
,
196 const GArray
*removed
,
197 const GArray
*local_pending
,
198 const GArray
*remote_pending
,
202 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
203 EmpathyContact
*actor_contact
= NULL
;
204 GList
*contacts
, *l
, *ll
;
206 actor_contact
= tp_group_get_contact (group
, actor
);
208 DEBUG ("Members changed for list %s:\n"
209 " added-len=%d, current-len=%d\n"
211 " local-pending-len=%d, current-len=%d\n"
212 " remote-pending-len=%d, current-len=%d",
213 priv
->group_name
, added
? added
->len
: 0,
214 g_list_length (priv
->members
), removed
? removed
->len
: 0,
215 local_pending
? local_pending
->len
: 0,
216 g_list_length (priv
->local_pendings
),
217 remote_pending
? remote_pending
->len
: 0,
218 g_list_length (priv
->remote_pendings
));
221 contacts
= tp_group_get_contacts (group
, added
);
222 for (l
= contacts
; l
; l
= l
->next
) {
223 tp_group_remove_from_pendings (group
, l
->data
);
225 /* If the contact is not yet member, add it and emit signal */
226 if (!g_list_find (priv
->members
, l
->data
)) {
227 priv
->members
= g_list_prepend (priv
->members
,
228 g_object_ref (l
->data
));
229 g_signal_emit (group
, signals
[MEMBER_ADDED
], 0,
230 l
->data
, actor_contact
, reason
, message
);
232 g_object_unref (l
->data
);
234 g_list_free (contacts
);
236 /* Contacts removed */
237 contacts
= tp_group_get_contacts (group
, removed
);
238 for (l
= contacts
; l
; l
= l
->next
) {
239 tp_group_remove_from_pendings (group
, l
->data
);
241 /* If the contact is member, remove it and emit signal */
242 if ((ll
= g_list_find (priv
->members
, l
->data
))) {
243 g_object_unref (ll
->data
);
244 priv
->members
= g_list_delete_link (priv
->members
, ll
);
245 g_signal_emit (group
, signals
[MEMBER_REMOVED
], 0,
246 l
->data
, actor_contact
, reason
, message
);
248 g_object_unref (l
->data
);
250 g_list_free (contacts
);
252 /* Contacts local pending */
253 contacts
= tp_group_get_contacts (group
, local_pending
);
254 for (l
= contacts
; l
; l
= l
->next
) {
255 /* If the contact is not yet local-pending, add it and emit signal */
256 if (!g_list_find_custom (priv
->local_pendings
, l
->data
,
257 tp_group_local_pending_find
)) {
258 EmpathyPendingInfo
*info
;
260 info
= empathy_pending_info_new (l
->data
,
264 priv
->local_pendings
= g_list_prepend (priv
->local_pendings
, info
);
265 g_signal_emit (group
, signals
[LOCAL_PENDING
], 0,
266 l
->data
, actor_contact
, reason
, message
);
268 g_object_unref (l
->data
);
270 g_list_free (contacts
);
272 /* Contacts remote pending */
273 contacts
= tp_group_get_contacts (group
, remote_pending
);
274 for (l
= contacts
; l
; l
= l
->next
) {
275 /* If the contact is not yet remote-pending, add it and emit signal */
276 if (!g_list_find (priv
->remote_pendings
, l
->data
)) {
277 priv
->remote_pendings
= g_list_prepend (priv
->remote_pendings
,
278 g_object_ref (l
->data
));
279 g_signal_emit (group
, signals
[REMOTE_PENDING
], 0,
280 l
->data
, actor_contact
, reason
, message
);
282 g_object_unref (l
->data
);
284 g_list_free (contacts
);
287 g_object_unref (actor_contact
);
290 DEBUG ("Members changed done for list %s:\n"
292 " local-pendings-len=%d\n"
293 " remote-pendings-len=%d",
294 priv
->group_name
, g_list_length (priv
->members
),
295 g_list_length (priv
->local_pendings
),
296 g_list_length (priv
->remote_pendings
));
300 tp_group_members_changed_cb (TpChannel
*channel
,
301 const gchar
*message
,
303 const GArray
*removed
,
304 const GArray
*local_pending
,
305 const GArray
*remote_pending
,
311 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
314 tp_group_update_members (EMPATHY_TP_GROUP (group
), message
,
316 local_pending
, remote_pending
,
322 tp_group_get_members_cb (TpChannel
*channel
,
323 const GArray
*handles
,
328 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
331 DEBUG ("Failed to get members: %s", error
->message
);
335 tp_group_update_members (EMPATHY_TP_GROUP (group
),
339 NULL
, /* local_pending */
340 NULL
, /* remote_pending */
346 g_object_notify (group
, "ready");
350 tp_group_get_local_pending_cb (TpChannel
*channel
,
351 const GPtrArray
*array
,
360 DEBUG ("Failed to get local pendings: %s", error
->message
);
364 handles
= g_array_sized_new (FALSE
, FALSE
, sizeof (guint
), 1);
365 g_array_append_val (handles
, i
);
366 for (i
= 0; array
->len
> i
; i
++) {
367 GValueArray
*pending_struct
;
368 const gchar
*message
;
373 pending_struct
= g_ptr_array_index (array
, i
);
374 member_handle
= g_value_get_uint (g_value_array_get_nth (pending_struct
, 0));
375 actor_handle
= g_value_get_uint (g_value_array_get_nth (pending_struct
, 1));
376 reason
= g_value_get_uint (g_value_array_get_nth (pending_struct
, 2));
377 message
= g_value_get_string (g_value_array_get_nth (pending_struct
, 3));
379 g_array_index (handles
, guint
, 0) = member_handle
;
381 tp_group_update_members (EMPATHY_TP_GROUP (group
),
382 message
, /* message */
385 handles
, /* local_pending */
386 NULL
, /* remote_pending */
387 actor_handle
, /* actor */
388 reason
); /* reason */
390 g_array_free (handles
, TRUE
);
394 tp_group_get_remote_pending_cb (TpChannel
*channel
,
395 const GArray
*handles
,
401 DEBUG ("Failed to get remote pendings: %s", error
->message
);
405 tp_group_update_members (EMPATHY_TP_GROUP (group
),
409 NULL
, /* local_pending */
410 handles
, /* remote_pending */
416 tp_group_inspect_handles_cb (TpConnection
*connection
,
422 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
425 DEBUG ("Failed to inspect channel handle: %s", error
->message
);
429 priv
->group_name
= g_strdup (*names
);
433 tp_group_invalidated_cb (TpProxy
*proxy
,
437 EmpathyTpGroup
*group
)
439 DEBUG ("Channel invalidated: %s", message
);
440 g_signal_emit (group
, signals
[DESTROY
], 0);
444 tp_group_get_self_handle_cb (TpChannel
*proxy
,
450 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
451 TpConnection
*connection
;
452 guint channel_handle
;
453 guint channel_handle_type
;
457 DEBUG ("Failed to get self handle: %s", error
->message
);
461 priv
->self_handle
= handle
;
462 tp_cli_channel_interface_group_connect_to_members_changed (priv
->channel
,
463 tp_group_members_changed_cb
,
467 /* GetMembers is called last, so it will be the last to get the reply,
468 * so we'll be ready once that call return. */
469 g_object_get (priv
->channel
,
470 "connection", &connection
,
471 "handle-type", &channel_handle_type
,
472 "handle", &channel_handle
,
474 handles
= g_array_sized_new (FALSE
, FALSE
, sizeof (guint
), 1);
475 g_array_prepend_val (handles
, channel_handle
);
476 tp_cli_connection_call_inspect_handles (connection
, -1,
479 tp_group_inspect_handles_cb
,
482 g_array_free (handles
, TRUE
);
484 tp_cli_channel_interface_group_call_get_local_pending_members_with_info
486 tp_group_get_local_pending_cb
,
489 tp_cli_channel_interface_group_call_get_remote_pending_members
491 tp_group_get_remote_pending_cb
,
494 tp_cli_channel_interface_group_call_get_members (priv
->channel
, -1,
495 tp_group_get_members_cb
,
501 tp_group_factory_ready_cb (EmpathyTpGroup
*group
)
503 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
504 EmpathyTpContactFactory
*tp_factory
;
506 tp_factory
= empathy_contact_factory_get_tp_factory (priv
->factory
, priv
->account
);
507 g_signal_handlers_disconnect_by_func (tp_factory
, tp_group_factory_ready_cb
, group
);
508 tp_cli_channel_interface_group_call_get_self_handle (priv
->channel
, -1,
509 tp_group_get_self_handle_cb
,
515 tp_group_channel_ready_cb (EmpathyTpGroup
*group
)
517 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
518 EmpathyTpContactFactory
*tp_factory
;
520 tp_factory
= empathy_contact_factory_get_tp_factory (priv
->factory
,
522 if (empathy_tp_contact_factory_is_ready (tp_factory
)) {
523 tp_group_factory_ready_cb (group
);
525 g_signal_connect_swapped (tp_factory
, "notify::ready",
526 G_CALLBACK (tp_group_factory_ready_cb
),
532 tp_group_finalize (GObject
*object
)
534 EmpathyTpGroupPriv
*priv
= GET_PRIV (object
);
535 EmpathyTpContactFactory
*tp_factory
;
537 DEBUG ("finalize: %p", object
);
539 tp_factory
= empathy_contact_factory_get_tp_factory (priv
->factory
, priv
->account
);
540 g_signal_handlers_disconnect_by_func (tp_factory
, tp_group_factory_ready_cb
, object
);
543 g_signal_handlers_disconnect_by_func (priv
->channel
,
544 tp_group_invalidated_cb
,
546 g_object_unref (priv
->channel
);
549 g_object_unref (priv
->account
);
552 g_object_unref (priv
->factory
);
554 g_free (priv
->group_name
);
556 g_list_foreach (priv
->members
, (GFunc
) g_object_unref
, NULL
);
557 g_list_free (priv
->members
);
559 g_list_foreach (priv
->local_pendings
, (GFunc
) empathy_pending_info_free
, NULL
);
560 g_list_free (priv
->local_pendings
);
562 g_list_foreach (priv
->remote_pendings
, (GFunc
) g_object_unref
, NULL
);
563 g_list_free (priv
->remote_pendings
);
565 G_OBJECT_CLASS (empathy_tp_group_parent_class
)->finalize (object
);
569 tp_group_constructed (GObject
*group
)
571 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
572 gboolean channel_ready
;
574 priv
->factory
= empathy_contact_factory_new ();
575 priv
->account
= empathy_channel_get_account (priv
->channel
);
577 g_signal_connect (priv
->channel
, "invalidated",
578 G_CALLBACK (tp_group_invalidated_cb
),
581 g_object_get (priv
->channel
, "channel-ready", &channel_ready
, NULL
);
583 tp_group_channel_ready_cb (EMPATHY_TP_GROUP (group
));
585 g_signal_connect_swapped (priv
->channel
, "notify::channel-ready",
586 G_CALLBACK (tp_group_channel_ready_cb
),
592 tp_group_get_property (GObject
*object
,
597 EmpathyTpGroupPriv
*priv
= GET_PRIV (object
);
601 g_value_set_object (value
, priv
->channel
);
604 g_value_set_boolean (value
, priv
->ready
);
607 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
613 tp_group_set_property (GObject
*object
,
618 EmpathyTpGroupPriv
*priv
= GET_PRIV (object
);
622 priv
->channel
= g_object_ref (g_value_get_object (value
));
625 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
631 empathy_tp_group_class_init (EmpathyTpGroupClass
*klass
)
633 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
635 object_class
->finalize
= tp_group_finalize
;
636 object_class
->constructed
= tp_group_constructed
;
637 object_class
->get_property
= tp_group_get_property
;
638 object_class
->set_property
= tp_group_set_property
;
640 g_object_class_install_property (object_class
,
642 g_param_spec_object ("channel",
644 "The channel for the group",
647 G_PARAM_CONSTRUCT_ONLY
));
648 g_object_class_install_property (object_class
,
650 g_param_spec_boolean ("ready",
651 "Is the object ready",
652 "This object can't be used until this becomes true",
656 signals
[MEMBER_ADDED
] =
657 g_signal_new ("member-added",
658 G_TYPE_FROM_CLASS (klass
),
662 _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING
,
664 4, EMPATHY_TYPE_CONTACT
, EMPATHY_TYPE_CONTACT
, G_TYPE_UINT
, G_TYPE_STRING
);
666 signals
[MEMBER_REMOVED
] =
667 g_signal_new ("member-removed",
668 G_TYPE_FROM_CLASS (klass
),
672 _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING
,
674 4, EMPATHY_TYPE_CONTACT
, EMPATHY_TYPE_CONTACT
, G_TYPE_UINT
, G_TYPE_STRING
);
676 signals
[LOCAL_PENDING
] =
677 g_signal_new ("local-pending",
678 G_TYPE_FROM_CLASS (klass
),
682 _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING
,
684 4, EMPATHY_TYPE_CONTACT
, EMPATHY_TYPE_CONTACT
, G_TYPE_UINT
, G_TYPE_STRING
);
686 signals
[REMOTE_PENDING
] =
687 g_signal_new ("remote-pending",
688 G_TYPE_FROM_CLASS (klass
),
692 _empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING
,
694 4, EMPATHY_TYPE_CONTACT
, EMPATHY_TYPE_CONTACT
, G_TYPE_UINT
, G_TYPE_STRING
);
697 g_signal_new ("destroy",
698 G_TYPE_FROM_CLASS (klass
),
702 g_cclosure_marshal_VOID__VOID
,
706 g_type_class_add_private (object_class
, sizeof (EmpathyTpGroupPriv
));
710 empathy_tp_group_init (EmpathyTpGroup
*group
)
712 EmpathyTpGroupPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (group
,
713 EMPATHY_TYPE_TP_GROUP
, EmpathyTpGroupPriv
);
719 empathy_tp_group_new (TpChannel
*channel
)
721 g_return_val_if_fail (TP_IS_CHANNEL (channel
), NULL
);
723 return g_object_new (EMPATHY_TYPE_TP_GROUP
,
729 tp_group_async_cb (TpChannel
*channel
,
732 GObject
*weak_object
)
735 DEBUG ("%s: %s", (gchar
*) user_data
, error
->message
);
740 empathy_tp_group_close (EmpathyTpGroup
*group
)
742 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
744 g_return_if_fail (EMPATHY_IS_TP_GROUP (group
));
745 g_return_if_fail (priv
->ready
);
747 tp_cli_channel_call_close (priv
->channel
, -1,
749 "Failed to close", NULL
,
754 tp_group_get_handles (GList
*contacts
)
760 length
= g_list_length (contacts
);
761 handles
= g_array_sized_new (FALSE
, FALSE
, sizeof (guint
), length
);
763 for (l
= contacts
; l
; l
= l
->next
) {
766 handle
= empathy_contact_get_handle (l
->data
);
767 g_array_append_val (handles
, handle
);
774 empathy_tp_group_add_members (EmpathyTpGroup
*group
,
776 const gchar
*message
)
778 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
781 g_return_if_fail (EMPATHY_IS_TP_GROUP (group
));
782 g_return_if_fail (contacts
!= NULL
);
783 g_return_if_fail (priv
->ready
);
785 handles
= tp_group_get_handles (contacts
);
786 tp_cli_channel_interface_group_call_add_members (priv
->channel
, -1,
790 "Failed to add members", NULL
,
792 g_array_free (handles
, TRUE
);
796 empathy_tp_group_remove_members (EmpathyTpGroup
*group
,
798 const gchar
*message
)
800 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
803 g_return_if_fail (EMPATHY_IS_TP_GROUP (group
));
804 g_return_if_fail (contacts
!= NULL
);
805 g_return_if_fail (priv
->ready
);
807 handles
= tp_group_get_handles (contacts
);
808 tp_cli_channel_interface_group_call_remove_members (priv
->channel
, -1,
812 "Failed to remove members", NULL
,
814 g_array_free (handles
, TRUE
);
818 empathy_tp_group_add_member (EmpathyTpGroup
*group
,
819 EmpathyContact
*contact
,
820 const gchar
*message
)
824 contacts
= g_list_prepend (NULL
, contact
);
825 empathy_tp_group_add_members (group
, contacts
, message
);
826 g_list_free (contacts
);
830 empathy_tp_group_remove_member (EmpathyTpGroup
*group
,
831 EmpathyContact
*contact
,
832 const gchar
*message
)
836 contacts
= g_list_prepend (NULL
, contact
);
837 empathy_tp_group_remove_members (group
, contacts
, message
);
838 g_list_free (contacts
);
842 empathy_tp_group_get_members (EmpathyTpGroup
*group
)
844 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
846 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), NULL
);
848 g_list_foreach (priv
->members
, (GFunc
) g_object_ref
, NULL
);
850 return g_list_copy (priv
->members
);
854 empathy_tp_group_get_local_pendings (EmpathyTpGroup
*group
)
856 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
857 GList
*pendings
= NULL
, *l
;
859 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), NULL
);
861 for (l
= priv
->local_pendings
; l
; l
= l
->next
) {
862 EmpathyPendingInfo
*info
;
863 EmpathyPendingInfo
*new_info
;
866 new_info
= empathy_pending_info_new (info
->member
,
869 pendings
= g_list_prepend (pendings
, new_info
);
876 empathy_tp_group_get_remote_pendings (EmpathyTpGroup
*group
)
878 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
880 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), NULL
);
882 g_list_foreach (priv
->remote_pendings
, (GFunc
) g_object_ref
, NULL
);
884 return g_list_copy (priv
->remote_pendings
);
888 empathy_tp_group_get_name (EmpathyTpGroup
*group
)
890 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
892 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), NULL
);
893 g_return_val_if_fail (priv
->ready
, NULL
);
895 return priv
->group_name
;
899 empathy_tp_group_get_self_contact (EmpathyTpGroup
*group
)
901 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
903 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), NULL
);
904 g_return_val_if_fail (priv
->ready
, NULL
);
906 return tp_group_get_contact (group
, priv
->self_handle
);
910 empathy_tp_group_is_member (EmpathyTpGroup
*group
,
911 EmpathyContact
*contact
)
913 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
915 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), FALSE
);
916 g_return_val_if_fail (EMPATHY_IS_CONTACT (contact
), FALSE
);
918 return g_list_find (priv
->members
, contact
) != NULL
;
922 empathy_tp_group_is_ready (EmpathyTpGroup
*group
)
924 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
926 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), FALSE
);
932 empathy_tp_group_get_invitation (EmpathyTpGroup
*group
,
933 EmpathyContact
**remote_contact
)
935 EmpathyTpGroupPriv
*priv
= GET_PRIV (group
);
936 EmpathyContact
*contact
= NULL
;
937 EmpathyPendingInfo
*invitation
= NULL
;
940 g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group
), FALSE
);
941 g_return_val_if_fail (priv
->ready
, NULL
);
943 for (l
= priv
->local_pendings
; l
; l
= l
->next
) {
944 EmpathyPendingInfo
*info
= l
->data
;
946 if (empathy_contact_is_user (info
->member
)) {
953 contact
= invitation
->actor
;
956 if (priv
->remote_pendings
) {
957 contact
= priv
->remote_pendings
->data
;
959 else if (priv
->members
) {
960 contact
= priv
->members
->data
;
964 if (remote_contact
&& contact
) {
965 *remote_contact
= g_object_ref (contact
);