]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-group.c
Add empathy_tp_chat_get_connection() to direct access the channel's connection.
[empathy.git] / libempathy / empathy-tp-group.c
index 6357169d5f9aaa9252e6b59e172e334feee790f7..c3471c1578c432c721667ba7929a7fd4cbfd336b 100644 (file)
 
 #include <config.h>
 
-#include <telepathy-glib/channel.h>
+#include <libmissioncontrol/mc-account.h>
+
 #include <telepathy-glib/util.h>
 #include <telepathy-glib/interfaces.h>
 
 #include "empathy-tp-group.h"
 #include "empathy-contact-factory.h"
-#include "empathy-debug.h"
 #include "empathy-utils.h"
 #include "empathy-marshal.h"
 
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
-                      EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupPriv))
-
-#define DEBUG_DOMAIN "TpGroup"
+#define DEBUG_FLAG EMPATHY_DEBUG_TP
+#include "empathy-debug.h"
 
-struct _EmpathyTpGroupPriv {
-       McAccount             *account;
-       TpChan                *tp_chan;
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpGroup)
+typedef struct {
        TpChannel             *channel;
+       gboolean               ready;
 
        EmpathyContactFactory *factory;
+       McAccount             *account;
        gchar                 *group_name;
        guint                  self_handle;
-       gboolean               ready;
        GList                 *members;
        GList                 *local_pendings;
        GList                 *remote_pendings;
-};
-
-static void empathy_tp_group_class_init (EmpathyTpGroupClass *klass);
-static void empathy_tp_group_init       (EmpathyTpGroup      *group);
+} EmpathyTpGroupPriv;
 
 enum {
        MEMBER_ADDED,
@@ -65,8 +60,6 @@ enum {
 
 enum {
        PROP_0,
-       PROP_ACCOUNT,
-       PROP_TP_CHAN,
        PROP_CHANNEL,
        PROP_READY
 };
@@ -211,18 +204,17 @@ tp_group_update_members (EmpathyTpGroup *group,
 
        actor_contact = tp_group_get_contact (group, actor);
 
-       empathy_debug (DEBUG_DOMAIN, "Members changed for list %s:\n"
-                                    "  added-len=%d, current-len=%d\n"
-                                    "  removed-len=%d\n"
-                                    "  local-pending-len=%d, current-len=%d\n"
-                                    "  remote-pending-len=%d, current-len=%d",
-                      empathy_tp_group_get_name (group),
-                      added ? added->len : 0, g_list_length (priv->members),
-                      removed ? removed->len : 0,
-                      local_pending ? local_pending->len : 0,
-                      g_list_length (priv->local_pendings),
-                      remote_pending ? remote_pending->len : 0,
-                      g_list_length (priv->remote_pendings));
+       DEBUG ("Members changed for list %s:\n"
+               "  added-len=%d, current-len=%d\n"
+               "  removed-len=%d\n"
+               "  local-pending-len=%d, current-len=%d\n"
+               "  remote-pending-len=%d, current-len=%d",
+               priv->group_name, added ? added->len : 0,
+               g_list_length (priv->members), removed ? removed->len : 0,
+               local_pending ? local_pending->len : 0,
+               g_list_length (priv->local_pendings),
+               remote_pending ? remote_pending->len : 0,
+               g_list_length (priv->remote_pendings));
 
        /* Contacts added */
        contacts = tp_group_get_contacts (group, added);
@@ -294,14 +286,13 @@ tp_group_update_members (EmpathyTpGroup *group,
                g_object_unref (actor_contact);
        }
 
-       empathy_debug (DEBUG_DOMAIN, "Members changed done for list %s:\n"
-                                    "  members-len=%d\n"
-                                    "  local-pendings-len=%d\n"
-                                    "  remote-pendings-len=%d",
-                      empathy_tp_group_get_name (group),
-                      g_list_length (priv->members),
-                      g_list_length (priv->local_pendings),
-                      g_list_length (priv->remote_pendings));
+       DEBUG ("Members changed done for list %s:\n"
+               "  members-len=%d\n"
+               "  local-pendings-len=%d\n"
+               "  remote-pendings-len=%d",
+               priv->group_name, g_list_length (priv->members),
+               g_list_length (priv->local_pendings),
+               g_list_length (priv->remote_pendings));
 }
 
 static void
@@ -336,8 +327,7 @@ tp_group_get_members_cb (TpChannel    *channel,
        EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
        if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Failed to get members: %s",
-                              error->message);
+               DEBUG ("Failed to get members: %s", error->message);
                return;
        }
 
@@ -350,7 +340,7 @@ tp_group_get_members_cb (TpChannel    *channel,
                                 0,       /* actor */
                                 0);      /* reason */
 
-       empathy_debug (DEBUG_DOMAIN, "Ready");
+       DEBUG ("Ready");
        priv->ready = TRUE;
        g_object_notify (group, "ready");
 }
@@ -366,8 +356,7 @@ tp_group_get_local_pending_cb (TpChannel        *channel,
        guint   i = 0;
        
        if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Failed to get local pendings: %s",
-                              error->message);
+               DEBUG ("Failed to get local pendings: %s", error->message);
                return;
        }
 
@@ -408,8 +397,7 @@ tp_group_get_remote_pending_cb (TpChannel    *channel,
                                GObject      *group)
 {
        if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Failed to get remote pendings: %s",
-                              error->message);
+               DEBUG ("Failed to get remote pendings: %s", error->message);
                return;
        }
 
@@ -423,6 +411,23 @@ tp_group_get_remote_pending_cb (TpChannel    *channel,
                                 0);      /* reason */
 }
 
+static void
+tp_group_inspect_handles_cb (TpConnection  *connection,
+                            const gchar  **names,
+                            const GError  *error,
+                            gpointer       user_data,
+                            GObject       *group)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+       if (error) {
+               DEBUG ("Failed to inspect channel handle: %s", error->message);
+               return;
+       }
+
+       priv->group_name = g_strdup (*names);
+}
+
 static void
 tp_group_invalidated_cb (TpProxy        *proxy,
                         guint           domain,
@@ -430,7 +435,7 @@ tp_group_invalidated_cb (TpProxy        *proxy,
                         gchar          *message,
                         EmpathyTpGroup *group)
 {
-       empathy_debug (DEBUG_DOMAIN, "Channel invalidated: %s", message);
+       DEBUG ("Channel invalidated: %s", message);
        g_signal_emit (group, signals[DESTROY], 0);
 }
 
@@ -442,20 +447,39 @@ tp_group_get_self_handle_cb (TpChannel    *proxy,
                             GObject      *group)
 {
        EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       TpConnection       *connection;
+       guint               channel_handle;
+       guint               channel_handle_type;
+       GArray             *handles;
 
        if (error) {
-               empathy_debug (DEBUG_DOMAIN, "Failed to get self handle: %s",
-                              error->message);
+               DEBUG ("Failed to get self handle: %s", error->message);
                return;
        }
 
-       /* GetMembers is called last, so it will be the last to get the reply,
-        * so we'll be ready once that call return. */
        priv->self_handle = handle;
        tp_cli_channel_interface_group_connect_to_members_changed (priv->channel,
                                                                   tp_group_members_changed_cb,
                                                                   NULL, NULL,
                                                                   group, NULL);
+
+       /* GetMembers is called last, so it will be the last to get the reply,
+        * so we'll be ready once that call return. */
+       g_object_get (priv->channel,
+                     "connection", &connection,
+                     "handle-type", &channel_handle_type,
+                     "handle", &channel_handle,
+                     NULL);
+       handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
+       g_array_prepend_val (handles, channel_handle);
+       tp_cli_connection_call_inspect_handles (connection, -1,
+                                               channel_handle_type,
+                                               handles,
+                                               tp_group_inspect_handles_cb,
+                                               NULL, NULL,
+                                               group);
+       g_array_free (handles, TRUE);
+
        tp_cli_channel_interface_group_call_get_local_pending_members_with_info
                                                        (priv->channel, -1,
                                                         tp_group_get_local_pending_cb,
@@ -509,14 +533,11 @@ tp_group_finalize (GObject *object)
        EmpathyTpGroupPriv      *priv = GET_PRIV (object);
        EmpathyTpContactFactory *tp_factory;
 
-       empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
+       DEBUG ("finalize: %p", object);
 
        tp_factory = empathy_contact_factory_get_tp_factory (priv->factory, priv->account);
        g_signal_handlers_disconnect_by_func (tp_factory, tp_group_factory_ready_cb, object);
 
-       if (priv->tp_chan) {
-               g_object_unref (priv->tp_chan);
-       }
        if (priv->channel) {
                g_signal_handlers_disconnect_by_func (priv->channel,
                                                      tp_group_invalidated_cb,
@@ -546,12 +567,11 @@ tp_group_finalize (GObject *object)
 static void
 tp_group_constructed (GObject *group)
 {
-       EmpathyTpGroupPriv      *priv = GET_PRIV (group);
-       gboolean                 channel_ready;
-
-       G_OBJECT_CLASS (empathy_tp_group_parent_class)->constructed (group);
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       gboolean            channel_ready;
 
-       priv->factory = empathy_contact_factory_new ();
+       priv->factory = empathy_contact_factory_dup_singleton ();
+       priv->account = empathy_channel_get_account (priv->channel);
 
        g_signal_connect (priv->channel, "invalidated",
                          G_CALLBACK (tp_group_invalidated_cb),
@@ -576,15 +596,12 @@ tp_group_get_property (GObject    *object,
        EmpathyTpGroupPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               g_value_set_object (value, priv->account);
-               break;
-       case PROP_TP_CHAN:
-               g_value_set_object (value, priv->tp_chan);
-               break;
        case PROP_CHANNEL:
                g_value_set_object (value, priv->channel);
                break;
+       case PROP_READY:
+               g_value_set_boolean (value, priv->ready);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -600,12 +617,6 @@ tp_group_set_property (GObject      *object,
        EmpathyTpGroupPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
-       case PROP_ACCOUNT:
-               priv->account = g_object_ref (g_value_get_object (value));
-               break;
-       case PROP_TP_CHAN:
-               priv->tp_chan = g_object_ref (g_value_get_object (value));
-               break;
        case PROP_CHANNEL:
                priv->channel = g_object_ref (g_value_get_object (value));
                break;
@@ -625,22 +636,6 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
        object_class->get_property = tp_group_get_property;
        object_class->set_property = tp_group_set_property;
 
-       g_object_class_install_property (object_class,
-                                        PROP_ACCOUNT,
-                                        g_param_spec_object ("account",
-                                                             "channel Account",
-                                                             "The account associated with the channel",
-                                                             MC_TYPE_ACCOUNT,
-                                                             G_PARAM_READWRITE |
-                                                             G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (object_class,
-                                        PROP_TP_CHAN,
-                                        g_param_spec_object ("tp-chan",
-                                                             "telepathy channel",
-                                                             "The old TpChan",
-                                                             TELEPATHY_CHAN_TYPE,
-                                                             G_PARAM_READWRITE |
-                                                             G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (object_class,
                                         PROP_CHANNEL,
                                         g_param_spec_object ("channel",
@@ -713,35 +708,20 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
 static void
 empathy_tp_group_init (EmpathyTpGroup *group)
 {
+       EmpathyTpGroupPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
+               EMPATHY_TYPE_TP_GROUP, EmpathyTpGroupPriv);
+
+       group->priv = priv;
 }
 
 EmpathyTpGroup *
-empathy_tp_group_new (McAccount *account,
-                     TpChan    *tp_chan)
+empathy_tp_group_new (TpChannel *channel)
 {
-       EmpathyTpGroup  *group;
-       TpChannel       *channel;
-       TpConnection    *connection;
-       MissionControl  *mc;
-
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-       g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
-
-       mc = empathy_mission_control_new ();
-       connection = mission_control_get_tpconnection (mc, account, NULL);
-       channel = tp_chan_dup_channel (tp_chan, connection, NULL);
-
-       group = g_object_new (EMPATHY_TYPE_TP_GROUP, 
-                             "account", account,
-                             "channel", channel,
-                             "tp-chan", tp_chan,
-                             NULL);
+       g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
 
-       g_object_unref (channel);
-       g_object_unref (connection);
-       g_object_unref (mc);
-
-       return group;
+       return g_object_new (EMPATHY_TYPE_TP_GROUP, 
+                            "channel", channel,
+                            NULL);
 }
 
 static void
@@ -750,10 +730,8 @@ tp_group_async_cb (TpChannel    *channel,
                   gpointer      user_data,
                   GObject      *weak_object)
 {
-       const gchar *msg = user_data;
-
        if (error) {
-               empathy_debug (DEBUG_DOMAIN, "%s: %s", msg, error->message);
+               DEBUG ("%s: %s", (gchar*) user_data, error->message);
        }
 }
 
@@ -908,16 +886,10 @@ empathy_tp_group_get_remote_pendings (EmpathyTpGroup *group)
 const gchar *
 empathy_tp_group_get_name (EmpathyTpGroup *group)
 {
-       EmpathyTpGroupPriv *priv;
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
        g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
-       priv = GET_PRIV (group);
-
-       /* Lazy initialisation */
-       if (!priv->group_name && priv->tp_chan->handle != 0) {
-               priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
-       }
+       g_return_val_if_fail (priv->ready, NULL);
 
        return priv->group_name;
 }
@@ -933,39 +905,77 @@ empathy_tp_group_get_self_contact (EmpathyTpGroup *group)
        return tp_group_get_contact (group, priv->self_handle);
 }
 
-const gchar *
-empathy_tp_group_get_object_path (EmpathyTpGroup *group)
+gboolean
+empathy_tp_group_is_member (EmpathyTpGroup *group,
+                           EmpathyContact *contact)
 {
-       EmpathyTpGroupPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
-       priv = GET_PRIV (group);
+       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
 
-       return TP_PROXY (priv->channel)->object_path;
+       return g_list_find (priv->members, contact) != NULL;
 }
 
-TpChan *
-empathy_tp_group_get_channel (EmpathyTpGroup *group)
+gboolean
+empathy_tp_group_is_ready (EmpathyTpGroup *group)
 {
-       EmpathyTpGroupPriv *priv;
-
-       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
+       EmpathyTpGroupPriv *priv = GET_PRIV (group);
 
-       priv = GET_PRIV (group);
+       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
 
-       return priv->tp_chan;
+       return priv->ready;
 }
 
-gboolean
-empathy_tp_group_is_member (EmpathyTpGroup *group,
-                           EmpathyContact *contact)
+EmpathyPendingInfo *
+empathy_tp_group_get_invitation (EmpathyTpGroup  *group,
+                                EmpathyContact **remote_contact)
 {
        EmpathyTpGroupPriv *priv = GET_PRIV (group);
+       EmpathyContact     *contact = NULL;
+       EmpathyPendingInfo *invitation = NULL;
+       GList              *l;
 
        g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), FALSE);
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
+       g_return_val_if_fail (priv->ready, NULL);
 
-       return g_list_find (priv->members, contact) != NULL;
+       for (l = priv->local_pendings; l; l = l->next) {
+               EmpathyPendingInfo *info = l->data;
+
+               if (empathy_contact_is_user (info->member)) {
+                       invitation = info;
+                       break;
+               }
+       }
+
+       if (invitation) {
+               contact = invitation->actor;
+       }
+       if (!invitation) {
+               if (priv->remote_pendings) {
+                       contact = priv->remote_pendings->data;
+               }
+               else if (priv->members) {
+                       contact = priv->members->data;
+               }
+       }
+
+       if (remote_contact && contact) {
+               *remote_contact = g_object_ref (contact);
+       }
+
+       return invitation;
 }
 
+TpChannelGroupFlags
+empathy_tp_group_get_flags (EmpathyTpGroup *self)
+{
+       EmpathyTpGroupPriv *priv = GET_PRIV (self);
+
+       g_return_val_if_fail (EMPATHY_IS_TP_GROUP (self), 0);
+
+       if (priv->channel == NULL)
+               return 0;
+
+       return tp_channel_group_get_flags (priv->channel);
+}