diff -r d0f3a028347a -r 59927b2d3b75 telepathygabble/src/group-mixin.c --- a/telepathygabble/src/group-mixin.c Tue Feb 02 01:10:06 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,785 +0,0 @@ -/* - * group-mixin.c - Source for GabbleGroupMixin - * Copyright (C) 2006 Collabora Ltd. - * - * @author Ole Andre Vadla Ravnaas - * @author Robert McQueen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "ansi.h" -#include "debug.h" -#include "telepathy-errors.h" - - -#include "group-mixin.h" -#include "group-mixin-signals-marshal.h" - -#define DEBUG_FLAG GABBLE_DEBUG_GROUPS -#ifdef DEBUG_FLAG -//#define DEBUG(format, ...) -#define DEBUGGING 0 -#define NODE_DEBUG(n, s) -#endif /* DEBUG_FLAG */ - -#ifdef EMULATOR -#include "libgabble_wsd_solution.h" - - GET_STATIC_VAR_FROM_TLS(offset_quark1,gabble_grp_mixin,GQuark) - #define offset_quark1 (*GET_WSD_VAR_NAME(offset_quark1,gabble_grp_mixin, s)()) - - GET_STATIC_VAR_FROM_TLS(offset_quark,gabble_grp_mixin,GQuark) - #define offset_quark (*GET_WSD_VAR_NAME(offset_quark,gabble_grp_mixin, s)()) - - -#endif - -static const char *group_change_reason_str(guint reason) -{ - switch (reason) - { - case TP_CHANNEL_GROUP_CHANGE_REASON_NONE: - return "unspecified reason"; - case TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE: - return "offline"; - case TP_CHANNEL_GROUP_CHANGE_REASON_KICKED: - return "kicked"; - case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY: - return "busy"; - case TP_CHANNEL_GROUP_CHANGE_REASON_INVITED: - return "invited"; - case TP_CHANNEL_GROUP_CHANGE_REASON_BANNED: - return "banned"; - default: - return "(unknown reason code)"; - } -} - -struct _GabbleGroupMixinPrivate { - GabbleHandleSet *actors; - GHashTable *handle_owners; -}; - - -/** - * gabble_group_mixin_class_get_offset_quark: - * - * Returns: the quark used for storing mixin offset on a GObjectClass - */ -GQuark -gabble_group_mixin_class_get_offset_quark () -{ -#ifndef EMULATOR - static GQuark offset_quark1 = 0; -#endif - - if (!offset_quark1) - offset_quark1 = g_quark_from_static_string("GroupMixinClassOffsetQuark"); - return offset_quark1; -} - -/** - * gabble_group_mixin_get_offset_quark: - * - * Returns: the quark used for storing mixin offset on a GObject - */ -GQuark -gabble_group_mixin_get_offset_quark () -{ -#ifndef EMULATOR - static GQuark offset_quark = 0; -#endif - - if (!offset_quark) - offset_quark = g_quark_from_static_string("GroupMixinOffsetQuark"); - return offset_quark; -} - -void gabble_group_mixin_class_init (GObjectClass *obj_cls, - glong offset, - GabbleGroupMixinAddMemberFunc add_func, - GabbleGroupMixinRemMemberFunc rem_func) -{ - GabbleGroupMixinClass *mixin_cls; - - g_assert (G_IS_OBJECT_CLASS (obj_cls)); - - g_type_set_qdata (G_OBJECT_CLASS_TYPE (obj_cls), - GABBLE_GROUP_MIXIN_CLASS_OFFSET_QUARK, - GINT_TO_POINTER (offset)); - - mixin_cls = GABBLE_GROUP_MIXIN_CLASS (obj_cls); - - mixin_cls->add_member = add_func; - mixin_cls->remove_member = rem_func; - - mixin_cls->group_flags_changed_signal_id = - g_signal_new ("group-flags-changed", - G_OBJECT_CLASS_TYPE (obj_cls), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - group_mixin_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - mixin_cls->members_changed_signal_id = - g_signal_new ("members-changed", - G_OBJECT_CLASS_TYPE (obj_cls), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - group_mixin_marshal_VOID__STRING_BOXED_BOXED_BOXED_BOXED_UINT_UINT, - G_TYPE_NONE, 7, G_TYPE_STRING, DBUS_TYPE_G_UINT_ARRAY, DBUS_TYPE_G_UINT_ARRAY, DBUS_TYPE_G_UINT_ARRAY, DBUS_TYPE_G_UINT_ARRAY, G_TYPE_UINT, G_TYPE_UINT); -} - -void gabble_group_mixin_init (GObject *obj, - glong offset, - GabbleHandleRepo *handle_repo, - GabbleHandle self_handle) -{ - GabbleGroupMixin *mixin; - - g_assert (G_IS_OBJECT (obj)); - - g_type_set_qdata (G_OBJECT_TYPE (obj), - GABBLE_GROUP_MIXIN_OFFSET_QUARK, - GINT_TO_POINTER (offset)); - - mixin = GABBLE_GROUP_MIXIN (obj); - - mixin->handle_repo = handle_repo; - mixin->self_handle = self_handle; - - mixin->group_flags = 0; - - mixin->members = handle_set_new (handle_repo, TP_HANDLE_TYPE_CONTACT); - mixin->local_pending = handle_set_new (handle_repo, TP_HANDLE_TYPE_CONTACT); - mixin->remote_pending = handle_set_new (handle_repo, TP_HANDLE_TYPE_CONTACT); - - mixin->priv = g_new0 (GabbleGroupMixinPrivate, 1); - mixin->priv->handle_owners = g_hash_table_new (g_direct_hash, g_direct_equal); - mixin->priv->actors = handle_set_new (handle_repo, TP_HANDLE_TYPE_CONTACT); -} - -static void -handle_owners_foreach_unref (gpointer key, - gpointer value, - gpointer user_data) -{ - GabbleGroupMixin *mixin = user_data; - - gabble_handle_unref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - GPOINTER_TO_UINT (key)); - gabble_handle_unref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - GPOINTER_TO_UINT (value)); -} - -void gabble_group_mixin_finalize (GObject *obj) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - handle_set_destroy (mixin->priv->actors); - - g_hash_table_foreach (mixin->priv->handle_owners, - handle_owners_foreach_unref, - mixin); - - g_hash_table_destroy (mixin->priv->handle_owners); - - g_free (mixin->priv); - - handle_set_destroy (mixin->members); - handle_set_destroy (mixin->local_pending); - handle_set_destroy (mixin->remote_pending); -} - -gboolean -gabble_group_mixin_get_self_handle (GObject *obj, guint *ret, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - if (handle_set_is_member (mixin->members, mixin->self_handle) || - handle_set_is_member (mixin->local_pending, mixin->self_handle) || - handle_set_is_member (mixin->remote_pending, mixin->self_handle)) - { - *ret = mixin->self_handle; - } - else - { - *ret = 0; - } - - return TRUE; -} - -gboolean -gabble_group_mixin_get_group_flags (GObject *obj, guint *ret, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - *ret = mixin->group_flags; - - return TRUE; -} - -gboolean -gabble_group_mixin_add_members (GObject *obj, const GArray *contacts, const gchar *message, GError **error) -{ - GabbleGroupMixinClass *mixin_cls = GABBLE_GROUP_MIXIN_CLASS (G_OBJECT_GET_CLASS (obj)); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - guint i; - GabbleHandle handle; - - /* reject invalid handles */ - if (!gabble_handles_are_valid (mixin->handle_repo, - TP_HANDLE_TYPE_CONTACT, - contacts, - FALSE, - error)) - return FALSE; - - /* check that adding is allowed by flags */ - for (i = 0; i < contacts->len; i++) - { - handle = g_array_index (contacts, GabbleHandle, i); - - if ((mixin->group_flags & TP_CHANNEL_GROUP_FLAG_CAN_ADD) == 0 && - !handle_set_is_member (mixin->local_pending, handle)) - { - gabble_debug (DEBUG_FLAG, "handle %u cannot be added to members without GROUP_FLAG_CAN_ADD", - handle); - - g_set_error (error, TELEPATHY_ERRORS, PermissionDenied, - "handle %u cannot be added to members without GROUP_FLAG_CAN_ADD", - handle); - - return FALSE; - } - } - - /* add handle by handle */ - for (i = 0; i < contacts->len; i++) - { - handle = g_array_index (contacts, GabbleHandle, i); - - if (handle_set_is_member (mixin->members, handle)) - { - gabble_debug (DEBUG_FLAG, "handle %u is already a member, skipping", handle); - - continue; - } - - if (!mixin_cls->add_member (obj, handle, message, error)) - { - return FALSE; - } - } - - return TRUE; -} - -gboolean -gabble_group_mixin_remove_members (GObject *obj, const GArray *contacts, const gchar *message, GError **error) -{ - GabbleGroupMixinClass *mixin_cls = GABBLE_GROUP_MIXIN_CLASS (G_OBJECT_GET_CLASS (obj)); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - guint i; - GabbleHandle handle; - - /* reject invalid handles */ - if (!gabble_handles_are_valid (mixin->handle_repo, - TP_HANDLE_TYPE_CONTACT, - contacts, - FALSE, - error)) - return FALSE; - - /* check removing is allowed by flags */ - for (i = 0; i < contacts->len; i++) - { - handle = g_array_index (contacts, GabbleHandle, i); - - if (handle_set_is_member (mixin->members, handle)) - { - if ((mixin->group_flags & TP_CHANNEL_GROUP_FLAG_CAN_REMOVE) == 0) - { - gabble_debug (DEBUG_FLAG, "handle %u cannot be removed from members without GROUP_FLAG_CAN_REMOVE", - handle); - - g_set_error (error, TELEPATHY_ERRORS, PermissionDenied, - "handle %u cannot be removed from members without GROUP_FLAG_CAN_REMOVE", - handle); - - return FALSE; - } - } - else if (handle_set_is_member (mixin->remote_pending, handle)) - { - if ((mixin->group_flags & TP_CHANNEL_GROUP_FLAG_CAN_RESCIND) == 0) - { - gabble_debug (DEBUG_FLAG, "handle %u cannot be removed from remote pending without GROUP_FLAG_CAN_RESCIND", - handle); - - g_set_error (error, TELEPATHY_ERRORS, PermissionDenied, - "handle %u cannot be removed from remote pending without GROUP_FLAG_CAN_RESCIND", - handle); - - return FALSE; - } - } - else if (!handle_set_is_member (mixin->local_pending, handle)) - { - gabble_debug (DEBUG_FLAG, "handle %u is not a current or pending member", - handle); - - g_set_error (error, TELEPATHY_ERRORS, NotAvailable, - "handle %u is not a current or pending member", handle); - - return FALSE; - } - } - - /* remove handle by handle */ - for (i = 0; i < contacts->len; i++) - { - handle = g_array_index (contacts, GabbleHandle, i); - - if (!mixin_cls->remove_member (obj, handle, message, error)) - { - return FALSE; - } - } - - return TRUE; -} - -gboolean -gabble_group_mixin_get_members (GObject *obj, GArray **ret, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - *ret = handle_set_to_array (mixin->members); - - return TRUE; -} - -gboolean -gabble_group_mixin_get_local_pending_members (GObject *obj, GArray **ret, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - *ret = handle_set_to_array (mixin->local_pending); - - return TRUE; -} - -gboolean -gabble_group_mixin_get_remote_pending_members (GObject *obj, GArray **ret, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - *ret = handle_set_to_array (mixin->remote_pending); - - return TRUE; -} - -gboolean -gabble_group_mixin_get_all_members (GObject *obj, GArray **ret, GArray **ret1, GArray **ret2, GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - *ret = handle_set_to_array (mixin->members); - *ret1 = handle_set_to_array (mixin->local_pending); - *ret2 = handle_set_to_array (mixin->remote_pending); - - return TRUE; -} - -gboolean -gabble_group_mixin_get_handle_owners (GObject *obj, - const GArray *handles, - GArray **ret, - GError **error) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GabbleGroupMixinPrivate *priv = mixin->priv; - guint i; - - if ((mixin->group_flags & - TP_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES) == 0) - { - g_set_error (error, TELEPATHY_ERRORS, NotAvailable, - "channel doesn't have channel specific handles"); - - return FALSE; - } - - if (!gabble_handles_are_valid (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - handles, FALSE, error)) - { - return FALSE; - } - - *ret = g_array_sized_new (FALSE, FALSE, sizeof (GabbleHandle), handles->len); - - for (i = 0; i < handles->len; i++) - { - GabbleHandle local_handle = g_array_index (handles, GabbleHandle, i); - GabbleHandle owner_handle; - - if (!handle_set_is_member (mixin->members, local_handle)) - { - g_set_error (error, TELEPATHY_ERRORS, InvalidArgument, - "handle %u is not a member", local_handle); - - g_array_free (*ret, TRUE); - *ret = NULL; - - return FALSE; - } - - owner_handle = GPOINTER_TO_UINT ( - g_hash_table_lookup (priv->handle_owners, - GUINT_TO_POINTER (local_handle))); - - g_array_append_val (*ret, owner_handle); - } - - return TRUE; -} - -#define GFTS_APPEND_FLAG_IF_SET(flag) \ - if (flags & flag) \ - { \ - if (i++ > 0) \ - g_string_append (str, "|"); \ - g_string_append (str, #flag + 22); \ - } - -static gchar * -group_flags_to_string (TpChannelGroupFlags flags) -{ - gint i = 0; - GString *str; - - str = g_string_new ("[" ANSI_BOLD_OFF); - - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_CAN_ADD); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_CAN_REMOVE); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_CAN_RESCIND); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_MESSAGE_REJECT); - GFTS_APPEND_FLAG_IF_SET (TP_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND); - - g_string_append (str, ANSI_BOLD_ON "]"); - - return g_string_free (str, FALSE); -} - -/** - * gabble_group_mixin_change_flags: - * - * Request a change to be made to the flags. Emits the - * signal with the changes which were made. - */ -void -gabble_group_mixin_change_flags (GObject *obj, - TpChannelGroupFlags add, - TpChannelGroupFlags remove) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GabbleGroupMixinClass *mixin_cls = GABBLE_GROUP_MIXIN_CLASS (G_OBJECT_GET_CLASS (obj)); - TpChannelGroupFlags added, removed; - - added = add & ~mixin->group_flags; - mixin->group_flags |= added; - - removed = remove & mixin->group_flags; - mixin->group_flags &= ~removed; - - if (add != 0 || remove != 0) - { - gchar *str_added, *str_removed, *str_flags; - - if (DEBUGGING) - { - str_added = group_flags_to_string (added); - str_removed = group_flags_to_string (removed); - str_flags = group_flags_to_string (mixin->group_flags); - - g_message (ANSI_BOLD_ON ANSI_FG_WHITE - "%s: emitting group flags changed\n" - " added : %s\n" - " removed : %s\n" - " flags now: %s\n" ANSI_RESET, - G_STRFUNC, str_added, str_removed, str_flags); - - fflush (stdout); - - g_free (str_added); - g_free (str_removed); - g_free (str_flags); - } - - g_signal_emit(obj, mixin_cls->group_flags_changed_signal_id, 0, added, removed); - } -} - -static gchar * -member_array_to_string (GabbleHandleRepo *repo, const GArray *array) -{ - GString *str; - guint i; - - str = g_string_new ("[" ANSI_BOLD_OFF); - - for (i = 0; i < array->len; i++) - { - GabbleHandle handle; - const gchar *handle_str; - - handle = g_array_index (array, guint32, i); - handle_str = gabble_handle_inspect (repo, TP_HANDLE_TYPE_CONTACT, handle); - - g_string_append_printf (str, "%s%u (%s)", - (i > 0) ? "\n " : "", - handle, handle_str); - } - - g_string_append (str, ANSI_BOLD_ON "]"); - - return g_string_free (str, FALSE); -} - -static void remove_handle_owners_if_exist (GObject *obj, GArray *array); - -/** - * gabble_group_mixin_change_members: - * - * Request members to be added, removed or marked as local or remote pending. - * Changes member sets, references, and emits the MembersChanged signal. - */ -gboolean -gabble_group_mixin_change_members (GObject *obj, - const gchar *message, - GIntSet *add, - GIntSet *remove, - GIntSet *local_pending, - GIntSet *remote_pending, - GabbleHandle actor, - guint reason) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GabbleGroupMixinClass *mixin_cls = GABBLE_GROUP_MIXIN_CLASS (G_OBJECT_GET_CLASS (obj)); - GIntSet *new_add, *new_remove, *new_local_pending, - *new_remote_pending, *tmp, *tmp2, *empty; - gboolean ret; - - empty = g_intset_new (); - - if (add == NULL) - add = empty; - - if (remove == NULL) - remove = empty; - - if (local_pending == NULL) - local_pending = empty; - - if (remote_pending == NULL) - remote_pending = empty; - - /* members + add */ - new_add = handle_set_update (mixin->members, add); - - /* members - remove */ - new_remove = handle_set_difference_update (mixin->members, remove); - - /* members - local_pending */ - tmp = handle_set_difference_update (mixin->members, local_pending); - g_intset_destroy (tmp); - - /* members - remote_pending */ - tmp = handle_set_difference_update (mixin->members, remote_pending); - g_intset_destroy (tmp); - - - /* local pending + local_pending */ - new_local_pending = handle_set_update (mixin->local_pending, local_pending); - - /* local pending - add */ - tmp = handle_set_difference_update (mixin->local_pending, add); - g_intset_destroy (tmp); - - /* local pending - remove */ - tmp = handle_set_difference_update (mixin->local_pending, remove); - tmp2 = g_intset_union (new_remove, tmp); - g_intset_destroy (new_remove); - g_intset_destroy (tmp); - new_remove = tmp2; - - /* local pending - remote_pending */ - tmp = handle_set_difference_update (mixin->local_pending, remote_pending); - g_intset_destroy (tmp); - - - /* remote pending + remote_pending */ - new_remote_pending = handle_set_update (mixin->remote_pending, remote_pending); - - /* remote pending - add */ - tmp = handle_set_difference_update (mixin->remote_pending, add); - g_intset_destroy (tmp); - - /* remote pending - remove */ - tmp = handle_set_difference_update (mixin->remote_pending, remove); - tmp2 = g_intset_union (new_remove, tmp); - g_intset_destroy (new_remove); - g_intset_destroy (tmp); - new_remove = tmp2; - - /* remote pending - local_pending */ - tmp = handle_set_difference_update (mixin->remote_pending, local_pending); - g_intset_destroy (tmp); - - if (g_intset_size (new_add) > 0 || - g_intset_size (new_remove) > 0 || - g_intset_size (new_local_pending) > 0 || - g_intset_size (new_remote_pending) > 0) - { - GArray *arr_add, *arr_remove, *arr_local, *arr_remote; - gchar *add_str, *rem_str, *local_str, *remote_str; - - /* translate intsets to arrays */ - arr_add = g_intset_to_array (new_add); - arr_remove = g_intset_to_array (new_remove); - arr_local = g_intset_to_array (new_local_pending); - arr_remote = g_intset_to_array (new_remote_pending); - - /* remove any handle owner mappings */ - remove_handle_owners_if_exist (obj, arr_remove); - - if (DEBUGGING) - { - add_str = member_array_to_string (mixin->handle_repo, arr_add); - rem_str = member_array_to_string (mixin->handle_repo, arr_remove); - local_str = member_array_to_string (mixin->handle_repo, arr_local); - remote_str = member_array_to_string (mixin->handle_repo, arr_remote); - - g_message (ANSI_BOLD_ON ANSI_FG_CYAN - "%s: emitting members changed\n" - " message : \"%s\"\n" - " added : %s\n" - " removed : %s\n" - " local_pending : %s\n" - " remote_pending: %s\n" - " actor : %u\n" - " reason : %u: %s\n" ANSI_RESET, - G_STRFUNC, message, add_str, rem_str, local_str, remote_str, - actor, reason, group_change_reason_str(reason)); - - fflush (stdout); - - g_free (add_str); - g_free (rem_str); - g_free (local_str); - g_free (remote_str); - } - - if (actor) - { - handle_set_add (mixin->priv->actors, actor); - } - /* emit signal */ - g_signal_emit(obj, mixin_cls->members_changed_signal_id, 0, - message, - arr_add, arr_remove, - arr_local, arr_remote, - actor, reason); - - /* free arrays */ - g_array_free (arr_add, TRUE); - g_array_free (arr_remove, TRUE); - g_array_free (arr_local, TRUE); - g_array_free (arr_remote, TRUE); - - ret = TRUE; - } - else - { - gabble_debug (DEBUG_FLAG, "not emitting signal, nothing changed"); - - ret = FALSE; - } - - /* free intsets */ - g_intset_destroy (new_add); - g_intset_destroy (new_remove); - g_intset_destroy (new_local_pending); - g_intset_destroy (new_remote_pending); - g_intset_destroy (empty); - - return ret; -} - -void -gabble_group_mixin_add_handle_owner (GObject *obj, - GabbleHandle local_handle, - GabbleHandle owner_handle) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GabbleGroupMixinPrivate *priv = mixin->priv; - - g_hash_table_insert (priv->handle_owners, GUINT_TO_POINTER (local_handle), - GUINT_TO_POINTER (owner_handle)); - - gabble_handle_ref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - local_handle); - gabble_handle_ref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - owner_handle); -} - -static void -remove_handle_owners_if_exist (GObject *obj, GArray *array) -{ - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GabbleGroupMixinPrivate *priv = mixin->priv; - guint i; - - for (i = 0; i < array->len; i++) - { - GabbleHandle handle = g_array_index (array, guint32, i); - gpointer local_handle, owner_handle; - - if (g_hash_table_lookup_extended (priv->handle_owners, - GUINT_TO_POINTER (handle), - &local_handle, - &owner_handle)) - { - gabble_handle_unref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - GPOINTER_TO_UINT (local_handle)); - gabble_handle_unref (mixin->handle_repo, TP_HANDLE_TYPE_CONTACT, - GPOINTER_TO_UINT (owner_handle)); - - g_hash_table_remove (priv->handle_owners, GUINT_TO_POINTER (handle)); - } - } -} -