summaryrefslogtreecommitdiff
path: root/telepathy-glib/contact.c
diff options
context:
space:
mode:
Diffstat (limited to 'telepathy-glib/contact.c')
-rw-r--r--telepathy-glib/contact.c381
1 files changed, 287 insertions, 94 deletions
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 233abf4c4..8076077d9 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -57,7 +57,7 @@
* An object representing a contact on a #TpConnection.
*
* Contact objects support tracking a number of attributes of contacts, as
- * described by the #TpContactFeature flags. Features can be specified when
+ * described by the contact feature #GQuark<!-- -->s. Features can be specified when
* instantiating contact objects (with tp_connection_get_contacts_by_id() or
* tp_connection_get_contacts_by_handle()), or added to an existing contact
* object with tp_connection_upgrade_contacts(). For example, a client wishing
@@ -89,68 +89,226 @@ struct _TpContact {
};
/**
- * TpContactFeature:
- * @TP_CONTACT_FEATURE_ALIAS: #TpContact:alias
- * @TP_CONTACT_FEATURE_AVATAR_TOKEN: #TpContact:avatar-token
- * @TP_CONTACT_FEATURE_PRESENCE: #TpContact:presence-type,
- * #TpContact:presence-status and #TpContact:presence-message
- * @TP_CONTACT_FEATURE_LOCATION: #TpContact:location (available since 0.11.1)
- * @TP_CONTACT_FEATURE_CAPABILITIES: #TpContact:capabilities
- * (available since 0.11.3)
- * @TP_CONTACT_FEATURE_AVATAR_DATA: #TpContact:avatar-file and
- * #TpContact:avatar-mime-type. Implies %TP_CONTACT_FEATURE_AVATAR_TOKEN
- * (available since 0.11.6)
- * @TP_CONTACT_FEATURE_CONTACT_INFO: #TpContact:contact-info
- * (available since 0.11.7)
- * @TP_CONTACT_FEATURE_CLIENT_TYPES: #TpContact:client-types
- * (available since 0.13.1)
- * @TP_CONTACT_FEATURE_SUBSCRIPTION_STATES: #TpContact:subscribe-state,
- * #TpContact:publish-state and #TpContact:publish-request. Require a
- * Connection implementing the %TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST
- * interface. (available since 0.13.12)
- * @TP_CONTACT_FEATURE_CONTACT_GROUPS: #TpContact:contact-groups
- * (available since 0.13.14)
- * @TP_CONTACT_FEATURE_CONTACT_BLOCKING: #TpContact:is-blocked. Require
- * Connection implementing the %TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING
- * interface. (available since 0.17.0)
- *
- * Enumeration representing the features a #TpContact can optionally support.
- * When requesting a #TpContact, library users specify the desired features;
- * the #TpContact code will only initialize state for those features, to
- * avoid unwanted D-Bus round-trips and signal connections.
- *
- * Since 0.11.5, there is a corresponding #GEnumClass type,
- * %TP_TYPE_CONTACT_FEATURE.
+ * TP_CONTACT_FEATURE_ALIAS:
*
- * Since: 0.7.18
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "alias" feature.
+ *
+ * When this feature is prepared, the contact's alias has been retrieved.
+ * In particular, the #TpContact:alias property has been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_alias (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-alias");
+}
+
+/**
+ * TP_CONTACT_FEATURE_AVATAR_TOKEN:
+ *
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "avatar token" feature.
+ *
+ * When this feature is prepared, the contact's avatar token has been
+ * retrieved. In particular, the #TpContact:avatar-token property has
+ * been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_avatar_token (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-avatar-token");
+}
+
+/**
+ * TP_CONTACT_FEATURE_PRESENCE:
+ *
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "presence" feature.
+ *
+ * When this feature is prepared, the contact's presence has been
+ * retrieved. In particular, the #TpContact:presence-type,
+ * #TpContact:presence-status, and #TpContact:presence-message
+ * properties have been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_presence (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-presence");
+}
+
+/**
+ * TP_CONTACT_FEATURE_LOCATION:
+ *
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "location" feature.
+ *
+ * When this feature is prepared, the contact's location has been
+ * retrieved. In particular, the #TpContact:location property has
+ * been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_location (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-location");
+}
+
+/**
+ * TP_CONTACT_FEATURE_CAPABILITIES:
+ *
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "capabilities" feature.
+ *
+ * When this feature is prepared, the contact's capabilities have been
+ * retrieved. In particular, the #TpContact:capabilities property has
+ * been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_capabilities (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-capabilities");
+}
+
+/**
+ * TP_CONTACT_FEATURE_AVATAR_DATA:
+ *
+ * Expands to a call to a function that returns a #GQuark representing
+ * the "avatar data" feature.
+ *
+ * When this feature is prepared, the contact's avatar has been
+ * retrieved. In particular, the #TpContact:avatar-file property has
+ * been set.
+ *
+ * This feature also implies the %TP_CONTACT_FEATURE_AVATAR_TOKEN.
+ *
+ * Since: 0.UNRELEASED
*/
+GQuark
+tp_contact_get_feature_quark_avatar_data (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-avatar-data");
+}
+
/**
- * TP_NUM_CONTACT_FEATURES:
+ * TP_CONTACT_FEATURE_CONTACT_INFO:
*
- * 1 higher than the highest #TpContactFeature supported by this version of
- * telepathy-glib.
+ * Expands to a call to a function that returns a #GQuark representing
+ * the "contact info" feature.
+ *
+ * When this feature is prepared, the contact's contact info has been
+ * retrieved. In particular, the #TpContact:contact-info property has
+ * been set.
*
* Since: 0.UNRELEASED
*/
+GQuark
+tp_contact_get_feature_quark_contact_info (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-contact-info");
+}
+
+/**
+ * TP_CONTACT_FEATURE_CLIENT_TYPES:
+ *
+ * Expands to a call to a function that returns a #GQuark representing
+ * the "client types" feature.
+ *
+ * When this feature is prepared, the contact's client types have been
+ * retrieved. In particular, the #TpContact:client-types property has
+ * been set.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_client_types (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-client-types");
+}
+
+/**
+ * TP_CONTACT_FEATURE_SUBSCRIPTION_STATES:
+ *
+ * Expands to a call to a function that returns a #GQuark representing
+ * the "subscription states" feature.
+ *
+ * When this feature is prepared, the contact's subscription states
+ * have been retrieved. In particular, the #TpContact:subscribe-state,
+ * #TpContact:publish-request, and #TpContact:publish-state properties
+ * have been set.
+ *
+ * This feature requires a Connection implementing the
+ * %TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST interface.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+GQuark
+tp_contact_get_feature_quark_subscription_states (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-subscription-states");
+}
+
/**
- * TP_CONTACT_FEATURE_INVALID: (skip)
+ * TP_CONTACT_FEATURE_CONTACT_GROUPS:
+ *
+ * Expands to a call to a function that returns a #GQuark representing the
+ * "contact groups" feature.
+ *
+ * When this feature is prepared, the contact's contact groups have
+ * been retrieved. In particular, the #TpContact:contact-groups
+ * property has been set.
*
- * An invalid TpContactFeature. Used as list termination. See for example
- * tp_simple_client_factory_add_contact_features_varargs().
+ * This feature requires a Connection implementing the
+ * %TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS interface.
*
- * Since: 0.15.5
+ * Since: 0.UNRELEASED
*/
+GQuark
+tp_contact_get_feature_quark_contact_groups (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-contact-groups");
+}
+
/**
- * TP_TYPE_CONTACT_FEATURE:
+ * TP_CONTACT_FEATURE_CONTACT_BLOCKING:
+ *
+ * Expands to a call to a function that returns a #GQuark representing
+ * the "contact blocking" feature.
*
- * The #GEnumClass type of a #TpContactFeature.
+ * When this feature is prepared, the contact's blocking state have
+ * been retrieved. In particular, the #TpContact:is-blocked property
+ * has been set.
*
- * Since: 0.11.5
+ * This feature requires a Connection implementing the
+ * %TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING interface.
+ *
+ * Since: 0.UNRELEASED
*/
+GQuark
+tp_contact_get_feature_quark_contact_blocking (void)
+{
+ return g_quark_from_static_string ("tp-contact-feature-contact-blocking");
+}
+
G_DEFINE_TYPE (TpContact, tp_contact, G_TYPE_OBJECT)
@@ -186,20 +344,22 @@ enum {
static guint signals[N_SIGNALS] = {0};
+static GQuark const no_quarks[] = { 0 };
+
/* The API allows for more than 32 features, but this implementation does
* not. We can easily expand this later. */
typedef enum {
- CONTACT_FEATURE_FLAG_ALIAS = 1 << TP_CONTACT_FEATURE_ALIAS,
- CONTACT_FEATURE_FLAG_AVATAR_TOKEN = 1 << TP_CONTACT_FEATURE_AVATAR_TOKEN,
- CONTACT_FEATURE_FLAG_PRESENCE = 1 << TP_CONTACT_FEATURE_PRESENCE,
- CONTACT_FEATURE_FLAG_LOCATION = 1 << TP_CONTACT_FEATURE_LOCATION,
- CONTACT_FEATURE_FLAG_CAPABILITIES = 1 << TP_CONTACT_FEATURE_CAPABILITIES,
- CONTACT_FEATURE_FLAG_AVATAR_DATA = 1 << TP_CONTACT_FEATURE_AVATAR_DATA,
- CONTACT_FEATURE_FLAG_CONTACT_INFO = 1 << TP_CONTACT_FEATURE_CONTACT_INFO,
- CONTACT_FEATURE_FLAG_CLIENT_TYPES = 1 << TP_CONTACT_FEATURE_CLIENT_TYPES,
- CONTACT_FEATURE_FLAG_STATES = 1 << TP_CONTACT_FEATURE_SUBSCRIPTION_STATES,
- CONTACT_FEATURE_FLAG_CONTACT_GROUPS = 1 << TP_CONTACT_FEATURE_CONTACT_GROUPS,
- CONTACT_FEATURE_FLAG_CONTACT_BLOCKING = 1 << TP_CONTACT_FEATURE_CONTACT_BLOCKING,
+ CONTACT_FEATURE_FLAG_ALIAS = 1 << 1,
+ CONTACT_FEATURE_FLAG_AVATAR_TOKEN = 1 << 2,
+ CONTACT_FEATURE_FLAG_PRESENCE = 1 << 3,
+ CONTACT_FEATURE_FLAG_LOCATION = 1 << 4,
+ CONTACT_FEATURE_FLAG_CAPABILITIES = 1 << 5,
+ CONTACT_FEATURE_FLAG_AVATAR_DATA = 1 << 6,
+ CONTACT_FEATURE_FLAG_CONTACT_INFO = 1 << 7,
+ CONTACT_FEATURE_FLAG_CLIENT_TYPES = 1 << 8,
+ CONTACT_FEATURE_FLAG_STATES = 1 << 9,
+ CONTACT_FEATURE_FLAG_CONTACT_GROUPS = 1 << 10,
+ CONTACT_FEATURE_FLAG_CONTACT_BLOCKING = 1 << 11,
} ContactFeatureFlags;
struct _TpContactPrivate {
@@ -318,6 +478,35 @@ tp_contact_get_identifier (TpContact *self)
return self->priv->identifier;
}
+static guint
+get_feature (GQuark feature)
+{
+ if (feature == TP_CONTACT_FEATURE_ALIAS)
+ return CONTACT_FEATURE_FLAG_ALIAS;
+ else if (feature == TP_CONTACT_FEATURE_AVATAR_TOKEN)
+ return CONTACT_FEATURE_FLAG_AVATAR_TOKEN;
+ else if (feature == TP_CONTACT_FEATURE_PRESENCE)
+ return CONTACT_FEATURE_FLAG_PRESENCE;
+ else if (feature == TP_CONTACT_FEATURE_LOCATION)
+ return CONTACT_FEATURE_FLAG_LOCATION;
+ else if (feature == TP_CONTACT_FEATURE_CAPABILITIES)
+ return CONTACT_FEATURE_FLAG_CAPABILITIES;
+ else if (feature == TP_CONTACT_FEATURE_AVATAR_DATA)
+ return CONTACT_FEATURE_FLAG_AVATAR_DATA;
+ else if (feature == TP_CONTACT_FEATURE_CONTACT_INFO)
+ return CONTACT_FEATURE_FLAG_CONTACT_INFO;
+ else if (feature == TP_CONTACT_FEATURE_CLIENT_TYPES)
+ return CONTACT_FEATURE_FLAG_CLIENT_TYPES;
+ else if (feature == TP_CONTACT_FEATURE_SUBSCRIPTION_STATES)
+ return CONTACT_FEATURE_FLAG_STATES;
+ else if (feature == TP_CONTACT_FEATURE_CONTACT_GROUPS)
+ return CONTACT_FEATURE_FLAG_CONTACT_GROUPS;
+ else if (feature == TP_CONTACT_FEATURE_CONTACT_BLOCKING)
+ return CONTACT_FEATURE_FLAG_CONTACT_BLOCKING;
+
+ return 0;
+}
+
/**
* tp_contact_has_feature:
* @self: a contact
@@ -331,12 +520,18 @@ tp_contact_get_identifier (TpContact *self)
*/
gboolean
tp_contact_has_feature (TpContact *self,
- TpContactFeature feature)
+ GQuark feature)
{
+ guint mask;
+
g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (feature < TP_NUM_CONTACT_FEATURES, FALSE);
- return ((self->priv->has_features & (1 << feature)) != 0);
+ mask = get_feature (feature);
+
+ if (mask == 0)
+ return FALSE;
+
+ return ((self->priv->has_features & mask) != 0);
}
@@ -2991,19 +3186,18 @@ tp_contact_set_attributes (TpContact *contact,
return TRUE;
}
-static gboolean get_feature_flags (guint n_features,
- const TpContactFeature *features, ContactFeatureFlags *flags);
+static gboolean get_feature_flags (const GQuark *features,
+ ContactFeatureFlags *flags);
gboolean
_tp_contact_set_attributes (TpContact *contact,
GHashTable *asv,
- guint n_features,
- const TpContactFeature *features,
+ const GQuark *features,
GError **error)
{
ContactFeatureFlags feature_flags = 0;
- if (!get_feature_flags (n_features, features, &feature_flags))
+ if (!get_feature_flags (features, &feature_flags))
return FALSE;
return tp_contact_set_attributes (contact, asv, feature_flags, error);
@@ -3219,12 +3413,11 @@ contacts_bind_to_signals (TpConnection *connection,
const gchar **
_tp_contacts_bind_to_signals (TpConnection *connection,
- guint n_features,
- const TpContactFeature *features)
+ const GQuark *features)
{
ContactFeatureFlags feature_flags = 0;
- if (!get_feature_flags (n_features, features, &feature_flags))
+ if (!get_feature_flags (features, &feature_flags))
return NULL;
return contacts_bind_to_signals (connection, feature_flags);
@@ -3313,18 +3506,16 @@ lookup_all_contacts (ContactsContext *context)
}
static gboolean
-get_feature_flags (guint n_features,
- const TpContactFeature *features,
+get_feature_flags (const GQuark *features,
ContactFeatureFlags *flags)
{
ContactFeatureFlags feature_flags = 0;
guint i;
- for (i = 0; i < n_features; i++)
- {
- g_return_val_if_fail (features[i] < TP_NUM_CONTACT_FEATURES, FALSE);
- feature_flags |= (1 << features[i]);
- }
+ g_return_val_if_fail (features != NULL, FALSE);
+
+ for (i = 0; features[i] != 0; i++)
+ feature_flags |= get_feature (features[i]);
/* Force AVATAR_TOKEN if we have AVATAR_DATA */
if ((feature_flags & CONTACT_FEATURE_FLAG_AVATAR_DATA) != 0)
@@ -3364,10 +3555,10 @@ contacts_context_remove_common_features (ContactsContext *context)
* @n_handles: The number of handles in @handles (must be at least 1)
* @handles: (array length=n_handles) (element-type uint): An array of handles
* of type %TP_HANDLE_TYPE_CONTACT representing the desired contacts
- * @n_features: The number of features in @features (may be 0)
- * @features: (array length=n_features) (allow-none) (element-type uint): An array of features that
+ * @features: (transfer-none) (array zero-terminated=1) (allow-none)
+ * (element-type GLib.Quark): A zero-terminated array of features that
* must be ready for use (if supported) before the callback is called (may
- * be %NULL if @n_features is 0)
+ * be %NULL)
* @callback: A user callback to call when the contacts are ready
* @user_data: Data to pass to the callback
* @destroy: Called to destroy @user_data either after @callback has been
@@ -3391,8 +3582,7 @@ void
tp_connection_get_contacts_by_handle (TpConnection *self,
guint n_handles,
const TpHandle *handles,
- guint n_features,
- const TpContactFeature *features,
+ const GQuark *features,
TpConnectionContactsByHandleCb callback,
gpointer user_data,
GDestroyNotify destroy,
@@ -3410,10 +3600,12 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
g_return_if_fail (tp_proxy_get_invalidated (self) == NULL);
g_return_if_fail (n_handles >= 1);
g_return_if_fail (handles != NULL);
- g_return_if_fail (n_features == 0 || features != NULL);
g_return_if_fail (callback != NULL);
- if (!get_feature_flags (n_features, features, &feature_flags))
+ if (features == NULL)
+ features = no_quarks;
+
+ if (!get_feature_flags (features, &feature_flags))
return;
context = contacts_context_new (self, n_handles, feature_flags,
@@ -3444,8 +3636,8 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
* @n_contacts: The number of contacts in @contacts (must be at least 1)
* @contacts: (array length=n_contacts): An array of #TpContact objects
* associated with @self
- * @n_features: The number of features in @features (must be at least 1)
- * @features: (array length=n_features): An array of features that must be
+ * @features: (transfer-none) (array zero-terminated=1)
+ * (element-type GLib.Quark): An array of features that must be
* ready for use (if supported) before the callback is called
* @callback: A user callback to call when the contacts are ready
* @user_data: Data to pass to the callback
@@ -3470,8 +3662,7 @@ void
tp_connection_upgrade_contacts (TpConnection *self,
guint n_contacts,
TpContact * const *contacts,
- guint n_features,
- const TpContactFeature *features,
+ const GQuark *features,
TpConnectionUpgradeContactsCb callback,
gpointer user_data,
GDestroyNotify destroy,
@@ -3485,16 +3676,18 @@ tp_connection_upgrade_contacts (TpConnection *self,
TP_CONNECTION_FEATURE_CONNECTED));
g_return_if_fail (n_contacts >= 1);
g_return_if_fail (contacts != NULL);
- g_return_if_fail (n_features == 0 || features != NULL);
g_return_if_fail (callback != NULL);
+ if (features == NULL)
+ features = no_quarks;
+
for (i = 0; i < n_contacts; i++)
{
g_return_if_fail (contacts[i]->priv->connection == self);
g_return_if_fail (contacts[i]->priv->identifier != NULL);
}
- if (!get_feature_flags (n_features, features, &feature_flags))
+ if (!get_feature_flags (features, &feature_flags))
return;
context = contacts_context_new (self, n_contacts, feature_flags,
@@ -3646,10 +3839,9 @@ contacts_requested_handles (TpConnection *connection,
* the desired contacts by their
* identifiers in the IM protocol (XMPP JIDs, SIP URIs, MSN Passports,
* AOL screen-names etc.)
- * @n_features: The number of features in @features (may be 0)
- * @features: (array length=n_features) (allow-none): An array of features
- * that must be ready for use (if supported)
- * before the callback is called (may be %NULL if @n_features is 0)
+ * @features: (transfer-none) (array zero-terminated=1) (allow-none)
+ * (element-type GLib.Quark): An array of features that must be ready for
+ * use (if supported) before the callback is called (may be %NULL)
* @callback: A user callback to call when the contacts are ready
* @user_data: Data to pass to the callback
* @destroy: Called to destroy @user_data either after @callback has been
@@ -3673,8 +3865,7 @@ void
tp_connection_get_contacts_by_id (TpConnection *self,
guint n_ids,
const gchar * const *ids,
- guint n_features,
- const TpContactFeature *features,
+ const GQuark *features,
TpConnectionContactsByIdCb callback,
gpointer user_data,
GDestroyNotify destroy,
@@ -3689,10 +3880,12 @@ tp_connection_get_contacts_by_id (TpConnection *self,
g_return_if_fail (n_ids >= 1);
g_return_if_fail (ids != NULL);
g_return_if_fail (ids[0] != NULL);
- g_return_if_fail (n_features == 0 || features != NULL);
g_return_if_fail (callback != NULL);
- if (!get_feature_flags (n_features, features, &feature_flags))
+ if (features == NULL)
+ features = no_quarks;
+
+ if (!get_feature_flags (features, &feature_flags))
return;
context = contacts_context_new (self, n_ids, feature_flags,