From a157e2b6fa0045ea8d2cd407333a5f81422708bf Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Sun, 16 Sep 2012 18:04:16 +0300 Subject: [PATCH] telepathy: add contact info interface Just the boilerplate code, no functionality yet. --- src/telepathy/telepathy-buddy.c | 140 ++++++++++++++++++++++++++++++++++- src/telepathy/telepathy-connection.c | 46 +++++++++++- src/telepathy/telepathy-private.h | 5 ++ src/telepathy/telepathy-search.c | 19 +++-- 4 files changed, 199 insertions(+), 11 deletions(-) diff --git a/src/telepathy/telepathy-buddy.c b/src/telepathy/telepathy-buddy.c index 617ccee6..8ce5012e 100644 --- a/src/telepathy/telepathy-buddy.c +++ b/src/telepathy/telepathy-buddy.c @@ -248,9 +248,11 @@ static GStrv dup_contact_groups(TpBaseContactList *contact_list, static void contact_group_list_iface_init(TpContactGroupListInterface *iface) { - iface->dup_groups = dup_groups; - iface->dup_group_members = dup_group_members; - iface->dup_contact_groups = dup_contact_groups; +#define IMPLEMENT(x) iface->x = x + IMPLEMENT(dup_groups); + IMPLEMENT(dup_group_members); + IMPLEMENT(dup_contact_groups); +#undef IMPLEMENT } /* create new contact list object */ @@ -309,6 +311,138 @@ guint sipe_telepathy_buddy_get_presence(SipeContactList *contact_list, return(buddy->activity); } +static void get_contact_info(TpSvcConnectionInterfaceContactInfo *iface, + SIPE_UNUSED_PARAMETER const GArray *contacts, + DBusGMethodInvocation *context) +{ + TpBaseConnection *base = TP_BASE_CONNECTION(iface); + + TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context); + + SIPE_DEBUG_INFO_NOFORMAT("SipeContactInfo::get_contact_info called"); +} + +static void refresh_contact_info(TpSvcConnectionInterfaceContactInfo *iface, + SIPE_UNUSED_PARAMETER const GArray *contacts, + DBusGMethodInvocation *context) +{ + TpBaseConnection *base = TP_BASE_CONNECTION(iface); + + TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context); + + SIPE_DEBUG_INFO_NOFORMAT("SipeContactInfo::refresh_contact_info called"); +} + +static void request_contact_info(TpSvcConnectionInterfaceContactInfo *iface, + SIPE_UNUSED_PARAMETER guint contact, + DBusGMethodInvocation *context) +{ + TpBaseConnection *base = TP_BASE_CONNECTION(iface); + + TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context); + + SIPE_DEBUG_INFO_NOFORMAT("SipeContactInfo::request_contact_info called"); +} + +static void set_contact_info(TpSvcConnectionInterfaceContactInfo *iface, + SIPE_UNUSED_PARAMETER const GPtrArray *contact_info, + DBusGMethodInvocation *context) +{ + TpBaseConnection *base = TP_BASE_CONNECTION(iface); + + TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context); + + SIPE_DEBUG_INFO_NOFORMAT("SipeContactInfo::set_contact_info called"); +} + +void sipe_telepathy_contact_info_iface_init(gpointer g_iface, + SIPE_UNUSED_PARAMETER gpointer iface_data) +{ + TpSvcConnectionInterfaceContactInfoClass *klass = g_iface; + +#define IMPLEMENT(x) tp_svc_connection_interface_contact_info_implement_##x( \ + klass, x) + IMPLEMENT(get_contact_info); + IMPLEMENT(refresh_contact_info); + IMPLEMENT(request_contact_info); + IMPLEMENT(set_contact_info); +#undef IMPLEMENT +} + +static const gchar *const sipe_to_vcard_field[SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY + 1] = { +/* SIPE_BUDDY_INFO_DISPLAY_NAME */ "fn", +/* SIPE_BUDDY_INFO_JOB_TITLE */ "title", +/* SIPE_BUDDY_INFO_CITY */ NULL, +/* SIPE_BUDDY_INFO_STATE */ NULL, +/* SIPE_BUDDY_INFO_OFFICE */ NULL, +/* SIPE_BUDDY_INFO_DEPARTMENT */ NULL, +/* SIPE_BUDDY_INFO_COUNTRY */ NULL, +/* SIPE_BUDDY_INFO_WORK_PHONE */ "tel", +/* SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY */ NULL, +/* SIPE_BUDDY_INFO_COMPANY */ "org", +/* SIPE_BUDDY_INFO_EMAIL */ "email", +/* SIPE_BUDDY_INFO_SITE */ NULL, +/* SIPE_BUDDY_INFO_ZIPCODE */ NULL, +/* SIPE_BUDDY_INFO_STREET */ NULL, +/* SIPE_BUDDY_INFO_MOBILE_PHONE */ NULL, +/* SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY */ NULL, +/* SIPE_BUDDY_INFO_HOME_PHONE */ NULL, +/* SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY */ NULL, +/* SIPE_BUDDY_INFO_OTHER_PHONE */ NULL, +/* SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY */ NULL, +/* SIPE_BUDDY_INFO_CUSTOM1_PHONE */ NULL, +/* SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY */ NULL, +}; + +GPtrArray *sipe_telepathy_contact_info_fields(void) +{ + GPtrArray *fields = dbus_g_type_specialized_construct(TP_ARRAY_TYPE_FIELD_SPECS); + guint i; + + SIPE_DEBUG_INFO_NOFORMAT("SipeContactInfo::contact_info_fields called"); + + for (i = 0; i <= SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY; i++) { + const gchar *vcard_name = sipe_to_vcard_field[i]; + GValueArray *va; + + /* unsupported field */ + if (!vcard_name) + continue; + + va = tp_value_array_build(4, + G_TYPE_STRING, vcard_name, + G_TYPE_STRV, NULL, + G_TYPE_UINT, 0, /* tp_flags */ + G_TYPE_UINT, 1, /* max_times */ + G_TYPE_INVALID); + g_ptr_array_add (fields, va); + } + + return(fields); +} + +/* TpDBusPropertiesMixinPropImpl is a broken typedef */ +gpointer sipe_telepathy_contact_info_props(void) +{ + static TpDBusPropertiesMixinPropImpl props[] = { + { + .name = "ContactInfoFlags", + .getter_data = GUINT_TO_POINTER(0), + /* @TODO .getter_data = GUINT_TO_POINTER(TP_CONTACT_INFO_FLAG_CAN_SET), */ + .setter_data = NULL, + }, + { + .name = "SupportedFields", + .getter_data = NULL, + .setter_data = NULL, + }, + { + .name = NULL + } + }; + return(props); +} + /* * Backend adaptor functions */ diff --git a/src/telepathy/telepathy-connection.c b/src/telepathy/telepathy-connection.c index 3244ae86..a38cdcae 100644 --- a/src/telepathy/telepathy-connection.c +++ b/src/telepathy/telepathy-connection.c @@ -47,6 +47,7 @@ G_BEGIN_DECLS */ typedef struct _SipeConnectionClass { TpBaseConnectionClass parent_class; + TpDBusPropertiesMixinClass properties_class; TpContactsMixinClass contacts_mixin; TpPresenceMixinClass presence_mixin; } SipeConnectionClass; @@ -70,6 +71,8 @@ typedef struct _SipeConnection { gchar *user_agent; gchar *authentication; gboolean is_disconnecting; + + GPtrArray *contact_info_fields; } SipeConnection; #define SIPE_PUBLIC_TO_CONNECTION sipe_public->backend_private->connection @@ -98,12 +101,16 @@ G_DEFINE_TYPE_WITH_CODE(SipeConnection, tp_contacts_mixin_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS, tp_base_contact_list_mixin_groups_iface_init); + G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO, + sipe_telepathy_contact_info_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST, tp_base_contact_list_mixin_list_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE, tp_presence_mixin_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - tp_presence_mixin_simple_presence_iface_init) + tp_presence_mixin_simple_presence_iface_init); + G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); ) @@ -361,8 +368,25 @@ static void aliasing_fill_contact_attributes(GObject *object, } } +static void contact_info_properties_getter(GObject *object, + SIPE_UNUSED_PARAMETER GQuark interface, + GQuark name, + GValue *value, + gpointer getter_data) +{ + GQuark fields = g_quark_from_static_string("SupportedFields"); + + if (name == fields) + g_value_set_boxed(value, + SIPE_CONNECTION(object)->contact_info_fields); + else + g_value_set_uint(value, + GPOINTER_TO_UINT(getter_data)); +} + static void sipe_connection_constructed(GObject *object) { + SipeConnection *self = SIPE_CONNECTION(object); TpBaseConnection *base = TP_BASE_CONNECTION(object); void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_connection_parent_class)->constructed; @@ -383,6 +407,8 @@ static void sipe_connection_constructed(GObject *object) G_STRUCT_OFFSET(SipeConnection, presence_mixin)); tp_presence_mixin_simple_presence_register_with_contacts_mixin(object); + + self->contact_info_fields = sipe_telepathy_contact_info_fields(); } static void sipe_connection_finalize(GObject *object) @@ -392,6 +418,8 @@ static void sipe_connection_finalize(GObject *object) SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::finalize"); tp_contacts_mixin_finalize(object); + tp_presence_mixin_finalize(object); + g_boxed_free(TP_ARRAY_TYPE_FIELD_SPECS, self->contact_info_fields); g_free(self->authentication); g_free(self->user_agent); @@ -411,6 +439,7 @@ static const gchar *interfaces_always_present[] = { /* @TODO */ TP_IFACE_CONNECTION_INTERFACE_ALIASING, TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, TP_IFACE_CONNECTION_INTERFACE_CONTACTS, TP_IFACE_CONNECTION_INTERFACE_PRESENCE, @@ -423,6 +452,17 @@ static void sipe_connection_class_init(SipeConnectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); TpBaseConnectionClass *base_class = TP_BASE_CONNECTION_CLASS(klass); + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { + /* 0 */ + .name = TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, + .getter = contact_info_properties_getter, + .setter = NULL, + }, + }; + + /* initalize non-constant fields */ + prop_interfaces[0].props = sipe_telepathy_contact_info_props(); SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::class_init"); @@ -436,6 +476,10 @@ static void sipe_connection_class_init(SipeConnectionClass *klass) base_class->interfaces_always_present = interfaces_always_present; + klass->properties_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init(object_class, + G_STRUCT_OFFSET(SipeConnectionClass, + properties_class)); tp_contacts_mixin_class_init(object_class, G_STRUCT_OFFSET(SipeConnectionClass, contacts_mixin)); diff --git a/src/telepathy/telepathy-private.h b/src/telepathy/telepathy-private.h index 09641d2a..03d0007c 100644 --- a/src/telepathy/telepathy-private.h +++ b/src/telepathy/telepathy-private.h @@ -60,6 +60,11 @@ void sipe_telepathy_buddy_set_alias(struct _SipeContactList *contact_list, const gchar *alias); guint sipe_telepathy_buddy_get_presence(struct _SipeContactList *contact_list, guint contact); +void sipe_telepathy_contact_info_iface_init(gpointer g_iface, + gpointer iface_data); +GPtrArray *sipe_telepathy_contact_info_fields(void); +/* TpDBusPropertiesMixinPropImpl is a broken typedef */ +gpointer sipe_telepathy_contact_info_props(void); /* connection */ struct _TpBaseConnection *sipe_telepathy_connection_new(struct _TpBaseProtocol *protocol, diff --git a/src/telepathy/telepathy-search.c b/src/telepathy/telepathy-search.c index e21e5de7..83d62660 100644 --- a/src/telepathy/telepathy-search.c +++ b/src/telepathy/telepathy-search.c @@ -105,7 +105,7 @@ G_DEFINE_TYPE_WITH_CODE(SipeSearchManager, /* * Search Manager class - type definition */ -static void contact_search_iface_init (gpointer, gpointer); +static void contact_search_iface_init(gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE(SipeSearchChannel, sipe_search_channel, TP_TYPE_BASE_CHANNEL, @@ -245,12 +245,14 @@ static void channel_manager_iface_init(gpointer g_iface, { TpChannelManagerIface *iface = g_iface; - iface->foreach_channel = foreach_channel; - iface->type_foreach_channel_class = type_foreach_channel_class; - iface->create_channel = create_channel; - iface->request_channel = create_channel; +#define IMPLEMENT(x, y) iface->x = y + IMPLEMENT(foreach_channel, foreach_channel); + IMPLEMENT(type_foreach_channel_class, type_foreach_channel_class); + IMPLEMENT(create_channel, create_channel); + IMPLEMENT(request_channel, create_channel); /* Ensuring these channels doesn't really make much sense. */ - iface->ensure_channel = NULL; + IMPLEMENT(ensure_channel, NULL); +#undef IMPLEMENT } /* create new search manager object */ @@ -512,8 +514,11 @@ static void contact_search_iface_init(gpointer g_iface, { TpSvcChannelTypeContactSearchClass *klass = g_iface; - tp_svc_channel_type_contact_search_implement_search(klass, search_channel_search); +#define IMPLEMENT(x) tp_svc_channel_type_contact_search_implement_##x( \ + klass, search_channel_##x) + IMPLEMENT(search); /* we don't support stopping a search */ +#undef IMPLEMENT } /* create new search channel object */ -- 2.11.4.GIT