]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-contact.c
Merge branch 'folks-async-and-prepare'
[empathy.git] / libempathy / empathy-contact.c
index bd8a63efafe5aa332c2d349bccc7ec3c57938e70..6842cde09d8078f60afd055236836eabf5d551bb 100644 (file)
@@ -28,9 +28,9 @@
 #include <telepathy-glib/account-manager.h>
 #include <telepathy-glib/interfaces.h>
 #include <telepathy-glib/util.h>
-#ifdef ENABEL_TPL
-#include <telepathy-logger/contact.h>
-#endif /* ENABLE_TPL */
+
+#include <folks/folks.h>
+#include <folks/folks-telepathy.h>
 
 #if HAVE_GEOCLUE
 #include <geoclue/geoclue-geocode.h>
 typedef struct {
   TpContact *tp_contact;
   TpAccount *account;
+  FolksPersona *persona;
   gchar *id;
-  gchar *name;
+  gchar *alias;
   EmpathyAvatar *avatar;
   TpConnectionPresenceType presence;
-  gchar *presence_message;
   guint handle;
   EmpathyCapabilities capabilities;
   gboolean is_user;
@@ -66,6 +66,7 @@ typedef struct {
    * more fields by searching the address using geoclue.
    */
   GHashTable *location;
+  GHashTable *groups;
 } EmpathyContactPriv;
 
 static void contact_finalize (GObject *object);
@@ -93,8 +94,9 @@ enum
   PROP_0,
   PROP_TP_CONTACT,
   PROP_ACCOUNT,
+  PROP_PERSONA,
   PROP_ID,
-  PROP_NAME,
+  PROP_ALIAS,
   PROP_AVATAR,
   PROP_PRESENCE,
   PROP_PRESENCE_MESSAGE,
@@ -123,7 +125,7 @@ tp_contact_notify_cb (TpContact *tp_contact,
 
   /* Forward property notifications */
   if (!tp_strdiff (param->name, "alias"))
-    g_object_notify (contact, "name");
+    g_object_notify (contact, "alias");
   else if (!tp_strdiff (param->name, "presence-type")) {
     TpConnectionPresenceType presence;
 
@@ -133,8 +135,6 @@ tp_contact_notify_cb (TpContact *tp_contact,
     priv->presence = presence;
     g_object_notify (contact, "presence");
   }
-  else if (!tp_strdiff (param->name, "presence-message"))
-    g_object_notify (contact, "presence-message");
   else if (!tp_strdiff (param->name, "identifier"))
     g_object_notify (contact, "id");
   else if (!tp_strdiff (param->name, "handle"))
@@ -158,6 +158,15 @@ tp_contact_notify_cb (TpContact *tp_contact,
     }
 }
 
+static void
+folks_persona_notify_cb (FolksPersona *folks_persona,
+                         GParamSpec *param,
+                         GObject *contact)
+{
+  if (!tp_strdiff (param->name, "presence-message"))
+    g_object_notify (contact, "presence-message");
+}
+
 static void
 contact_dispose (GObject *object)
 {
@@ -176,6 +185,14 @@ contact_dispose (GObject *object)
     g_object_unref (priv->account);
   priv->account = NULL;
 
+  if (priv->persona)
+    {
+      g_signal_handlers_disconnect_by_func (priv->persona,
+          folks_persona_notify_cb, object);
+      g_object_unref (priv->persona);
+    }
+  priv->persona = NULL;
+
   if (priv->avatar != NULL)
     {
       empathy_avatar_unref (priv->avatar);
@@ -219,6 +236,14 @@ empathy_contact_class_init (EmpathyContactClass *class)
         TP_TYPE_ACCOUNT,
         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class,
+      PROP_PERSONA,
+      g_param_spec_object ("persona",
+        "Persona",
+        "The FolksPersona associated with the contact",
+        FOLKS_TYPE_PERSONA,
+        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (object_class,
       PROP_ID,
       g_param_spec_string ("id",
@@ -228,10 +253,10 @@ empathy_contact_class_init (EmpathyContactClass *class)
         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
-      PROP_NAME,
-      g_param_spec_string ("name",
-        "Contact Name",
-        "The name of the contact",
+      PROP_ALIAS,
+      g_param_spec_string ("alias",
+        "Contact alias",
+        "An alias for the contact",
         NULL,
         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
@@ -320,6 +345,7 @@ empathy_contact_init (EmpathyContact *contact)
   contact->priv = priv;
 
   priv->location = NULL;
+  priv->groups = NULL;
 }
 
 static void
@@ -331,9 +357,10 @@ contact_finalize (GObject *object)
 
   DEBUG ("finalize: %p", object);
 
-  g_free (priv->name);
+  if (priv->groups != NULL)
+    g_hash_table_destroy (priv->groups);
+  g_free (priv->alias);
   g_free (priv->id);
-  g_free (priv->presence_message);
 
   G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
 }
@@ -391,11 +418,14 @@ contact_get_property (GObject *object,
       case PROP_ACCOUNT:
         g_value_set_object (value, empathy_contact_get_account (contact));
         break;
+      case PROP_PERSONA:
+        g_value_set_object (value, empathy_contact_get_persona (contact));
+        break;
       case PROP_ID:
         g_value_set_string (value, empathy_contact_get_id (contact));
         break;
-      case PROP_NAME:
-        g_value_set_string (value, empathy_contact_get_name (contact));
+      case PROP_ALIAS:
+        g_value_set_string (value, empathy_contact_get_alias (contact));
         break;
       case PROP_AVATAR:
         g_value_set_boxed (value, empathy_contact_get_avatar (contact));
@@ -439,11 +469,14 @@ contact_set_property (GObject *object,
         g_assert (priv->account == NULL);
         priv->account = g_value_dup_object (value);
         break;
+      case PROP_PERSONA:
+        empathy_contact_set_persona (contact, g_value_get_object (value));
+        break;
       case PROP_ID:
         empathy_contact_set_id (contact, g_value_get_string (value));
         break;
-      case PROP_NAME:
-        empathy_contact_set_name (contact, g_value_get_string (value));
+      case PROP_ALIAS:
+        empathy_contact_set_alias (contact, g_value_get_string (value));
         break;
       case PROP_AVATAR:
         empathy_contact_set_avatar (contact, g_value_get_boxed (value));
@@ -479,37 +512,35 @@ empathy_contact_new (TpContact *tp_contact)
       NULL);
 }
 
-#ifdef ENABLE_TPL
 EmpathyContact *
 empathy_contact_from_tpl_contact (TpAccount *account,
-    TplContact *tpl_contact)
+    TplEntity *tpl_entity)
 {
   EmpathyContact *retval;
   gboolean is_user;
 
-  g_return_val_if_fail (TPL_IS_CONTACT (tpl_contact), NULL);
+  g_return_val_if_fail (TPL_IS_ENTITY (tpl_entity), NULL);
 
-  is_user = (TPL_CONTACT_USER == tpl_contact_get_contact_type (tpl_contact));
+  is_user = (TPL_ENTITY_SELF == tpl_entity_get_entity_type (tpl_entity));
 
   retval = g_object_new (EMPATHY_TYPE_CONTACT,
-      "id", tpl_contact_get_alias (tpl_contact),
-      "name", tpl_contact_get_identifier (tpl_contact),
+      "id", tpl_entity_get_alias (tpl_entity),
+      "alias", tpl_entity_get_identifier (tpl_entity),
       "account", account,
       "is-user", is_user,
       NULL);
 
-  if (!EMP_STR_EMPTY (tpl_contact_get_avatar_token (tpl_contact)))
+  if (!EMP_STR_EMPTY (tpl_entity_get_avatar_token (tpl_entity)))
     empathy_contact_load_avatar_cache (retval,
-        tpl_contact_get_avatar_token (tpl_contact));
+        tpl_entity_get_avatar_token (tpl_entity));
 
   return retval;
 }
-#endif /* ENABLE_TPL */
 
 EmpathyContact *
 empathy_contact_new_for_log (TpAccount *account,
                              const gchar *id,
-                             const gchar *name,
+                             const gchar *alias,
                              gboolean is_user)
 {
   g_return_val_if_fail (id != NULL, NULL);
@@ -518,7 +549,7 @@ empathy_contact_new_for_log (TpAccount *account,
   return g_object_new (EMPATHY_TYPE_CONTACT,
       "account", account,
       "id", id,
-      "name", name,
+      "alias", alias,
       "is-user", is_user,
       NULL);
 }
@@ -570,15 +601,15 @@ empathy_contact_set_id (EmpathyContact *contact,
       priv->id = g_strdup (id);
 
       g_object_notify (G_OBJECT (contact), "id");
-      if (EMP_STR_EMPTY (priv->name))
-          g_object_notify (G_OBJECT (contact), "name");
+      if (EMP_STR_EMPTY (priv->alias))
+          g_object_notify (G_OBJECT (contact), "alias");
     }
 
   g_object_unref (contact);
 }
 
 const gchar *
-empathy_contact_get_name (EmpathyContact *contact)
+empathy_contact_get_alias (EmpathyContact *contact)
 {
   EmpathyContactPriv *priv;
   const gchar        *alias;
@@ -590,7 +621,7 @@ empathy_contact_get_name (EmpathyContact *contact)
   if (priv->tp_contact != NULL)
     alias = tp_contact_get_alias (priv->tp_contact);
   else
-    alias = priv->name;
+    alias = priv->alias;
 
   if (!EMP_STR_EMPTY (alias))
     return alias;
@@ -599,61 +630,86 @@ empathy_contact_get_name (EmpathyContact *contact)
 }
 
 void
-empathy_contact_set_name (EmpathyContact *contact,
-                          const gchar *name)
+empathy_contact_set_alias (EmpathyContact *contact,
+                          const gchar *alias)
 {
   EmpathyContactPriv *priv;
+  FolksPersona *persona;
 
   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
   priv = GET_PRIV (contact);
 
   g_object_ref (contact);
-  if (tp_strdiff (name, priv->name))
+
+  /* Set the alias on the persona if possible */
+  persona = empathy_contact_get_persona (contact);
+  if (persona != NULL && FOLKS_IS_ALIAS (persona))
+    {
+      DEBUG ("Setting alias for contact %s to %s",
+          empathy_contact_get_id (contact), alias);
+
+      folks_alias_set_alias (FOLKS_ALIAS (persona), alias);
+    }
+
+  if (tp_strdiff (alias, priv->alias))
     {
-      g_free (priv->name);
-      priv->name = g_strdup (name);
-      g_object_notify (G_OBJECT (contact), "name");
+      g_free (priv->alias);
+      priv->alias = g_strdup (alias);
+      g_object_notify (G_OBJECT (contact), "alias");
     }
+
   g_object_unref (contact);
 }
 
 static void
-contact_set_aliases_cb (TpConnection *connection,
-    const GError *error,
-    gpointer user_data,
-    GObject *weak_object)
+groups_change_group_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
 {
-       if (error)
-               DEBUG ("Error: %s", error->message);
+  FolksGroups *groups = FOLKS_GROUPS (source);
+  GError *error = NULL;
+
+  folks_groups_change_group_finish (groups, result, &error);
+  if (error != NULL)
+    {
+      g_warning ("failed to change group: %s", error->message);
+      g_clear_error (&error);
+    }
 }
 
 void
-empathy_contact_set_alias (EmpathyContact *contact,
-    const gchar *alias)
+empathy_contact_change_group (EmpathyContact *contact, const gchar *group,
+    gboolean is_member)
 {
-       TpConnection *connection;
-       GHashTable *new_alias;
-       guint handle;
-
-       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
-       handle = empathy_contact_get_handle (contact);
+  EmpathyContactPriv *priv;
+  FolksPersona *persona;
 
-       DEBUG ("Setting alias for contact %s (%d) to %s",
-               empathy_contact_get_id (contact),
-               handle, alias);
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+  g_return_if_fail (group != NULL);
 
-       new_alias = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-           g_free);
+  priv = GET_PRIV (contact);
 
-       g_hash_table_insert (new_alias, GUINT_TO_POINTER (handle), g_strdup (alias));
+  /* Normally pass through the changes to the persona */
+  persona = empathy_contact_get_persona (contact);
+  if (persona != NULL)
+    {
+      if (FOLKS_IS_GROUPS (persona))
+        folks_groups_change_group (FOLKS_GROUPS (persona), group, is_member,
+          groups_change_group_cb, contact);
+      return;
+    }
 
-       connection = empathy_contact_get_connection (contact);
-       tp_cli_connection_interface_aliasing_call_set_aliases (connection, -1,
-           new_alias, contact_set_aliases_cb, NULL, NULL, NULL);
+  /* If the persona doesn't exist yet, we have to cache the changes until it
+   * does */
+  if (priv->groups == NULL)
+    {
+      priv->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+          NULL);
+    }
 
-       g_hash_table_destroy (new_alias);
+  g_hash_table_insert (priv->groups, g_strdup (group),
+      GUINT_TO_POINTER (is_member));
 }
 
 EmpathyAvatar *
@@ -715,6 +771,94 @@ empathy_contact_get_account (EmpathyContact *contact)
   return priv->account;
 }
 
+FolksPersona *
+empathy_contact_get_persona (EmpathyContact *contact)
+{
+  EmpathyContactPriv *priv;
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  priv = GET_PRIV (contact);
+
+  if (priv->persona == NULL && priv->tp_contact != NULL)
+    {
+      /* FIXME: This is disgustingly slow */
+      /* Query for the persona */
+      EmpathyIndividualManager *manager;
+      GList *individuals, *l;
+
+      manager = empathy_individual_manager_dup_singleton ();
+      individuals = empathy_individual_manager_get_members (manager);
+
+      for (l = individuals; l != NULL; l = l->next)
+        {
+          GList *personas, *j;
+          FolksIndividual *individual = FOLKS_INDIVIDUAL (l->data);
+
+          personas = folks_individual_get_personas (individual);
+          for (j = personas; j != NULL; j = j->next)
+            {
+              TpfPersona *persona = j->data;
+
+              if (TPF_IS_PERSONA (persona))
+                {
+                  TpContact *tp_contact = tpf_persona_get_contact (persona);
+
+                  if (tp_contact == priv->tp_contact)
+                    {
+                      /* Found the right persona */
+                      priv->persona = g_object_ref (persona);
+                      goto finished;
+                    }
+                }
+            }
+        }
+
+finished:
+      g_list_free (individuals);
+      g_object_unref (manager);
+    }
+
+  return priv->persona;
+}
+
+void
+empathy_contact_set_persona (EmpathyContact *contact,
+    FolksPersona *persona)
+{
+  EmpathyContactPriv *priv;
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+  g_return_if_fail (TPF_IS_PERSONA (persona));
+
+  priv = GET_PRIV (contact);
+
+  if (persona == priv->persona)
+    return;
+
+  if (priv->persona != NULL)
+    g_object_unref (priv->persona);
+  priv->persona = g_object_ref (persona);
+
+  g_signal_connect (priv->persona, "notify",
+    G_CALLBACK (folks_persona_notify_cb), contact);
+
+  g_object_notify (G_OBJECT (contact), "persona");
+
+  /* Set the persona's alias, since ours could've been set using
+   * empathy_contact_set_alias() before we had a persona; this happens when
+   * adding a contact. */
+  empathy_contact_set_alias (contact, priv->alias);
+
+  /* Set the persona's groups */
+  if (priv->groups != NULL)
+    {
+      folks_groups_set_groups (FOLKS_GROUPS (persona), priv->groups);
+      g_hash_table_destroy (priv->groups);
+      priv->groups = NULL;
+    }
+}
+
 TpConnection *
 empathy_contact_get_connection (EmpathyContact *contact)
 {
@@ -777,10 +921,10 @@ empathy_contact_get_presence_message (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
-  if (priv->tp_contact != NULL)
-    return tp_contact_get_presence_message (priv->tp_contact);
+  if (priv->persona != NULL)
+    return folks_presence_get_presence_message (FOLKS_PRESENCE (priv->persona));
 
-  return priv->presence_message;
+  return NULL;
 }
 
 void
@@ -791,13 +935,11 @@ empathy_contact_set_presence_message (EmpathyContact *contact,
 
   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
-  if (!tp_strdiff (message, priv->presence_message))
-    return;
-
-  g_free (priv->presence_message);
-  priv->presence_message = g_strdup (message);
-
-  g_object_notify (G_OBJECT (contact), "presence-message");
+  if (priv->persona != NULL)
+    {
+      folks_presence_set_presence_message (FOLKS_PRESENCE (priv->persona),
+          message);
+    }
 }
 
 guint
@@ -975,7 +1117,7 @@ empathy_contact_can_send_files (EmpathyContact *contact)
 }
 
 gboolean
-empathy_contact_can_use_stream_tube (EmpathyContact *contact)
+empathy_contact_can_use_rfb_stream_tube (EmpathyContact *contact)
 {
   EmpathyContactPriv *priv;
 
@@ -983,7 +1125,7 @@ empathy_contact_can_use_stream_tube (EmpathyContact *contact)
 
   priv = GET_PRIV (contact);
 
-  return priv->capabilities & EMPATHY_CAPABILITIES_STREAM_TUBE;
+  return priv->capabilities & EMPATHY_CAPABILITIES_RFB_STREAM_TUBE;
 }
 
 static gchar *
@@ -1117,6 +1259,7 @@ empathy_avatar_unref (EmpathyAvatar *avatar)
       g_free (avatar->data);
       g_free (avatar->format);
       g_free (avatar->token);
+      g_free (avatar->filename);
       g_slice_free (EmpathyAvatar, avatar);
     }
 }
@@ -1453,7 +1596,13 @@ tp_caps_to_capabilities (TpCapabilities *caps)
         }
       else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
         {
-          capabilities |= EMPATHY_CAPABILITIES_STREAM_TUBE;
+          const gchar *service;
+
+          service = tp_asv_get_string (fixed_prop,
+              TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
+
+          if (!tp_strdiff (service, "rfb"))
+            capabilities |= EMPATHY_CAPABILITIES_RFB_STREAM_TUBE;
         }
       else if (!tp_strdiff (chan_type,
         TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))