summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-04-16 18:26:27 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-04-17 14:22:31 +0100
commit9a3f7ce829bf31def0baa19f54bda5a300579667 (patch)
treeab719673e39902a1bfdfd7be88e242969dfe2397
parent22ed228270e7e29e7ede985a198d5c675464be51 (diff)
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.
-rw-r--r--docs/reference/telepathy-glib/telepathy-glib-sections.txt2
-rw-r--r--examples/cm/call/conn.c28
-rw-r--r--examples/cm/contactlist/conn.c6
-rw-r--r--telepathy-glib/base-connection-internal.h8
-rw-r--r--telepathy-glib/base-connection.c10
-rw-r--r--telepathy-glib/presence-mixin.c94
-rw-r--r--telepathy-glib/presence-mixin.h6
-rw-r--r--tests/lib/contacts-conn.c6
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
<TITLE>TpPresenceMixin</TITLE>
TpPresenceMixinInterface
+tp_presence_mixin_init
+tp_presence_mixin_fill_contact_attributes
tp_presence_mixin_emit_presence_update
tp_presence_mixin_emit_one_presence_update
<SUBSECTION Standard>
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
@@ -119,6 +119,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)
{
ExampleCallConnection *self = EXAMPLE_CALL_CONNECTION (object);
@@ -309,6 +321,20 @@ example_call_connection_get_possible_interfaces (void)
}
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 */