aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libempathy/empathy-contact.c140
-rw-r--r--libempathy/empathy-contact.h14
2 files changed, 154 insertions, 0 deletions
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index c4be98135..0bba88396 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -29,6 +29,8 @@
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/util.h>
+#include <telepathy-logger/log-manager.h>
+
#include <folks/folks.h>
#include <folks/folks-telepathy.h>
@@ -1125,6 +1127,54 @@ empathy_contact_can_use_rfb_stream_tube (EmpathyContact *contact)
return priv->capabilities & EMPATHY_CAPABILITIES_RFB_STREAM_TUBE;
}
+static gboolean
+contact_has_log (EmpathyContact *contact)
+{
+ TplLogManager *manager;
+ gboolean have_log;
+
+ manager = tpl_log_manager_dup_singleton ();
+ have_log = tpl_log_manager_exists (manager,
+ empathy_contact_get_account (contact), empathy_contact_get_id (contact),
+ FALSE);
+ g_object_unref (manager);
+
+ return have_log;
+}
+
+gboolean
+empathy_contact_can_do_action (EmpathyContact *self,
+ EmpathyActionType action_type)
+{
+ gboolean sensitivity = FALSE;
+
+ switch (action_type)
+ {
+ case EMPATHY_ACTION_CHAT:
+ sensitivity = TRUE;
+ break;
+ case EMPATHY_ACTION_AUDIO_CALL:
+ sensitivity = empathy_contact_can_voip_audio (self);
+ break;
+ case EMPATHY_ACTION_VIDEO_CALL:
+ sensitivity = empathy_contact_can_voip_video (self);
+ break;
+ case EMPATHY_ACTION_VIEW_LOGS:
+ sensitivity = contact_has_log (self);
+ break;
+ case EMPATHY_ACTION_SEND_FILE:
+ sensitivity = empathy_contact_can_send_files (self);
+ break;
+ case EMPATHY_ACTION_SHARE_MY_DESKTOP:
+ sensitivity = empathy_contact_can_use_rfb_stream_tube (self);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return (sensitivity ? TRUE : FALSE);
+}
+
static gchar *
contact_get_avatar_filename (EmpathyContact *contact,
const gchar *token)
@@ -1686,3 +1736,93 @@ empathy_contact_dup_from_tp_contact (TpContact *tp_contact)
return contact;
}
+static int
+presence_sort_func (EmpathyContact *a, EmpathyContact *b)
+{
+ FolksPresence *presence_a, *presence_b;
+
+ presence_a = FOLKS_PRESENCE (empathy_contact_get_persona (a));
+ presence_b = FOLKS_PRESENCE (empathy_contact_get_persona (b));
+
+ /* We negate the result because we're sorting in reverse order (i.e. such that
+ * the Personas with the highest presence are at the beginning of the list. */
+ return -folks_presence_typecmp (folks_presence_get_presence_type (presence_a),
+ folks_presence_get_presence_type (presence_b));
+}
+
+static GCompareFunc
+get_sort_func_for_action (EmpathyActionType action_type)
+{
+ switch (action_type)
+ {
+ case EMPATHY_ACTION_CHAT:
+ case EMPATHY_ACTION_AUDIO_CALL:
+ case EMPATHY_ACTION_VIDEO_CALL:
+ case EMPATHY_ACTION_VIEW_LOGS:
+ case EMPATHY_ACTION_SEND_FILE:
+ case EMPATHY_ACTION_SHARE_MY_DESKTOP:
+ default:
+ return (GCompareFunc) presence_sort_func;
+ }
+}
+
+/**
+ * empathy_contact_dup_best_for_action:
+ * @individual: a #FolksIndividual
+ * @action_type: the type of action to be performed on the contact
+ *
+ * Chooses a #FolksPersona from the given @individual which is best-suited for
+ * the given @action_type. "Best-suited" is determined by choosing the persona
+ * with the highest presence out of all the personas which can perform the given
+ * @action_type (e.g. are capable of video calling).
+ *
+ * Return value: an #EmpathyContact for the best persona, or %NULL;
+ * unref with g_object_unref()
+ */
+EmpathyContact *
+empathy_contact_dup_best_for_action (FolksIndividual *individual,
+ EmpathyActionType action_type)
+{
+ GList *personas, *contacts, *l;
+ EmpathyContact *best_contact = NULL;
+
+ /* Build a list of EmpathyContacts that we can sort */
+ personas = folks_individual_get_personas (individual);
+ contacts = NULL;
+
+ for (l = personas; l != NULL; l = l->next)
+ {
+ TpContact *tp_contact;
+ EmpathyContact *contact;
+
+ if (!TPF_IS_PERSONA (l->data))
+ continue;
+
+ tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
+ contact = empathy_contact_dup_from_tp_contact (tp_contact);
+ empathy_contact_set_persona (contact, FOLKS_PERSONA (l->data));
+
+ /* Only choose the contact if they're actually capable of the specified
+ * action. */
+ if (!empathy_contact_can_do_action (contact, action_type))
+ {
+ g_object_unref (contact);
+ continue;
+ }
+
+ contacts = g_list_prepend (contacts, contact);
+ }
+
+ /* Sort the contacts by some heuristic based on the action type, then take
+ * the top contact. */
+ if (contacts != NULL)
+ {
+ contacts = g_list_sort (contacts, get_sort_func_for_action (action_type));
+ best_contact = g_object_ref (contacts->data);
+ }
+
+ g_list_foreach (contacts, (GFunc) g_object_unref, NULL);
+ g_list_free (contacts);
+
+ return best_contact;
+}
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index c1ef55d6b..005cf1e7a 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -100,6 +100,17 @@ gboolean empathy_contact_can_voip_video (EmpathyContact *contact);
gboolean empathy_contact_can_send_files (EmpathyContact *contact);
gboolean empathy_contact_can_use_rfb_stream_tube (EmpathyContact *contact);
+typedef enum {
+ EMPATHY_ACTION_CHAT,
+ EMPATHY_ACTION_AUDIO_CALL,
+ EMPATHY_ACTION_VIDEO_CALL,
+ EMPATHY_ACTION_VIEW_LOGS,
+ EMPATHY_ACTION_SEND_FILE,
+ EMPATHY_ACTION_SHARE_MY_DESKTOP,
+} EmpathyActionType;
+
+gboolean empathy_contact_can_do_action (EmpathyContact *self,
+ EmpathyActionType action_type);
#define EMPATHY_TYPE_AVATAR (empathy_avatar_get_type ())
GType empathy_avatar_get_type (void) G_GNUC_CONST;
@@ -118,6 +129,9 @@ gboolean empathy_contact_equal (gconstpointer contact1,
gconstpointer contact2);
EmpathyContact *empathy_contact_dup_from_tp_contact (TpContact *tp_contact);
+EmpathyContact * empathy_contact_dup_best_for_action (
+ FolksIndividual *individual,
+ EmpathyActionType action_type);
G_END_DECLS