From 9a3f7ce829bf31def0baa19f54bda5a300579667 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 16 Apr 2014 18:26:27 +0100 Subject: Decouple TpPresenceMixin from TpBaseConnection again I never liked the idea of putting individual interfaces in TpBaseConnection, and it's actually unnecessary: qdata will work just as well. --- .../telepathy-glib/telepathy-glib-sections.txt | 2 + examples/cm/call/conn.c | 28 +++++++ examples/cm/contactlist/conn.c | 6 ++ telepathy-glib/base-connection-internal.h | 8 -- telepathy-glib/base-connection.c | 10 --- telepathy-glib/presence-mixin.c | 94 ++++++++++++++++++---- telepathy-glib/presence-mixin.h | 6 ++ tests/lib/contacts-conn.c | 6 ++ 8 files changed, 127 insertions(+), 33 deletions(-) diff --git a/docs/reference/telepathy-glib/telepathy-glib-sections.txt b/docs/reference/telepathy-glib/telepathy-glib-sections.txt index 855c45af9..51e14fedf 100644 --- a/docs/reference/telepathy-glib/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib/telepathy-glib-sections.txt @@ -1683,6 +1683,8 @@ tp_presence_status_new tp_presence_status_free TpPresenceMixin TpPresenceMixinInterface +tp_presence_mixin_init +tp_presence_mixin_fill_contact_attributes tp_presence_mixin_emit_presence_update tp_presence_mixin_emit_one_presence_update diff --git a/examples/cm/call/conn.c b/examples/cm/call/conn.c index 3d1c1d3c5..eea43dd06 100644 --- a/examples/cm/call/conn.c +++ b/examples/cm/call/conn.c @@ -118,6 +118,18 @@ set_property (GObject *object, } } +static void +constructed (GObject *object) +{ + void (*chain_up) (GObject *) = + G_OBJECT_CLASS (example_call_connection_parent_class)->constructed; + + if (chain_up != NULL) + chain_up (object); + + tp_presence_mixin_init (TP_BASE_CONNECTION (object)); +} + static void finalize (GObject *object) { @@ -308,6 +320,20 @@ example_call_connection_get_possible_interfaces (void) return interfaces_always_present; } +static void +fill_contact_attributes (TpBaseConnection *conn, + const gchar *dbus_interface, + TpHandle contact, + GVariantDict *attributes) +{ + if (tp_presence_mixin_fill_contact_attributes (conn, + dbus_interface, contact, attributes)) + return; + + ((TpBaseConnectionClass *) example_call_connection_parent_class)-> + fill_contact_attributes (conn, dbus_interface, contact, attributes); +} + static void init_presence (gpointer g_iface, gpointer iface_data) @@ -330,6 +356,7 @@ example_call_connection_class_init ( object_class->get_property = get_property; object_class->set_property = set_property; + object_class->constructed = constructed; object_class->finalize = finalize; g_type_class_add_private (klass, sizeof (ExampleCallConnectionPrivate)); @@ -339,6 +366,7 @@ example_call_connection_class_init ( base_class->create_channel_managers = create_channel_managers; base_class->start_connecting = start_connecting; base_class->shut_down = shut_down; + base_class->fill_contact_attributes = fill_contact_attributes; param_spec = g_param_spec_string ("account", "Account name", "The username of this user", NULL, diff --git a/examples/cm/contactlist/conn.c b/examples/cm/contactlist/conn.c index 307ccdc87..9105a995b 100644 --- a/examples/cm/contactlist/conn.c +++ b/examples/cm/contactlist/conn.c @@ -245,6 +245,10 @@ example_contact_list_connection_fill_contact_attributes (TpBaseConnection *conn, dbus_interface, contact, attributes)) return; + if (tp_presence_mixin_fill_contact_attributes (conn, + dbus_interface, contact, attributes)) + return; + ((TpBaseConnectionClass *) example_contact_list_connection_parent_class)-> fill_contact_attributes (conn, dbus_interface, contact, attributes); } @@ -272,6 +276,8 @@ constructed (GObject *object) g_signal_connect (self->priv->contact_list, "presence-updated", G_CALLBACK (presence_updated_cb), self); + tp_presence_mixin_init (TP_BASE_CONNECTION (object)); + iface = tp_svc_interface_skeleton_new (skel, TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING1); g_dbus_object_skeleton_add_interface (skel, iface); diff --git a/telepathy-glib/base-connection-internal.h b/telepathy-glib/base-connection-internal.h index ae669cc56..5fb387462 100644 --- a/telepathy-glib/base-connection-internal.h +++ b/telepathy-glib/base-connection-internal.h @@ -83,7 +83,6 @@ struct _TpBaseConnectionPrivate _TpGDBusConnection *connection_skeleton; _TpGDBusConnectionInterfaceRequests *requests_skeleton; - _TpGDBusConnectionInterfacePresence1 *presence_skeleton; }; void _tp_base_connection_set_handle_repo (TpBaseConnection *self, @@ -99,13 +98,6 @@ GVariant *_tp_base_connection_dup_contact_attributes ( const gchar * const *interfaces, const gchar * const *assumed_interfaces); -/* TpPresenceMixin */ -void _tp_presence_mixin_init (TpBaseConnection *self); -gboolean _tp_presence_mixin_fill_contact_attributes (TpBaseConnection *self, - const gchar *dbus_interface, - TpHandle contact, - GVariantDict *attributes); - G_END_DECLS #endif diff --git a/telepathy-glib/base-connection.c b/telepathy-glib/base-connection.c index 11d6d86d1..4e8913110 100644 --- a/telepathy-glib/base-connection.c +++ b/telepathy-glib/base-connection.c @@ -439,7 +439,6 @@ tp_base_connection_dispose (GObject *object) g_clear_object (&self->priv->connection_skeleton); g_clear_object (&self->priv->requests_skeleton); - g_clear_object (&self->priv->presence_skeleton); if (G_OBJECT_CLASS (tp_base_connection_parent_class)->dispose) G_OBJECT_CLASS (tp_base_connection_parent_class)->dispose (object); @@ -769,11 +768,6 @@ tp_base_connection_constructed (GObject *object) G_CALLBACK (tp_base_connection_interface_changed_cb), GINT_TO_POINTER (-1)); - if (TP_IS_PRESENCE_MIXIN (self)) - { - _tp_presence_mixin_init (self); - } - /* We don't have any interfaces yet (except for Connection and Requests) * so it's OK that the default for _TpGDBusConnection:interfaces is NULL. */ } @@ -923,10 +917,6 @@ _tp_base_connection_fill_contact_attributes (TpBaseConnection *self, { const gchar *tmp; - if (_tp_presence_mixin_fill_contact_attributes (self, dbus_interface, contact, - attributes)) - return; - if (tp_strdiff (dbus_interface, TP_IFACE_CONNECTION)) { DEBUG ("contact #%u: interface '%s' unhandled", contact, dbus_interface); diff --git a/telepathy-glib/presence-mixin.c b/telepathy-glib/presence-mixin.c index e23cb7e73..fd4ada225 100644 --- a/telepathy-glib/presence-mixin.c +++ b/telepathy-glib/presence-mixin.c @@ -165,11 +165,16 @@ #include "debug-internal.h" #include "base-connection-internal.h" -struct _TpPresenceMixinPrivate +static GQuark +skeleton_quark (void) { - _TpGDBusConnectionInterfacePresence1 *skeleton; -}; + static GQuark q = 0; + if (q == 0) + q = g_quark_from_static_string ("TpPresenceMixin-skeleton"); + + return q; +} static GVariant *construct_presence_map ( const TpPresenceStatusSpec *supported_statuses, @@ -248,15 +253,26 @@ connection_status_changed_cb (TpBaseConnection *self, } } +/** + * tp_presence_mixin_init: + * @self: a #TpBaseConnection that implements #TpPresenceMixinInterface + * + * Implement the Presence interface via this mixin. Call this from + * the #GObjectClass.constructed function of a #TpBaseConnection + * subclass that implements #TpPresenceMixin. + */ void -_tp_presence_mixin_init (TpBaseConnection *self) +tp_presence_mixin_init (TpBaseConnection *self) { + _TpGDBusConnectionInterfacePresence1 *presence_skeleton; TpPresenceMixinInterface *iface = TP_PRESENCE_MIXIN_GET_INTERFACE (self); guint i; - g_assert (iface->get_contact_status != NULL); - g_assert (iface->set_own_status != NULL); - g_assert (iface->statuses != NULL); + g_return_if_fail (TP_IS_BASE_CONNECTION (self)); + g_return_if_fail (TP_IS_PRESENCE_MIXIN (self)); + g_return_if_fail (iface->get_contact_status != NULL); + g_return_if_fail (iface->set_own_status != NULL); + g_return_if_fail (iface->statuses != NULL); for (i = 0; iface->statuses[i].name != NULL; i++) { @@ -278,10 +294,11 @@ _tp_presence_mixin_init (TpBaseConnection *self) } } - self->priv->presence_skeleton = - _tp_gdbus_connection_interface_presence1_skeleton_new (); + presence_skeleton = _tp_gdbus_connection_interface_presence1_skeleton_new (); + g_object_set_qdata_full (G_OBJECT (self), skeleton_quark (), + presence_skeleton, g_object_unref); - g_signal_connect_object (self->priv->presence_skeleton, "handle-set-presence", + g_signal_connect_object (presence_skeleton, "handle-set-presence", G_CALLBACK (tp_presence_mixin_set_presence), self, 0); /* Set the initial properties values, we'll update them once CONNECTED */ @@ -291,7 +308,7 @@ _tp_presence_mixin_init (TpBaseConnection *self) G_CALLBACK (connection_status_changed_cb), NULL); g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (self), - G_DBUS_INTERFACE_SKELETON (self->priv->presence_skeleton)); + G_DBUS_INTERFACE_SKELETON (presence_skeleton)); } /** @@ -309,11 +326,15 @@ tp_presence_mixin_emit_presence_update (TpBaseConnection *self, GHashTable *contact_statuses) { TpPresenceMixinInterface *iface = TP_PRESENCE_MIXIN_GET_INTERFACE (self); + _TpGDBusConnectionInterfacePresence1 *presence_skeleton; DEBUG ("called."); + presence_skeleton = g_object_get_qdata (G_OBJECT (self), skeleton_quark ()); + g_return_if_fail (presence_skeleton != NULL); + _tp_gdbus_connection_interface_presence1_emit_presences_changed ( - self->priv->presence_skeleton, + presence_skeleton, construct_presence_map (iface->statuses, contact_statuses)); } @@ -427,9 +448,13 @@ static void update_statuses_property (TpBaseConnection *self) { TpPresenceMixinInterface *iface = TP_PRESENCE_MIXIN_GET_INTERFACE (self); + _TpGDBusConnectionInterfacePresence1 *presence_skeleton; GVariantBuilder builder; int i; + presence_skeleton = g_object_get_qdata (G_OBJECT (self), skeleton_quark ()); + g_return_if_fail (presence_skeleton != NULL); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{s(ubb)}")); for (i = 0; iface->statuses[i].name != NULL; i++) { @@ -451,7 +476,7 @@ update_statuses_property (TpBaseConnection *self) } _tp_gdbus_connection_interface_presence1_set_statuses ( - self->priv->presence_skeleton, + presence_skeleton, g_variant_builder_end (&builder)); } @@ -459,13 +484,17 @@ static void update_max_status_message_len_property (TpBaseConnection *self) { TpPresenceMixinInterface *iface = TP_PRESENCE_MIXIN_GET_INTERFACE (self); + _TpGDBusConnectionInterfacePresence1 *presence_skeleton; guint max_status_message_length = 0; + presence_skeleton = g_object_get_qdata (G_OBJECT (self), skeleton_quark ()); + g_return_if_fail (presence_skeleton != NULL); + if (iface->get_maximum_status_message_length != NULL) max_status_message_length = iface->get_maximum_status_message_length (self); _tp_gdbus_connection_interface_presence1_set_maximum_status_message_length ( - self->priv->presence_skeleton, max_status_message_length); + presence_skeleton, max_status_message_length); } static gboolean @@ -555,8 +584,43 @@ construct_presence_map (const TpPresenceStatusSpec *supported_statuses, return g_variant_builder_end (&builder); } +/** + * tp_presence_mixin_fill_contact_attributes: + * @self: a connection that implements #TpPresenceMixin + * @dbus_interface: the interface in which the client is interested + * @contact: a contact's handle + * @attributes: used to return the attributes of @contact + * + * If this mixin implements @dbus_interface, fill in the attributes + * for @contact and return %TRUE. + * + * Typical usage is something like this: + * + * |[ + * static void + * my_fill_contact_attributes (TpBaseConnection *base, + * ...) + * { + * if (!tp_strdiff (dbus_interface, INTERFACE_THAT_I_IMPLEMENT)) + * { + * // ... fill them in + * return; + * } + * // ... similar calls for any other interfaces + * + * if (tp_presence_mixin_fill_contact_attributes (base, ...)) + * return; + * // ... similar calls for any other mixins + * + * TP_BASE_CONNECTION_CLASS (my_connection_parent_class)-> + * fill_contact_attributes (base, ...); + * } + * ]| + * + * Returns: %TRUE if @dbus_interface was handled + */ gboolean -_tp_presence_mixin_fill_contact_attributes (TpBaseConnection *self, +tp_presence_mixin_fill_contact_attributes (TpBaseConnection *self, const gchar *dbus_interface, TpHandle contact, GVariantDict *attributes) diff --git a/telepathy-glib/presence-mixin.h b/telepathy-glib/presence-mixin.h index ed4483487..c9d97777e 100644 --- a/telepathy-glib/presence-mixin.h +++ b/telepathy-glib/presence-mixin.h @@ -148,6 +148,12 @@ void tp_presence_mixin_emit_one_presence_update (TpBaseConnection *self, TpHandle handle, const TpPresenceStatus *status); +void tp_presence_mixin_init (TpBaseConnection *self); +gboolean tp_presence_mixin_fill_contact_attributes (TpBaseConnection *self, + const gchar *dbus_interface, + TpHandle contact, + GVariantDict *attributes); + G_END_DECLS #endif /* #ifndef __TP_PRESENCE_MIXIN_H__ */ diff --git a/tests/lib/contacts-conn.c b/tests/lib/contacts-conn.c index 539c9bb8f..d4a3ebc13 100644 --- a/tests/lib/contacts-conn.c +++ b/tests/lib/contacts-conn.c @@ -298,6 +298,10 @@ tp_tests_contacts_connection_fill_contact_attributes (TpBaseConnection *base, dbus_interface, contact, attributes)) return; + if (tp_presence_mixin_fill_contact_attributes (base, + dbus_interface, contact, attributes)) + return; + ((TpBaseConnectionClass *) tp_tests_contacts_connection_parent_class)-> fill_contact_attributes (base, dbus_interface, contact, attributes); } @@ -412,6 +416,8 @@ constructed (GObject *object) self->priv->list_manager = g_object_new (TP_TESTS_TYPE_CONTACT_LIST_MANAGER, "connection", self, NULL); + + tp_presence_mixin_init (TP_BASE_CONNECTION (self)); } /* Must match TpTestsContactsConnectionPresenceStatusIndex in the .h */ -- cgit v1.2.3