diff -r 000000000000 -r d0f3a028347a telepathygabble/src/gabble-roster-channel.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telepathygabble/src/gabble-roster-channel.c Tue Feb 02 01:10:06 2010 +0200 @@ -0,0 +1,812 @@ +/* + * gabble-roster-channel.c - Source for GabbleRosterChannel + * Copyright (C) 2005 Collabora Ltd. + * + * + * 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 + +#define DEBUG_FLAG GABBLE_DEBUG_ROSTER + +#include "debug.h" +#include "gabble-connection.h" +#include "gintset.h" +#include "group-mixin.h" +#include "handle-set.h" +#include "roster.h" +#include "telepathy-errors.h" +#include "telepathy-helpers.h" +#include "telepathy-interfaces.h" +#include "tp-channel-iface.h" +#include "util.h" + +#include "gabble-roster-channel.h" +#include "gabble-roster-channel-glue.h" +#include "gabble-roster-channel-signals-marshal.h" + +#include "gabble_enums.h" + +#ifndef EMULATOR +G_DEFINE_TYPE_WITH_CODE (GabbleRosterChannel, gabble_roster_channel, + G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)); +#endif + +/* signal enum */ +enum +{ + CLOSED, + GROUP_FLAGS_CHANGED, + MEMBERS_CHANGED, + LAST_SIGNAL +#ifdef EMULATOR + = LAST_SIGNAL_ROS_CHNL +#endif + +}; + + +#ifdef EMULATOR +#include "libgabble_wsd_solution.h" + + GET_STATIC_ARRAY_FROM_TLS(signals,gabble_ros_chnl,guint) + #define signals (GET_WSD_VAR_NAME(signals,gabble_ros_chnl, s)()) + + GET_STATIC_VAR_FROM_TLS(gabble_roster_channel_parent_class,gabble_ros_chnl,gpointer) + #define gabble_roster_channel_parent_class (*GET_WSD_VAR_NAME(gabble_roster_channel_parent_class,gabble_ros_chnl,s)()) + + GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_ros_chnl,GType) + #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_ros_chnl,s)()) + +static void gabble_roster_channel_init (GabbleRosterChannel *self); +static void gabble_roster_channel_class_init (GabbleRosterChannelClass *klass); +static void gabble_roster_channel_class_intern_init (gpointer klass) +{ + gabble_roster_channel_parent_class = g_type_class_peek_parent (klass); + gabble_roster_channel_class_init ((GabbleRosterChannelClass*) klass); + } + + EXPORT_C GType gabble_roster_channel_get_type (void) + { + if ((g_define_type_id == 0)) { static const GTypeInfo g_define_type_info = { sizeof (GabbleRosterChannelClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_roster_channel_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleRosterChannel), 0, (GInstanceInitFunc) gabble_roster_channel_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleRosterChannel"), &g_define_type_info, (GTypeFlags) 0); { { static const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc) ((void *)0) }; g_type_add_interface_static (g_define_type_id, tp_channel_iface_get_type(), &g_implement_interface_info); } ; } } return g_define_type_id; } ; + +#else + + static guint signals[LAST_SIGNAL] = {0}; + +#endif + + + +/* properties */ +enum +{ + PROP_OBJECT_PATH = 1, + PROP_CHANNEL_TYPE, + PROP_HANDLE_TYPE, + PROP_HANDLE, + PROP_CONNECTION, + LAST_PROPERTY +}; + +/* private structure */ +typedef struct _GabbleRosterChannelPrivate GabbleRosterChannelPrivate; + +struct _GabbleRosterChannelPrivate +{ + GabbleConnection *conn; + char *object_path; + GabbleHandle handle; + + gboolean dispose_has_run; +}; + +#define GABBLE_ROSTER_CHANNEL_GET_PRIVATE(obj) \ + ((GabbleRosterChannelPrivate *)obj->priv) + +static void +gabble_roster_channel_init (GabbleRosterChannel *self) +{ + GabbleRosterChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + GABBLE_TYPE_ROSTER_CHANNEL, GabbleRosterChannelPrivate); + + self->priv = priv; + + /* allocate any data required by the object here */ +} + +static GObject * +gabble_roster_channel_constructor (GType type, guint n_props, + GObjectConstructParam *props) +{ + GObject *obj; + GabbleRosterChannelPrivate *priv; + DBusGConnection *bus; + GabbleHandleRepo *handles; + gboolean valid; + GabbleHandle self_handle; + + obj = G_OBJECT_CLASS (gabble_roster_channel_parent_class)-> + constructor (type, n_props, props); + priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj)); + handles = priv->conn->handles; + self_handle = priv->conn->self_handle; + + /* register object on the bus */ + bus = tp_get_bus (); + dbus_g_connection_register_g_object (bus, priv->object_path, obj); + + /* ref our list handle */ + valid = gabble_handle_ref (handles, TP_HANDLE_TYPE_LIST, priv->handle); + g_assert (valid); + + /* initialize group mixin */ + gabble_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleRosterChannel, group), + handles, self_handle); + + if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle) + { + gabble_group_mixin_change_flags (obj, + TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | + TP_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT | + TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE, + 0); + } + else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle) + { + gabble_group_mixin_change_flags (obj, + TP_CHANNEL_GROUP_FLAG_CAN_ADD | + TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | + TP_CHANNEL_GROUP_FLAG_CAN_RESCIND | + TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD | + TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE | + TP_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND, + 0); + } + else if (GABBLE_LIST_HANDLE_KNOWN == priv->handle) + { + gabble_group_mixin_change_flags (obj, + TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, + 0); + } + else if (GABBLE_LIST_HANDLE_DENY == priv->handle) + { + gabble_group_mixin_change_flags (obj, + TP_CHANNEL_GROUP_FLAG_CAN_ADD | + TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, + 0); + } + else + { + g_assert_not_reached (); + } + + return obj; +} + +static void +gabble_roster_channel_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GabbleRosterChannel *chan = GABBLE_ROSTER_CHANNEL (object); + GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan); + + switch (property_id) { + case PROP_OBJECT_PATH: + g_value_set_string (value, priv->object_path); + break; + case PROP_CHANNEL_TYPE: + g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST); + break; + case PROP_HANDLE_TYPE: + g_value_set_uint (value, TP_HANDLE_TYPE_LIST); + break; + case PROP_HANDLE: + g_value_set_uint (value, priv->handle); + break; + case PROP_CONNECTION: + g_value_set_object (value, priv->conn); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gabble_roster_channel_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GabbleRosterChannel *chan = GABBLE_ROSTER_CHANNEL (object); + GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan); + + switch (property_id) { + case PROP_OBJECT_PATH: + g_free (priv->object_path); + priv->object_path = g_value_dup_string (value); + break; + case PROP_HANDLE: + priv->handle = g_value_get_uint (value); + break; + case PROP_CONNECTION: + priv->conn = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void gabble_roster_channel_dispose (GObject *object); +static void gabble_roster_channel_finalize (GObject *object); + +static gboolean _gabble_roster_channel_add_member_cb (GObject *obj, GabbleHandle handle, const gchar *message, GError **error); +static gboolean _gabble_roster_channel_remove_member_cb (GObject *obj, GabbleHandle handle, const gchar *message, GError **error); + +static void +gabble_roster_channel_class_init (GabbleRosterChannelClass *gabble_roster_channel_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (gabble_roster_channel_class); + GParamSpec *param_spec; + + g_type_class_add_private (gabble_roster_channel_class, sizeof (GabbleRosterChannelPrivate)); + + object_class->constructor = gabble_roster_channel_constructor; + + object_class->get_property = gabble_roster_channel_get_property; + object_class->set_property = gabble_roster_channel_set_property; + + object_class->dispose = gabble_roster_channel_dispose; + object_class->finalize = gabble_roster_channel_finalize; + + param_spec = g_param_spec_object ("connection", "GabbleConnection object", + "Gabble connection object that owns this " + "Roster channel object.", + GABBLE_TYPE_CONNECTION, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB); + g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); + + g_object_class_override_property (object_class, PROP_OBJECT_PATH, "object-path"); + g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, "channel-type"); + g_object_class_override_property (object_class, PROP_HANDLE_TYPE, "handle-type"); + g_object_class_override_property (object_class, PROP_HANDLE, "handle"); + + signals[CLOSED] = + g_signal_new ("closed", + G_OBJECT_CLASS_TYPE (gabble_roster_channel_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gabble_group_mixin_class_init (object_class, + G_STRUCT_OFFSET (GabbleRosterChannelClass, group_class), + _gabble_roster_channel_add_member_cb, + _gabble_roster_channel_remove_member_cb); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (gabble_roster_channel_class), &dbus_glib_gabble_roster_channel_object_info); +} + +void +gabble_roster_channel_dispose (GObject *object) +{ + GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (object); + GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + g_signal_emit(self, signals[CLOSED], 0); + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (gabble_roster_channel_parent_class)->dispose) + G_OBJECT_CLASS (gabble_roster_channel_parent_class)->dispose (object); +} + +void +gabble_roster_channel_finalize (GObject *object) +{ + GabbleRosterChannel *self = GABBLE_ROSTER_CHANNEL (object); + GabbleRosterChannelPrivate *priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self); + + /* free any data held directly by the object here */ + + g_free (priv->object_path); + + gabble_handle_unref (priv->conn->handles, TP_HANDLE_TYPE_LIST, priv->handle); + + gabble_group_mixin_finalize (object); + + G_OBJECT_CLASS (gabble_roster_channel_parent_class)->finalize (object); +} + + +static gboolean +_gabble_roster_channel_send_presence (GabbleRosterChannel *chan, + LmMessageSubType sub_type, + GabbleHandle handle, + const gchar *status, + GError **error) +{ + GabbleRosterChannelPrivate *priv; + GabbleHandleRepo *repo; + const char *contact; + LmMessage *message; + gboolean result; + + priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (chan); + repo = priv->conn->handles; + contact = gabble_handle_inspect (repo, TP_HANDLE_TYPE_CONTACT, handle); + + message = lm_message_new_with_sub_type (contact, + LM_MESSAGE_TYPE_PRESENCE, + sub_type); + + if (LM_MESSAGE_SUB_TYPE_SUBSCRIBE == sub_type) + lm_message_node_add_own_nick (message->node, priv->conn); + + if (status != NULL && status[0] != '\0') + lm_message_node_add_child (message->node, "status", status); + + result = _gabble_connection_send (priv->conn, message, error); + + lm_message_unref (message); + + return result; +} + + +/** + * _gabble_roster_channel_add_member_cb + * + * Called by the group mixin to add one member. + */ +static gboolean +_gabble_roster_channel_add_member_cb (GObject *obj, + GabbleHandle handle, + const gchar *message, + GError **error) +{ + GabbleRosterChannelPrivate *priv; + GabbleHandleRepo *repo; + gboolean ret = FALSE; + + priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj)); + + repo = priv->conn->handles; + + gabble_debug (DEBUG_FLAG, "called on %s with handle %u (%s) \"%s\"", gabble_handle_inspect (repo, TP_HANDLE_TYPE_LIST, priv->handle), handle, + gabble_handle_inspect (repo, TP_HANDLE_TYPE_CONTACT, handle), message); + + /* publish list */ + if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle) + { + /* send */ + ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj), + LM_MESSAGE_SUB_TYPE_SUBSCRIBED, handle, message, error); + } + /* subscribe list */ + else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle) + { + /* add item to the roster (GTalk depends on this, clearing the H flag) */ + gabble_roster_handle_add (priv->conn->roster, handle, NULL); + + /* send */ + ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj), + LM_MESSAGE_SUB_TYPE_SUBSCRIBE, handle, message, error); + } + /* deny list */ + else if (GABBLE_LIST_HANDLE_DENY == priv->handle) + { + /* block contact */ + ret = gabble_roster_handle_set_blocked (priv->conn->roster, handle, TRUE, + error); + } + else + { + g_assert_not_reached (); + } + + return ret; +} + + +/** + * _gabble_roster_channel_remove_member_cb + * + * Called by the group mixin to remove one member. + */ +static gboolean +_gabble_roster_channel_remove_member_cb (GObject *obj, + GabbleHandle handle, + const gchar *message, + GError **error) +{ + GabbleRosterChannelPrivate *priv; + GabbleHandleRepo *repo; + gboolean ret = FALSE; + + priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (GABBLE_ROSTER_CHANNEL (obj)); + + repo = priv->conn->handles; + + gabble_debug (DEBUG_FLAG, "called on %s with handle %u (%s) \"%s\"", gabble_handle_inspect (repo, TP_HANDLE_TYPE_LIST, priv->handle), handle, + gabble_handle_inspect (repo, TP_HANDLE_TYPE_CONTACT, handle), message); + + /* publish list */ + if (GABBLE_LIST_HANDLE_PUBLISH == priv->handle) + { + /* send */ + ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj), + LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED, handle, message, error); + + /* remove it from local_pending here, because roster callback doesn't + know if it can (subscription='none' is used both during request and + when it's rejected) */ + if (handle_set_is_member (GABBLE_ROSTER_CHANNEL (obj)->group.local_pending, handle)) + { + GIntSet *rem = g_intset_new (); + + g_intset_add (rem, handle); + gabble_group_mixin_change_members (obj, "", NULL, rem, NULL, NULL, + 0, 0); + + g_intset_destroy (rem); + } + } + /* subscribe list */ + else if (GABBLE_LIST_HANDLE_SUBSCRIBE == priv->handle) + { + /* send */ + ret = _gabble_roster_channel_send_presence (GABBLE_ROSTER_CHANNEL (obj), + LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE, handle, message, error); + } + /* known list */ + else if (GABBLE_LIST_HANDLE_KNOWN == priv->handle) + { + /* send roster subscription=remove IQ */ + ret = gabble_roster_handle_remove (priv->conn->roster, handle, error); + } + /* deny list */ + else if (GABBLE_LIST_HANDLE_DENY == priv->handle) + { + /* unblock contact */ + ret = gabble_roster_handle_set_blocked (priv->conn->roster, handle, FALSE, + error); + } + else + { + g_assert_not_reached (); + } + + return ret; +} + + +/** + * gabble_roster_channel_add_members + * + * Implements D-Bus method AddMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_add_members (GabbleRosterChannel *self, + const GArray *contacts, + const gchar *message, + GError **error) +{ + return gabble_group_mixin_add_members (G_OBJECT (self), contacts, message, + error); +} + + +/** + * gabble_roster_channel_close + * + * Implements D-Bus method Close + * on interface org.freedesktop.Telepathy.Channel + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_close (GabbleRosterChannel *self, + GError **error) +{ + g_set_error (error, TELEPATHY_ERRORS, NotImplemented, + "you may not close contact list channels"); + + return FALSE; +} + + +/** + * gabble_roster_channel_get_all_members + * + * Implements D-Bus method GetAllMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_all_members (GabbleRosterChannel *self, + GArray **ret, + GArray **ret1, + GArray **ret2, + GError **error) +{ + return gabble_group_mixin_get_all_members (G_OBJECT (self), ret, ret1, ret2, + error); +} + + +/** + * gabble_roster_channel_get_channel_type + * + * Implements D-Bus method GetChannelType + * on interface org.freedesktop.Telepathy.Channel + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_channel_type (GabbleRosterChannel *self, + gchar **ret, + GError **error) +{ + *ret = g_strdup (TP_IFACE_CHANNEL_TYPE_CONTACT_LIST); + + return TRUE; +} + + +/** + * gabble_roster_channel_get_group_flags + * + * Implements D-Bus method GetGroupFlags + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_group_flags (GabbleRosterChannel *self, + guint *ret, + GError **error) +{ + return gabble_group_mixin_get_group_flags (G_OBJECT (self), ret, error); +} + + +/** + * gabble_roster_channel_get_handle + * + * Implements D-Bus method GetHandle + * on interface org.freedesktop.Telepathy.Channel + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_handle (GabbleRosterChannel *self, + guint *ret, + guint *ret1, + GError **error) +{ + GabbleRosterChannelPrivate *priv; + + g_assert (GABBLE_IS_ROSTER_CHANNEL (self)); + + priv = GABBLE_ROSTER_CHANNEL_GET_PRIVATE (self); + + *ret = TP_HANDLE_TYPE_LIST; + *ret1 = priv->handle; + + return TRUE; +} + + +/** + * gabble_roster_channel_get_handle_owners + * + * Implements D-Bus method GetHandleOwners + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_handle_owners (GabbleRosterChannel *self, + const GArray *handles, + GArray **ret, + GError **error) +{ + return gabble_group_mixin_get_handle_owners (G_OBJECT (self), handles, ret, + error); +} + + +/** + * gabble_roster_channel_get_interfaces + * + * Implements D-Bus method GetInterfaces + * on interface org.freedesktop.Telepathy.Channel + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_interfaces (GabbleRosterChannel *self, + gchar ***ret, + GError **error) +{ + const char *interfaces[] = { TP_IFACE_CHANNEL_INTERFACE_GROUP, NULL }; + + *ret = g_strdupv ((gchar **) interfaces); + + return TRUE; +} + + +/** + * gabble_roster_channel_get_local_pending_members + * + * Implements D-Bus method GetLocalPendingMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_local_pending_members (GabbleRosterChannel *self, + GArray **ret, + GError **error) +{ + return gabble_group_mixin_get_local_pending_members (G_OBJECT (self), ret, + error); +} + + +/** + * gabble_roster_channel_get_members + * + * Implements D-Bus method GetMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_members (GabbleRosterChannel *self, + GArray **ret, + GError **error) +{ + return gabble_group_mixin_get_members (G_OBJECT (self), ret, error); +} + + +/** + * gabble_roster_channel_get_remote_pending_members + * + * Implements D-Bus method GetRemotePendingMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_remote_pending_members (GabbleRosterChannel *self, + GArray **ret, + GError **error) +{ + return gabble_group_mixin_get_remote_pending_members (G_OBJECT (self), ret, + error); +} + + +/** + * gabble_roster_channel_get_self_handle + * + * Implements D-Bus method GetSelfHandle + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_get_self_handle (GabbleRosterChannel *self, + guint *ret, + GError **error) +{ + return gabble_group_mixin_get_self_handle (G_OBJECT (self), ret, error); +} + + +/** + * gabble_roster_channel_remove_members + * + * Implements D-Bus method RemoveMembers + * on interface org.freedesktop.Telepathy.Channel.Interface.Group + * + * @error: Used to return a pointer to a GError detailing any error + * that occurred, D-Bus will throw the error only if this + * function returns FALSE. + * + * Returns: TRUE if successful, FALSE if an error was thrown. + */ +gboolean +gabble_roster_channel_remove_members (GabbleRosterChannel *self, + const GArray *contacts, + const gchar *message, + GError **error) +{ + return gabble_group_mixin_remove_members (G_OBJECT (self), contacts, message, + error); +} +