]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-utils.c
improve TP_ERROR_STR_ALREADY_CONNECTED displayed error string
[empathy.git] / libempathy / empathy-utils.c
index 5f9178a55b70d8554f27eea75c3530a88009a3f7..8e3509b025f9cc71ecde40017c61f4e711e6e013 100644 (file)
 #include <folks/folks.h>
 #include <folks/folks-telepathy.h>
 
+#include <dbus/dbus-protocol.h>
+
 #include <telepathy-glib/account-manager.h>
 #include <telepathy-glib/connection.h>
 #include <telepathy-glib/channel.h>
 #include <telepathy-glib/dbus.h>
 #include <telepathy-glib/util.h>
 
+#include "empathy-client-factory.h"
 #include "empathy-utils.h"
-#include "empathy-contact-manager.h"
 #include "empathy-individual-manager.h"
 #include "empathy-presence-manager.h"
 #include "empathy-request-util.h"
@@ -79,10 +81,22 @@ static struct {
   { NULL, },
 };
 
+static gboolean
+properties_contains (gchar **list,
+                    gint length,
+                    const gchar *property);
+
+static gboolean
+check_writeable_property (TpConnection *connection,
+                         FolksIndividual *individual,
+                         gchar *property);
+
 void
 empathy_init (void)
 {
   static gboolean initialized = FALSE;
+  TpAccountManager *am;
+  EmpathyClientFactory *factory;
 
   if (initialized)
     return;
@@ -103,6 +117,13 @@ empathy_init (void)
   emp_cli_init ();
 
   initialized = TRUE;
+
+  factory = empathy_client_factory_dup ();
+  am = tp_account_manager_new_with_factory (TP_SIMPLE_CLIENT_FACTORY (factory));
+  tp_account_manager_set_default (am);
+
+  g_object_unref (factory);
+  g_object_unref (am);
 }
 
 gboolean
@@ -331,7 +352,7 @@ create_errors_to_message_hash (void)
   g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_LOST,
     _("Connection has been lost"));
   g_hash_table_insert (errors, TP_ERROR_STR_ALREADY_CONNECTED,
-    _("This resource is already connected to the server"));
+    _("This account is already connected to the server"));
   g_hash_table_insert (errors, TP_ERROR_STR_CONNECTION_REPLACED,
     _("Connection has been replaced by a new connection using the "
     "same resource"));
@@ -348,6 +369,10 @@ create_errors_to_message_hash (void)
     _("The length of the server certificate, or the depth of the "
     "server certificate chain, exceed the limits imposed by the "
     "cryptography library"));
+  g_hash_table_insert (errors, TP_ERROR_STR_SOFTWARE_UPGRADE_REQUIRED,
+    _("Your software is too old"));
+  g_hash_table_insert (errors, DBUS_ERROR_NO_REPLY,
+    _("Internal error"));
 
   return errors;
 }
@@ -372,7 +397,7 @@ empathy_account_get_error_message (TpAccount *account,
 {
   const gchar *dbus_error;
   const gchar *message;
-        const GHashTable *details = NULL;
+  const GHashTable *details = NULL;
   TpConnectionStatusReason reason;
 
   dbus_error = tp_account_get_detailed_error (account, &details);
@@ -389,11 +414,11 @@ empathy_account_get_error_message (TpAccount *account,
   if (message != NULL)
     return message;
 
+  tp_account_get_connection_status (account, &reason);
+
   DEBUG ("Don't understand error '%s'; fallback to the status reason (%u)",
     dbus_error, reason);
 
-  tp_account_get_connection_status (account, &reason);
-
   return empathy_status_reason_get_default_message (reason);
 }
 
@@ -559,36 +584,6 @@ empathy_service_name_to_display_name (const gchar *service_name)
   return service_name;
 }
 
-/* Note: this function depends on the account manager having its core feature
- * prepared. */
-TpAccount *
-empathy_get_account_for_connection (TpConnection *connection)
-{
-  TpAccountManager *manager;
-  TpAccount *account = NULL;
-  GList *accounts, *l;
-
-  manager = tp_account_manager_dup ();
-
-  accounts = tp_account_manager_get_valid_accounts (manager);
-
-  for (l = accounts; l != NULL; l = l->next)
-    {
-      TpAccount *a = l->data;
-
-      if (tp_account_get_connection (a) == connection)
-        {
-          account = a;
-          break;
-        }
-    }
-
-  g_list_free (accounts);
-  g_object_unref (manager);
-
-  return account;
-}
-
 gboolean
 empathy_account_manager_get_accounts_connected (gboolean *connecting)
 {
@@ -735,13 +730,22 @@ empathy_contact_dup_from_folks_individual (FolksIndividual *individual)
           TpContact *tp_contact;
 
           tp_contact = tpf_persona_get_contact (persona);
-          contact = empathy_contact_dup_from_tp_contact (tp_contact);
-          empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
+          if (tp_contact != NULL)
+            {
+              contact = empathy_contact_dup_from_tp_contact (tp_contact);
+              empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
+            }
         }
       g_clear_object (&persona);
     }
   g_clear_object (&iter);
 
+  if (contact == NULL)
+    {
+      DEBUG ("Can't create an EmpathyContact for Individual %s",
+          folks_individual_get_id (individual));
+    }
+
   return contact;
 }
 
@@ -797,6 +801,10 @@ empathy_connection_can_add_personas (TpConnection *connection)
 
   g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
 
+  if (tp_connection_get_status (connection, NULL) !=
+          TP_CONNECTION_STATUS_CONNECTED)
+      return FALSE;
+
   persona_store = FOLKS_PERSONA_STORE (
       empathy_dup_persona_store_for_connection (connection));
 
@@ -809,39 +817,35 @@ empathy_connection_can_add_personas (TpConnection *connection)
 }
 
 gboolean
-empathy_connection_can_alias_personas (TpConnection *connection)
+empathy_connection_can_alias_personas (TpConnection *connection,
+                                      FolksIndividual *individual)
 {
   gboolean retval;
-  FolksPersonaStore *persona_store;
 
   g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
 
-  persona_store = FOLKS_PERSONA_STORE (
-      empathy_dup_persona_store_for_connection (connection));
-
-  retval = (folks_persona_store_get_can_alias_personas (persona_store) ==
-      FOLKS_MAYBE_BOOL_TRUE);
+  if (tp_connection_get_status (connection, NULL) !=
+          TP_CONNECTION_STATUS_CONNECTED)
+      return FALSE;
 
-  g_clear_object (&persona_store);
+  retval = check_writeable_property (connection, individual, "alias");
 
   return retval;
 }
 
 gboolean
-empathy_connection_can_group_personas (TpConnection *connection)
+empathy_connection_can_group_personas (TpConnection *connection,
+                                      FolksIndividual *individual)
 {
   gboolean retval;
-  FolksPersonaStore *persona_store;
 
   g_return_val_if_fail (TP_IS_CONNECTION (connection), FALSE);
 
-  persona_store = FOLKS_PERSONA_STORE (
-      empathy_dup_persona_store_for_connection (connection));
-
-  retval = (folks_persona_store_get_can_group_personas (persona_store) ==
-      FOLKS_MAYBE_BOOL_TRUE);
+  if (tp_connection_get_status (connection, NULL) !=
+          TP_CONNECTION_STATUS_CONNECTED)
+      return FALSE;
 
-  g_clear_object (&persona_store);
+  retval = check_writeable_property (connection, individual, "groups");
 
   return retval;
 }
@@ -972,3 +976,222 @@ empathy_format_currency (gint amount,
 
   return money;
 }
+
+gboolean
+empathy_account_has_uri_scheme_tel (TpAccount *account)
+{
+  const gchar * const * uri_schemes;
+  guint i;
+
+  uri_schemes = tp_account_get_uri_schemes (account);
+  if (uri_schemes == NULL)
+    return FALSE;
+
+  for (i = 0; uri_schemes[i] != NULL; i++)
+    {
+      if (!tp_strdiff (uri_schemes[i], "tel"))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* Return the TpContact on @conn associated with @individual, if any */
+TpContact *
+empathy_get_tp_contact_for_individual (FolksIndividual *individual,
+    TpConnection *conn)
+{
+  TpContact *contact = NULL;
+  GeeSet *personas;
+  GeeIterator *iter;
+
+  personas = folks_individual_get_personas (individual);
+  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+  while (contact == NULL && gee_iterator_next (iter))
+    {
+      TpfPersona *persona = gee_iterator_get (iter);
+      TpConnection *contact_conn;
+      TpContact *contact_cur = NULL;
+
+      if (TPF_IS_PERSONA (persona))
+        {
+          contact_cur = tpf_persona_get_contact (persona);
+          if (contact_cur != NULL)
+            {
+              contact_conn = tp_contact_get_connection (contact_cur);
+
+              if (!tp_strdiff (tp_proxy_get_object_path (contact_conn),
+                    tp_proxy_get_object_path (conn)))
+                contact = contact_cur;
+            }
+        }
+
+      g_clear_object (&persona);
+    }
+  g_clear_object (&iter);
+
+  return contact;
+}
+
+static gboolean
+properties_contains (gchar **list,
+                    gint length,
+                    const gchar *property)
+{
+  gint i;
+
+  for (i = 0; i < length; i++)
+    {
+      if (!tp_strdiff (list[i], property))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+check_writeable_property (TpConnection *connection,
+                         FolksIndividual *individual,
+                         gchar *property)
+{
+  gchar **properties;
+  gint prop_len;
+  gboolean retval = FALSE;
+  GeeSet *personas;
+  GeeIterator *iter;
+  FolksPersonaStore *persona_store;
+
+  persona_store = FOLKS_PERSONA_STORE (
+      empathy_dup_persona_store_for_connection (connection));
+
+  properties =
+    folks_persona_store_get_always_writeable_properties (persona_store,
+                                                        &prop_len);
+  retval = properties_contains (properties, prop_len, property);
+  if (retval == TRUE)
+    goto out;
+
+  /* Lets see if the Individual contains a Persona with the given property */
+  personas = folks_individual_get_personas (individual);
+  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+  while (!retval && gee_iterator_next (iter))
+    {
+      FolksPersona *persona = gee_iterator_get (iter);
+
+      properties =
+       folks_persona_get_writeable_properties (persona, &prop_len);
+      retval = properties_contains (properties, prop_len, property);
+
+      g_clear_object (&persona);
+
+      if (retval == TRUE)
+       break;
+    }
+  g_clear_object (&iter);
+
+out:
+  g_clear_object (&persona_store);
+  return retval;
+}
+
+/* Calculate whether the Individual can do audio or video calls.
+ * FIXME: We can remove this once libfolks has grown capabilities support
+ * again: bgo#626179. */
+void
+empathy_individual_can_audio_video_call (FolksIndividual *individual,
+    gboolean *can_audio_call,
+    gboolean *can_video_call,
+    EmpathyContact **out_contact)
+{
+  GeeSet *personas;
+  GeeIterator *iter;
+  gboolean can_audio = FALSE, can_video = FALSE;
+
+  personas = folks_individual_get_personas (individual);
+  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+  while (gee_iterator_next (iter))
+    {
+      FolksPersona *persona = gee_iterator_get (iter);
+      TpContact *tp_contact;
+
+      if (!empathy_folks_persona_is_interesting (persona))
+        goto while_finish;
+
+      tp_contact = tpf_persona_get_contact (TPF_PERSONA (persona));
+      if (tp_contact != NULL)
+        {
+          EmpathyContact *contact;
+
+          contact = empathy_contact_dup_from_tp_contact (tp_contact);
+          empathy_contact_set_persona (contact, persona);
+
+          can_audio = can_audio || empathy_contact_get_capabilities (contact) &
+              EMPATHY_CAPABILITIES_AUDIO;
+          can_video = can_video || empathy_contact_get_capabilities (contact) &
+              EMPATHY_CAPABILITIES_VIDEO;
+
+          if (out_contact != NULL)
+            *out_contact = g_object_ref (contact);
+
+          g_object_unref (contact);
+        }
+
+while_finish:
+      g_clear_object (&persona);
+
+      if (can_audio && can_video)
+        break;
+    }
+
+  g_clear_object (&iter);
+
+  if (can_audio_call != NULL)
+    *can_audio_call = can_audio;
+
+  if (can_video_call != NULL)
+    *can_video_call = can_video;
+}
+
+gboolean
+empathy_sasl_channel_supports_mechanism (TpChannel *channel,
+    const gchar *mechanism)
+{
+  GHashTable *props;
+  const gchar * const *available_mechanisms;
+
+  props = tp_channel_borrow_immutable_properties (channel);
+  available_mechanisms = tp_asv_get_boxed (props,
+      TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_AVAILABLE_MECHANISMS,
+      G_TYPE_STRV);
+
+  return tp_strv_contains (available_mechanisms, mechanism);
+}
+
+FolksIndividual *
+empathy_create_individual_from_tp_contact (TpContact *contact)
+{
+  GeeSet *personas;
+  TpfPersona *persona;
+  FolksIndividual *individual;
+
+  persona = tpf_persona_dup_for_contact (contact);
+  if (persona == NULL)
+    {
+      DEBUG ("Failed to get a persona for %s",
+          tp_contact_get_identifier (contact));
+      return NULL;
+    }
+
+  personas = GEE_SET (
+      gee_hash_set_new (FOLKS_TYPE_PERSONA, g_object_ref, g_object_unref,
+      g_direct_hash, g_direct_equal));
+
+  gee_collection_add (GEE_COLLECTION (personas), persona);
+
+  individual = folks_individual_new (personas);
+
+  g_clear_object (&persona);
+  g_clear_object (&personas);
+
+  return individual;
+}