*/
#include "config.h"
-
-#include <string.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/util.h>
-#include <telepathy-yell/telepathy-yell.h>
-
-#include <telepathy-logger/log-manager.h>
-
-#include <folks/folks.h>
-#include <folks/folks-telepathy.h>
+#include "empathy-contact.h"
#ifdef HAVE_GEOCODE
#include <geocode-glib/geocode-glib.h>
#endif
-#include "empathy-contact.h"
-#include "empathy-individual-manager.h"
#include "empathy-utils.h"
#include "empathy-enum-types.h"
-#include "empathy-marshal.h"
-#include "empathy-location.h"
#define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
#include "empathy-debug.h"
FolksPersona *persona;
gchar *id;
gchar *alias;
+ gchar *logged_alias;
EmpathyAvatar *avatar;
TpConnectionPresenceType presence;
guint handle;
EmpathyCapabilities capabilities;
gboolean is_user;
- guint hash;
/* Location is composed of string keys and GValues.
* Example: a "city" key would have "Helsinki" as string GValue,
* a "latitude" would have 65.0 as double GValue.
PROP_PERSONA,
PROP_ID,
PROP_ALIAS,
+ PROP_LOGGED_ALIAS,
PROP_AVATAR,
PROP_PRESENCE,
PROP_PRESENCE_MESSAGE,
EmpathyContact *contact = (EmpathyContact *) object;
EmpathyContactPriv *priv = GET_PRIV (contact);
GHashTable *location;
- TpHandle self_handle;
- TpHandle handle;
+ TpContact *self_contact;
const gchar * const *client_types;
if (priv->tp_contact == NULL)
/* Set is-user property. Note that it could still be the handle is
* different from the connection's self handle, in the case the handle
* comes from a group interface. */
- self_handle = tp_connection_get_self_handle (
+ self_contact = tp_connection_get_self_contact (
tp_contact_get_connection (priv->tp_contact));
- handle = tp_contact_get_handle (priv->tp_contact);
- empathy_contact_set_is_user (contact, self_handle == handle);
+ empathy_contact_set_is_user (contact, self_contact == priv->tp_contact);
g_signal_connect (priv->tp_contact, "notify",
G_CALLBACK (tp_contact_notify_cb), contact);
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class,
+ PROP_LOGGED_ALIAS,
+ g_param_spec_string ("logged-alias",
+ "Logged alias",
+ "The alias the user had when a message was logged, "
+ "only set when using empathy_contact_from_tpl_contact()",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (object_class,
PROP_AVATAR,
g_param_spec_boxed ("avatar",
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- _empathy_marshal_VOID__UINT_UINT,
+ g_cclosure_marshal_generic,
G_TYPE_NONE,
2, G_TYPE_UINT,
G_TYPE_UINT);
g_clear_object (&priv->groups);
g_free (priv->alias);
+ g_free (priv->logged_alias);
g_free (priv->id);
g_strfreev (priv->client_types);
case PROP_ALIAS:
g_value_set_string (value, empathy_contact_get_alias (contact));
break;
+ case PROP_LOGGED_ALIAS:
+ g_value_set_string (value, empathy_contact_get_logged_alias (contact));
+ break;
case PROP_AVATAR:
g_value_set_boxed (value, empathy_contact_get_avatar (contact));
break;
case PROP_ALIAS:
empathy_contact_set_alias (contact, g_value_get_string (value));
break;
+ case PROP_LOGGED_ALIAS:
+ g_assert (priv->logged_alias == NULL);
+ priv->logged_alias = g_value_dup_string (value);
+ break;
case PROP_PRESENCE:
empathy_contact_set_presence (contact, g_value_get_uint (value));
break;
{
EmpathyContact *contact = value;
FindContactData *data = user_data;
+ TpAccount *account = empathy_contact_get_account (contact);
+ const gchar *path = NULL;
+
+ if (account != NULL)
+ path = tp_proxy_get_object_path (account);
return !tp_strdiff (empathy_contact_get_id (contact),
tpl_entity_get_identifier (data->entity)) &&
- !tp_strdiff (tp_proxy_get_object_path (data->account),
- tp_proxy_get_object_path (
- empathy_contact_get_account (contact)));
+ !tp_strdiff (tp_proxy_get_object_path (data->account), path);
+}
+
+static void
+get_contacts_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpWeakRef *wr = user_data;
+ EmpathyContactPriv *priv;
+ EmpathyContact *self;
+
+ self = tp_weak_ref_dup_object (wr);
+ if (self == NULL)
+ goto out;
+
+ priv = GET_PRIV (self);
+
+ g_return_if_fail (priv->tp_contact == NULL);
+
+ priv->tp_contact = tp_connection_dup_contact_by_id_finish (
+ TP_CONNECTION (source), result, NULL);
+ if (priv->tp_contact == NULL)
+ goto out;
+
+ g_object_notify (G_OBJECT (self), "tp-contact");
+
+ /* Update capabilities now that we have a TpContact */
+ set_capabilities_from_tp_caps (self,
+ tp_contact_get_capabilities (priv->tp_contact));
+
+out:
+ g_clear_object (&self);
+ tp_weak_ref_destroy (wr);
}
EmpathyContact *
if (existing_contact != NULL)
{
- EmpathyContactPriv *priv;
-
retval = g_object_new (EMPATHY_TYPE_CONTACT,
"tp-contact", empathy_contact_get_tp_contact (existing_contact),
+ "logged-alias", tpl_entity_get_alias (tpl_entity),
NULL);
-
- priv = GET_PRIV (retval);
-
- /* contact_set_property() calls empathy_contact_set_alias(), which
- * tries to set the alias on the FolksPersona, but we don't want to
- * do that when creating an EmpathyContact from a TplEntity. So just
- * set priv->alias instead of passing it to g_object_new() instead. */
- g_free (priv->alias);
- priv->alias = g_strdup (tpl_entity_get_alias (tpl_entity));
}
else
{
+ TpConnection *conn;
+ const gchar *id;
+
is_user = (TPL_ENTITY_SELF == tpl_entity_get_entity_type (tpl_entity));
+ id = tpl_entity_get_identifier (tpl_entity);
+
retval = g_object_new (EMPATHY_TYPE_CONTACT,
- "id", tpl_entity_get_identifier (tpl_entity),
+ "id", id,
"alias", tpl_entity_get_alias (tpl_entity),
"account", account,
"is-user", is_user,
NULL);
+
+ /* Try to get a TpContact associated to have at least contact
+ * capabilities if possible. This is useful for CM supporting calling
+ * offline contacts for example. */
+ conn = tp_account_get_connection (account);
+ if (conn != NULL)
+ {
+ TpContactFeature features[] = { TP_CONTACT_FEATURE_CAPABILITIES };
+ conn = tp_account_get_connection (account);
+
+ tp_connection_dup_contact_by_id_async (conn, id,
+ G_N_ELEMENTS (features), features, get_contacts_cb,
+ tp_weak_ref_new (retval, NULL, NULL));
+ }
}
if (!EMP_STR_EMPTY (tpl_entity_get_avatar_token (tpl_entity)))
return empathy_contact_get_id (contact);
}
+const gchar *
+empathy_contact_get_logged_alias (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (contact);
+
+ if (priv->logged_alias != NULL)
+ return priv->logged_alias;
+ else
+ return empathy_contact_get_alias (contact);
+}
+
void
empathy_contact_set_alias (EmpathyContact *contact,
const gchar *alias)
if (priv->groups == NULL)
{
priv->groups = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup,
- g_free, g_str_hash, g_str_equal);
+ g_free, NULL, NULL, NULL, NULL, NULL, NULL);
}
gee_collection_add (GEE_COLLECTION (priv->groups), group);
/* FIXME: This assume the account manager already exists */
connection = tp_contact_get_connection (priv->tp_contact);
priv->account =
- g_object_ref (empathy_get_account_for_connection (connection));
+ g_object_ref (tp_connection_get_account (connection));
}
return priv->account;
if (priv->persona == NULL && priv->tp_contact != NULL)
{
- /* FIXME: This is disgustingly slow */
- /* Query for the persona */
- EmpathyIndividualManager *manager;
- GList *individuals, *l;
+ TpfPersona *persona;
- manager = empathy_individual_manager_dup_singleton ();
- individuals = empathy_individual_manager_get_members (manager);
-
- for (l = individuals; l != NULL; l = l->next)
+ persona = tpf_persona_dup_for_contact (priv->tp_contact);
+ if (persona != NULL)
{
- FolksIndividual *individual = FOLKS_INDIVIDUAL (l->data);
- GeeSet *personas;
- GeeIterator *iter;
- gboolean persona_found = FALSE;
-
- personas = folks_individual_get_personas (individual);
- iter = gee_iterable_iterator (GEE_ITERABLE (personas));
- while (!persona_found && gee_iterator_next (iter))
- {
- TpfPersona *persona = gee_iterator_get (iter);
-
- if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona)))
- {
- TpContact *tp_contact = tpf_persona_get_contact (persona);
-
- if (tp_contact == priv->tp_contact)
- {
- /* Found the right persona */
- empathy_contact_set_persona (contact,
- (FolksPersona *) persona);
- persona_found = TRUE;
- }
- g_clear_object (&persona);
- }
- }
- g_clear_object (&iter);
+ empathy_contact_set_persona (contact, (FolksPersona *) persona);
+ g_object_unref (persona);
}
-
- g_list_free (individuals);
- g_object_unref (manager);
}
return priv->persona;
avatar_path = g_build_filename (g_get_user_cache_dir (),
"telepathy",
"avatars",
- tp_account_get_connection_manager (account),
- tp_account_get_protocol (account),
+ tp_account_get_cm_name (account),
+ tp_account_get_protocol_name (account),
NULL);
g_mkdir_with_parents (avatar_path, 0700);
EmpathyContact *contact = user_data;
EmpathyContactPriv *priv = GET_PRIV (contact);
GError *error = NULL;
+ GList *res;
+ GeocodeLocation *loc;
GHashTable *new_location;
- GHashTable *resolved;
+ GHashTable *resolved = NULL;
gdouble latitude, longitude;
if (priv->location == NULL)
goto out;
- resolved = geocode_object_resolve_finish (GEOCODE_OBJECT (source), result,
+ res = geocode_forward_search_finish (GEOCODE_FORWARD (source), result,
&error);
- if (resolved == NULL)
+ if (res == NULL)
{
DEBUG ("Failed to resolve geocode: %s", error->message);
g_error_free (error);
goto out;
}
- if (!geocode_object_get_coords (resolved, &longitude, &latitude))
- goto out;
+ loc = res->data;
new_location = tp_asv_new (
- EMPATHY_LOCATION_LAT, G_TYPE_DOUBLE, latitude,
- EMPATHY_LOCATION_LON, G_TYPE_DOUBLE, longitude,
+ EMPATHY_LOCATION_LAT, G_TYPE_DOUBLE, loc->latitude,
+ EMPATHY_LOCATION_LON, G_TYPE_DOUBLE, loc->longitude,
NULL);
- DEBUG ("\t - Latitude: %f", latitude);
- DEBUG ("\t - Longitude: %f", longitude);
+ DEBUG ("\t - Latitude: %f", loc->latitude);
+ DEBUG ("\t - Longitude: %f", loc->longitude);
+
+ g_list_free_full (res, (GDestroyNotify) geocode_location_free);
/* Copy remaning fields. LAT and LON were not defined so we won't overwrite
* the values we just set. */
g_object_notify ((GObject *) contact, "location");
out:
- tp_clear_pointer (&result, g_hash_table_unref);
+ tp_clear_pointer (&resolved, g_hash_table_unref);
g_object_unref (contact);
}
static void
update_geocode (EmpathyContact *contact)
{
- GeocodeObject *geocode;
+ GeocodeForward *geocode;
GHashTable *location;
location = empathy_contact_get_location (contact);
- if (location == NULL)
+ if (location == NULL ||
+ g_hash_table_size (location) == 0)
return;
/* No need to search for position if contact published it */
g_hash_table_lookup (location, EMPATHY_LOCATION_LON) != NULL)
return;
- geocode = geocode_object_new_for_params (location);
+ geocode = geocode_forward_new_for_params (location);
+ if (geocode == NULL)
+ return;
- geocode_object_resolve_async (geocode, NULL, geocode_cb,
+ geocode_forward_search_async (geocode, NULL, geocode_cb,
g_object_ref (contact));
g_object_unref (geocode);
tp_caps_to_capabilities (TpCapabilities *caps)
{
EmpathyCapabilities capabilities = 0;
- guint i;
- GPtrArray *classes;
- classes = tp_capabilities_get_channel_classes (caps);
+ if (tp_capabilities_supports_file_transfer (caps))
+ capabilities |= EMPATHY_CAPABILITIES_FT;
- for (i = 0; i < classes->len; i++)
- {
- GValueArray *class_struct;
- GHashTable *fixed_prop;
- GStrv allowed_prop;
- TpHandleType handle_type;
- const gchar *chan_type;
-
- class_struct = g_ptr_array_index (classes, i);
- tp_value_array_unpack (class_struct, 2,
- &fixed_prop,
- &allowed_prop);
-
- handle_type = tp_asv_get_uint32 (fixed_prop,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL);
- if (handle_type != TP_HANDLE_TYPE_CONTACT)
- continue;
-
- chan_type = tp_asv_get_string (fixed_prop,
- TP_PROP_CHANNEL_CHANNEL_TYPE);
-
- if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
- {
- capabilities |= EMPATHY_CAPABILITIES_FT;
- }
- else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- {
- const gchar *service;
+ if (tp_capabilities_supports_stream_tubes (caps, TP_HANDLE_TYPE_CONTACT,
+ "rfb"))
+ capabilities |= EMPATHY_CAPABILITIES_RFB_STREAM_TUBE;
- 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))
- {
- guint j;
-
- for (j = 0; allowed_prop[j] != NULL; j++)
- {
- if (!tp_strdiff (allowed_prop[j],
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO))
- capabilities |= EMPATHY_CAPABILITIES_AUDIO;
- else if (!tp_strdiff (allowed_prop[j],
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO))
- capabilities |= EMPATHY_CAPABILITIES_VIDEO;
- }
-
- if (tp_asv_get_boolean (fixed_prop,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL))
- capabilities |= EMPATHY_CAPABILITIES_AUDIO;
- if (tp_asv_get_boolean (fixed_prop,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL))
- capabilities |= EMPATHY_CAPABILITIES_VIDEO;
- }
- else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
- {
- if (tp_asv_get_boolean (fixed_prop,
- TP_PROP_CHANNEL_INTERFACE_SMS_SMS_CHANNEL, NULL))
- capabilities |= EMPATHY_CAPABILITIES_SMS;
- }
- else if (!tp_strdiff (chan_type,
- TPY_IFACE_CHANNEL_TYPE_CALL))
- {
- guint j;
-
- if (tp_asv_get_boolean (fixed_prop,
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL))
- capabilities |= EMPATHY_CAPABILITIES_AUDIO;
-
- if (tp_asv_get_boolean (fixed_prop,
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL))
- capabilities |= EMPATHY_CAPABILITIES_VIDEO;
-
- for (j = 0; allowed_prop[j] != NULL; j++)
- {
- if (!tp_strdiff (allowed_prop[j],
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO))
- capabilities |= EMPATHY_CAPABILITIES_AUDIO;
- else if (!tp_strdiff (allowed_prop[j],
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO))
- capabilities |= EMPATHY_CAPABILITIES_VIDEO;
- }
- }
+ if (tp_capabilities_supports_audio_video_call (caps, TP_HANDLE_TYPE_CONTACT))
+ {
+ capabilities |= EMPATHY_CAPABILITIES_AUDIO;
+ capabilities |= EMPATHY_CAPABILITIES_VIDEO;
}
+ else if (tp_capabilities_supports_audio_call (caps, TP_HANDLE_TYPE_CONTACT))
+ {
+ capabilities |= EMPATHY_CAPABILITIES_AUDIO;
+ }
+
+ if (tp_capabilities_supports_sms (caps))
+ capabilities |= EMPATHY_CAPABILITIES_SMS;
return capabilities;
}
gchar *data;
gsize len;
gchar *path;
+ GError *error = NULL;
+
+ if (!g_file_load_contents (file, NULL, &data, &len, NULL, &error))
+ {
+ DEBUG ("Failed to load avatar: %s", error->message);
+
+ g_error_free (error);
+ contact_set_avatar (contact, NULL);
+ return;
+ }
- g_file_load_contents (file, NULL, &data, &len, NULL, NULL);
path = g_file_get_path (file);
avatar = empathy_avatar_new ((guchar *) data, len, mime, path);
goto while_finish;
tp_contact = tpf_persona_get_contact (TPF_PERSONA (persona));
+ if (tp_contact == NULL)
+ goto while_finish;
+
contact = empathy_contact_dup_from_tp_contact (tp_contact);
empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
return best_contact;
}
+
+#define declare_contact_cb(name) \
+static void \
+contact_##name##_cb (GObject *source, \
+ GAsyncResult *result, \
+ gpointer user_data) \
+{ \
+ TpContact *contact = (TpContact *) source; \
+ GError *error = NULL; \
+ \
+ if (!tp_contact_##name##_finish (contact, result, &error)) \
+ { \
+ DEBUG ("Failed to ##name## on %s\n", \
+ tp_contact_get_identifier (contact)); \
+ g_error_free (error); \
+ } \
+}
+
+declare_contact_cb (request_subscription)
+declare_contact_cb (authorize_publication)
+declare_contact_cb (unblock)
+
+void
+empathy_contact_add_to_contact_list (EmpathyContact *self,
+ const gchar *message)
+{
+ EmpathyContactPriv *priv = GET_PRIV (self);
+
+ g_return_if_fail (priv->tp_contact != NULL);
+
+ tp_contact_request_subscription_async (priv->tp_contact, message,
+ contact_request_subscription_cb, NULL);
+
+ tp_contact_authorize_publication_async (priv->tp_contact,
+ contact_authorize_publication_cb, NULL);
+
+ tp_contact_unblock_async (priv->tp_contact, contact_unblock_cb, NULL);
+}
+
+declare_contact_cb (remove)
+
+void
+empathy_contact_remove_from_contact_list (EmpathyContact *self)
+{
+ EmpathyContactPriv *priv = GET_PRIV (self);
+
+ g_return_if_fail (priv->tp_contact != NULL);
+
+ tp_contact_remove_async (priv->tp_contact, contact_remove_cb, NULL);
+}