[Telepathy-commits] [telepathy-glib/master] TpMessageMixin: convert API to fit the new D-Bus API better
Simon McVittie
simon.mcvittie at collabora.co.uk
Thu Dec 18 10:41:38 PST 2008
20080512144848-53eee-2e380fb33539204db70d5f1bfd76e3d861bd0c5b.gz
---
telepathy-glib/message-mixin.c | 425 ++++++++++++++++++++++++++++++++--------
telepathy-glib/message-mixin.h | 16 +-
2 files changed, 347 insertions(+), 94 deletions(-)
diff --git a/telepathy-glib/message-mixin.c b/telepathy-glib/message-mixin.c
index 0a2397e..50c4b69 100644
--- a/telepathy-glib/message-mixin.c
+++ b/telepathy-glib/message-mixin.c
@@ -69,13 +69,55 @@
struct _TpMessageMixinPrivate
{
TpMessageMixinSendImpl send_message;
+ GArray *msg_types;
- TpHandleRepoIface *contact_repo;
+ /* Receiving */
+ TpMessageMixinCleanUpReceivedImpl clean_up_received;
guint recv_id;
-
GQueue *pending;
+};
- GArray *msg_types;
+
+static const char * const forbidden_keys[] = {
+ "pending-message-id",
+ NULL
+};
+
+
+static const char * const body_only[] = {
+ "alternative",
+ "type",
+ "content",
+ "identifier",
+ "needs-retrieval",
+ "truncated",
+ "size",
+ NULL
+};
+
+
+static const char * const body_only_incoming[] = {
+ "needs-retrieval",
+ "truncated",
+ "size",
+ NULL
+};
+
+
+static const char * const headers_only[] = {
+ "message-type",
+ "message-sender",
+ "message-sent",
+ "message-received",
+ NULL
+};
+
+
+static const char * const headers_only_incoming[] = {
+ "message-sender",
+ "message-sent",
+ "message-received",
+ NULL
};
#define TP_MESSAGE_MIXIN_CLASS_OFFSET_QUARK \
@@ -119,6 +161,8 @@ tp_message_mixin_class_get_offset_quark (void)
* <!--no documentation beyond Returns: needed-->
*
* Returns: the quark used for storing mixin offset on a GObject
+ *
+ * @since 0.7.9
*/
static GQuark
tp_message_mixin_get_offset_quark (void)
@@ -166,13 +210,24 @@ tp_message_mixin_class_init (GObjectClass *obj_cls,
typedef struct {
guint32 id;
- TpHandle sender;
- time_t timestamp;
- TpChannelTextMessageType message_type;
GPtrArray *parts;
+ gpointer cleanup_data;
+ /* We replace the header (the first part) with a copy, so we can safely
+ * add to it. This means we need to hang on to the original header, so we
+ * can pass it back to the caller. */
+ GHashTable *orig_header;
+
+ /* For the Text API */
+ guint old_timestamp;
+ TpHandle old_sender; /* borrowed from header, so not reffed */
+ TpChannelTextMessageType old_message_type;
TpChannelTextMessageFlags old_flags;
gchar *old_text;
- /* A non-NULL reference until we have been queued, NULL afterwards */
+
+ /* GValues that need freeing later */
+ GValueArray *added_values;
+
+ /* A non-NULL reference until we have been queued; borrowed afterwards */
GObject *target;
} PendingItem;
@@ -190,43 +245,32 @@ pending_item_id_equals_data (gconstpointer item,
static void
pending_item_free (PendingItem *pending,
- TpHandleRepoIface *contact_repo)
+ GObject *obj,
+ TpMessageMixinCleanUpReceivedImpl clean_up_received)
{
- guint i;
+ g_assert (clean_up_received != NULL);
+ g_assert (pending->parts->len >= 1);
- if (pending->sender != 0)
- tp_handle_unref (contact_repo, pending->sender);
+ g_hash_table_destroy (g_ptr_array_index (pending->parts, 0));
+ g_ptr_array_index (pending->parts, 0) = pending->orig_header;
+ pending->orig_header = NULL;
- if (pending->parts != NULL)
- {
- for (i = 0; i < pending->parts->len; i++)
- {
- g_hash_table_destroy (g_ptr_array_index (pending->parts, i));
- }
-
- g_ptr_array_free (pending->parts, TRUE);
- }
+ clean_up_received (obj, pending->parts, pending->cleanup_data);
g_free (pending->old_text);
+ pending->old_text = NULL;
- g_slice_free (PendingItem, pending);
-}
-
+ g_value_array_free (pending->added_values);
+ pending->added_values = NULL;
-static inline const gchar *
-value_force_string (const GValue *value)
-{
- if (value == NULL || !G_VALUE_HOLDS_STRING (value))
- return NULL;
-
- return g_value_get_string (value);
+ g_slice_free (PendingItem, pending);
}
static inline void
nullify_hash (GHashTable **hash)
{
- if (*hash != NULL)
+ if (*hash == NULL)
return;
g_hash_table_destroy (*hash);
@@ -246,10 +290,14 @@ subtract_from_hash (gpointer key,
static TpChannelTextMessageFlags
parts_to_text (const GPtrArray *parts,
- GString *buffer)
+ GString *buffer,
+ TpChannelTextMessageType *out_type,
+ TpHandle *out_sender,
+ guint *out_timestamp)
{
guint i;
TpChannelTextMessageFlags flags = 0;
+ GHashTable *header = g_ptr_array_index (parts, 0);
/* Lazily created hash tables, used as a sets: keys are borrowed
* "alternative" string values from @parts, value == key. */
/* Alternative IDs for which we have already extracted an alternative */
@@ -260,13 +308,18 @@ parts_to_text (const GPtrArray *parts,
* Channel_Text_Message_Flag_Non_Text_Content must be set. */
GHashTable *alternatives_needed = NULL;
- for (i = 0; i < parts->len; i++)
+ /* If the message is on an extended interface or only contains headers,
+ * definitely set the "your client is too old" flag. */
+ if (parts->len <= 1 || g_hash_table_lookup (header, "interface") != NULL)
+ {
+ flags |= TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT;
+ }
+
+ for (i = 1; i < parts->len; i++)
{
GHashTable *part = g_ptr_array_index (parts, i);
- const gchar *type = value_force_string (g_hash_table_lookup (part,
- "type"));
- const gchar *alternative = value_force_string (g_hash_table_lookup (part,
- "alternative"));
+ const gchar *type = tp_asv_get_string (part, "type");
+ const gchar *alternative = tp_asv_get_string (part, "alternative");
DEBUG ("Parsing part %u, type %s, alternative %s", i, type, alternative);
@@ -374,6 +427,33 @@ parts_to_text (const GPtrArray *parts,
if (alternatives_used != NULL)
g_hash_table_destroy (alternatives_used);
+ if (out_type != NULL)
+ {
+ /* The fallback behaviour of tp_asv_get_uint32 is OK here, because
+ * message type NORMAL is zero */
+ *out_type = tp_asv_get_uint32 (header, "message-type", NULL);
+ }
+
+ if (out_sender != NULL)
+ {
+ /* The fallback behaviour of tp_asv_get_uint32 is OK here - if there's
+ * no good sender, then 0 is the least bad */
+ *out_sender = tp_asv_get_uint32 (header, "message-sender", NULL);
+ }
+
+ if (out_timestamp != NULL)
+ {
+ /* The fallback behaviour of tp_asv_get_uint32 is OK here - we assume
+ * that we won't legitimately receive messages from 1970-01-01 :-) */
+ *out_timestamp = tp_asv_get_uint32 (header, "message-sent", NULL);
+
+ if (*out_timestamp == 0)
+ *out_timestamp = tp_asv_get_uint32 (header, "message-received", NULL);
+
+ if (*out_timestamp == 0)
+ *out_timestamp = time (NULL);
+ }
+
return flags;
}
@@ -382,24 +462,58 @@ parts_to_text (const GPtrArray *parts,
* tp_message_mixin_implement_sending:
* @obj: An instance of the implementation that uses this mixin
* @send: An implementation of SendMessage()
+ * @n_types: Number of supported message types
+ * @types: @n_types supported message types
+ *
+ * Set the callback used to implement SendMessage, and the types of message
+ * that can be sent
*
*/
void
tp_message_mixin_implement_sending (GObject *object,
- TpMessageMixinSendImpl send)
+ TpMessageMixinSendImpl send,
+ guint n_types,
+ const TpChannelTextMessageType *types)
{
TpMessageMixin *mixin = TP_MESSAGE_MIXIN (object);
g_return_if_fail (mixin->priv->send_message == NULL);
mixin->priv->send_message = send;
+
+ if (mixin->priv->msg_types->len > 0)
+ g_array_remove_range (mixin->priv->msg_types, 0,
+ mixin->priv->msg_types->len);
+
+ g_assert (mixin->priv->msg_types->len == 0);
+ g_array_append_vals (mixin->priv->msg_types, types, n_types);
}
/**
+ * TpMessageMixinCleanUpReceivedImpl:
+ * @object: An instance of the implementation that uses this mixin
+ * @parts: An array of GHashTable containing a message
+ *
+ * Assume that @parts was passed to tp_message_mixin_take_received(),
+ * clean up any allocations or handle references that would have occurred
+ * when the message was received, and free the parts and the array.
+ *
+ * This typically means unreferencing any handles in the array of hash tables
+ * (notably "message-sender"), destroying the hash tables, and freeing the
+ * pointer array.
+ *
+ * (The #TpMessageMixin code can't do this automatically, because the
+ * extensibility of the API means that the mixin doesn't
+ * know which integers are handles and which are just numbers.)
+ */
+
+
+/**
* tp_message_mixin_init:
* @obj: An instance of the implementation that uses this mixin
* @offset: The byte offset of the TpMessageMixin within the object structure
* @contact_repo: The connection's %TP_HANDLE_TYPE_CONTACT repository
+ * @clean_up_received:
*
* Initialize the mixin. Should be called from the implementation's
* instance init function like so:
@@ -407,13 +521,14 @@ tp_message_mixin_implement_sending (GObject *object,
* <informalexample><programlisting>
* tp_message_mixin_init ((GObject *) self,
* G_STRUCT_OFFSET (SomeObject, message_mixin),
- * self->contact_repo);
+ * self->contact_repo,
+ * some_object_clean_up_received);
* </programlisting></informalexample>
*/
void
tp_message_mixin_init (GObject *obj,
gsize offset,
- TpHandleRepoIface *contact_repo)
+ TpMessageMixinCleanUpReceivedImpl clean_up_received)
{
TpMessageMixin *mixin;
@@ -428,10 +543,10 @@ tp_message_mixin_init (GObject *obj,
mixin->priv = g_slice_new0 (TpMessageMixinPrivate);
mixin->priv->pending = g_queue_new ();
- mixin->priv->contact_repo = contact_repo;
mixin->priv->recv_id = 0;
mixin->priv->msg_types = g_array_sized_new (FALSE, FALSE, sizeof (guint),
NUM_TP_CHANNEL_TEXT_MESSAGE_TYPES);
+ mixin->priv->clean_up_received = clean_up_received;
}
static void
@@ -442,7 +557,7 @@ tp_message_mixin_clear (GObject *obj)
while ((item = g_queue_pop_head (mixin->priv->pending)) != NULL)
{
- pending_item_free (item, mixin->priv->contact_repo);
+ pending_item_free (item, obj, mixin->priv->clean_up_received);
}
}
@@ -511,7 +626,8 @@ tp_message_mixin_acknowledge_pending_messages_async (
g_queue_remove (mixin->priv->pending, item);
- pending_item_free (item, mixin->priv->contact_repo);
+ pending_item_free (item, (GObject *) iface,
+ mixin->priv->clean_up_received);
}
g_free (nodes);
@@ -541,18 +657,21 @@ tp_message_mixin_list_pending_messages_async (TpSvcChannelTypeText *iface,
GValue val = { 0, };
guint flags;
GString *text;
+ TpChannelTextMessageType type;
+ TpHandle sender;
+ guint timestamp;
text = g_string_new ("");
- flags = parts_to_text (msg->parts, text);
+ flags = parts_to_text (msg->parts, text, &type, &sender, ×tamp);
g_value_init (&val, pending_type);
g_value_take_boxed (&val,
dbus_g_type_specialized_construct (pending_type));
dbus_g_type_struct_set (&val,
0, msg->id,
- 1, msg->timestamp,
- 2, msg->sender,
- 3, msg->message_type,
+ 1, timestamp,
+ 2, sender,
+ 3, type,
4, flags,
5, text->str,
G_MAXUINT);
@@ -579,7 +698,8 @@ tp_message_mixin_list_pending_messages_async (TpSvcChannelTypeText *iface,
i = msg->id;
g_array_append_val (ids, i);
g_queue_delete_link (mixin->priv->pending, cur);
- pending_item_free (msg, mixin->priv->contact_repo);
+ pending_item_free (msg, (GObject *) iface,
+ mixin->priv->clean_up_received);
cur = next;
}
@@ -690,16 +810,13 @@ queue_pending (gpointer data)
GObject *object = pending->target;
TpMessageMixin *mixin = TP_MESSAGE_MIXIN (object);
- pending->target = NULL;
-
g_queue_push_tail (mixin->priv->pending, pending);
tp_svc_channel_type_text_emit_received (object, pending->id,
- pending->timestamp, pending->sender, pending->message_type,
+ pending->old_timestamp, pending->old_sender, pending->old_message_type,
pending->old_flags, pending->old_text);
tp_svc_channel_interface_messages_emit_message_received (object,
- pending->id, pending->timestamp, pending->sender, pending->message_type,
pending->parts);
g_object_unref (object);
@@ -711,49 +828,93 @@ queue_pending (gpointer data)
/**
* tp_message_mixin_take_received:
* @object: a channel with this mixin
- * @timestamp: the time the message was received (if 0, time (NULL) will be
- * used)
- * @sender: an owned reference to the handle of the sender, which is stolen
- * by the message mixin
- * @message_type: the type of message
- * @content: the content of the message, which is stolen by the message mixin
+ * @parts: the content of the message, which is stolen by the message mixin and
+ * must not be modified or freed until the
+ * #TpMessageMixinCleanUpReceivedImpl is called. This is a non-empty array of
+ * GHashTables, the first of which contains headers (which must not include
+ * "pending-message-id").
+ * @user_data: implementation-specific data which will be passed to the
+ * #TpMessageMixinCleanUpReceivedImpl
*
* Receive a message into the pending messages queue, where it will stay
* until acknowledged, and emit the ReceivedMessage signal. Also emit the
* Received signal if appropriate.
*
- * Note that the sender and content arguments are *not* copied, and the caller
- * loses ownership of them (this is to avoid lengthy and unnecessary copying
- * of the content).
+ * It is an error to call this method if a %NULL
+ * #TpMessageMixinCleanUpReceivedImpl was passed to tp_message_mixin_init().
*
* Returns: the message ID
*/
guint
tp_message_mixin_take_received (GObject *object,
- time_t timestamp,
- TpHandle sender,
- TpChannelTextMessageType message_type,
- GPtrArray *content)
+ GPtrArray *parts,
+ gpointer user_data)
{
TpMessageMixin *mixin = TP_MESSAGE_MIXIN (object);
- PendingItem *pending = g_slice_new0 (PendingItem);
+ PendingItem *pending;
GString *text;
+ GHashTable *header;
+ GValue v = { 0 };
- if (timestamp == 0)
- timestamp = time (NULL);
+ g_return_val_if_fail (mixin->priv->clean_up_received != NULL, 0);
+ g_return_val_if_fail (parts->len >= 1, 0);
- DEBUG ("%p: time %u, sender %u, type %u, %u parts",
- object, (guint) timestamp, sender, message_type, content->len);
+ header = g_ptr_array_index (parts, 0);
+
+ g_return_val_if_fail (g_hash_table_lookup (header, "pending-message-id")
+ == NULL, 0);
+ pending = g_slice_new0 (PendingItem);
/* FIXME: we don't check for overflow, so in highly pathological cases we
* might end up with multiple messages with the same ID */
pending->id = mixin->priv->recv_id++;
- pending->sender = sender;
- pending->timestamp = timestamp;
- pending->message_type = message_type;
- pending->parts = content;
+ pending->parts = parts;
+ pending->cleanup_data = user_data;
+
+ /* We replace the header (the first part) with a copy, so we can safely
+ * add to it. This means we need to hang on to the original header, so we
+ * can pass it back to the caller for destruction */
+ pending->orig_header = header;
+ /* The keys are either static strings in this file, or borrowed from
+ * the orig_header - in either case, there's no need to free them. The
+ * values are either borrowed from the orig_header, or from the
+ * PendingItem's added_values array. */
+ header = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+ tp_g_hash_table_update (header, pending->orig_header, NULL, NULL);
+ g_ptr_array_index (parts, 0) = header;
+
+ /* Now that header is fully under our control, we can fill in any missing
+ * keys */
+ pending->added_values = g_value_array_new (1);
+ g_value_init (&v, G_TYPE_UINT);
+ g_value_array_append (pending->added_values, &v);
+ g_value_unset (&v);
+ g_value_set_uint (pending->added_values->values + 0, pending->id);
+ g_hash_table_insert (header, "pending-message-id",
+ pending->added_values->values + 0);
+
+ /* Provide a message-received header if necessary - it's easy */
+ if (tp_asv_get_uint32 (header, "message-received", NULL) == 0)
+ {
+ guint i = pending->added_values->n_values;
+
+ g_value_init (&v, G_TYPE_UINT);
+ g_value_array_append (pending->added_values, &v);
+ g_value_unset (&v);
+ g_value_set_uint (pending->added_values->values + i, time (NULL));
+ g_hash_table_insert (header, "message-received",
+ pending->added_values->values + i);
+ }
+
text = g_string_new ("");
- pending->old_flags = parts_to_text (content, text);
+ pending->old_flags = parts_to_text (parts, text,
+ &(pending->old_message_type), &(pending->old_sender),
+ &(pending->old_timestamp));
+
+ DEBUG ("%p: time %u, sender %u, type %u, %u parts",
+ object, (guint) (pending->old_timestamp), pending->old_sender,
+ pending->old_message_type, parts->len);
+
pending->old_text = g_string_free (text, FALSE);
/* We don't actually add the pending message to the queue immediately,
@@ -792,6 +953,7 @@ tp_message_mixin_sent (GObject *object,
time_t now = time (NULL);
GString *string;
guint i;
+ TpChannelTextMessageType message_type;
g_return_if_fail (mixin != NULL);
g_return_if_fail (object != NULL);
@@ -818,10 +980,10 @@ tp_message_mixin_sent (GObject *object,
/* emit Sent and MessageSent */
tp_svc_channel_interface_messages_emit_message_sent (object,
- message->message_type, message->parts, token);
+ message->parts, token);
string = g_string_new ("");
- parts_to_text (message->parts, string);
- tp_svc_channel_type_text_emit_sent (object, now, message->message_type,
+ parts_to_text (message->parts, string, &message_type, NULL, NULL);
+ tp_svc_channel_type_text_emit_sent (object, now, message_type,
string->str);
g_string_free (string, TRUE);
@@ -871,7 +1033,17 @@ tp_message_mixin_send_async (TpSvcChannelTypeText *iface,
return;
}
- parts = g_ptr_array_sized_new (1);
+ parts = g_ptr_array_sized_new (2);
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, message_type);
+ g_hash_table_insert (table, "message-type", value);
+
+ g_ptr_array_add (parts, table);
+
table = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) tp_g_value_slice_free);
@@ -887,7 +1059,6 @@ tp_message_mixin_send_async (TpSvcChannelTypeText *iface,
message = g_slice_new0 (TpMessageMixinOutgoingMessage);
message->flags = 0;
- message->message_type = message_type;
message->parts = parts;
message->priv = g_slice_new0 (TpMessageMixinOutgoingMessagePrivate);
message->priv->context = context;
@@ -899,13 +1070,15 @@ tp_message_mixin_send_async (TpSvcChannelTypeText *iface,
static void
tp_message_mixin_send_message_async (TpSvcChannelInterfaceMessages *iface,
- guint message_type,
const GPtrArray *parts,
guint flags,
DBusGMethodInvocation *context)
{
TpMessageMixin *mixin = TP_MESSAGE_MIXIN (iface);
TpMessageMixinOutgoingMessage *message;
+ GHashTable *header;
+ guint i;
+ const char * const *iter;
if (mixin->priv->send_message == NULL)
{
@@ -913,13 +1086,93 @@ tp_message_mixin_send_message_async (TpSvcChannelInterfaceMessages *iface,
return;
}
+ /* it must have at least a header part */
+ if (parts->len < 1)
+ {
+ GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Cannot send a message that does not have at least one part" };
+
+ dbus_g_method_return_error (context, &e);
+ return;
+ }
+
+ header = g_ptr_array_index (parts, 0);
+
+ for (i = 0; i < parts->len; i++)
+ {
+ for (iter = forbidden_keys; *iter != NULL; iter++)
+ {
+ if (g_hash_table_lookup (header, *iter) != NULL)
+ {
+ GError *error = g_error_new (TP_ERRORS,
+ TP_ERROR_INVALID_ARGUMENT,
+ "Key '%s' not allowed in a sent message", *iter);
+
+ dbus_g_method_return_error (context, error);
+ return;
+ }
+ }
+ }
+
+ for (iter = body_only; *iter != NULL; iter++)
+ {
+ if (g_hash_table_lookup (header, *iter) != NULL)
+ {
+ GError *error = g_error_new (TP_ERRORS,
+ TP_ERROR_INVALID_ARGUMENT,
+ "Key '%s' not allowed in a message header", *iter);
+
+ dbus_g_method_return_error (context, error);
+ return;
+ }
+ }
+
+ for (iter = headers_only_incoming; *iter != NULL; iter++)
+ {
+ if (g_hash_table_lookup (header, *iter) != NULL)
+ {
+ GError *error = g_error_new (TP_ERRORS,
+ TP_ERROR_INVALID_ARGUMENT,
+ "Key '%s' not allowed in an outgoing message header", *iter);
+
+ dbus_g_method_return_error (context, error);
+ return;
+ }
+ }
+
+ for (i = 1; i < parts->len; i++)
+ {
+ for (iter = headers_only; *iter != NULL; iter++)
+ {
+ if (g_hash_table_lookup (g_ptr_array_index (parts, i), *iter)
+ != NULL)
+ {
+ GError *error = g_error_new (TP_ERRORS,
+ TP_ERROR_INVALID_ARGUMENT,
+ "Key '%s' not allowed in a message body", *iter);
+
+ dbus_g_method_return_error (context, error);
+ return;
+ }
+ }
+ }
+
message = g_slice_new0 (TpMessageMixinOutgoingMessage);
message->flags = flags;
- message->message_type = message_type;
- /* FIXME: fix codegen so we get a GType-generator for
- * TP_ARRAY_TYPE_MESSAGE_PART */
- message->parts = g_boxed_copy (dbus_g_type_get_collection ("GPtrArray",
- TP_HASH_TYPE_MESSAGE_PART), parts);
+
+ message->parts = g_ptr_array_sized_new (parts->len);
+
+ for (i = 0; i < parts->len; i++)
+ {
+ g_ptr_array_add (message->parts,
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free));
+ tp_g_hash_table_update (g_ptr_array_index (message->parts, i),
+ g_ptr_array_index (parts, i),
+ (GBoxedCopyFunc) g_strdup,
+ (GBoxedCopyFunc) tp_g_value_slice_dup);
+ }
+
message->priv = g_slice_new0 (TpMessageMixinOutgoingMessagePrivate);
message->priv->context = context;
message->priv->messages = TRUE;
diff --git a/telepathy-glib/message-mixin.h b/telepathy-glib/message-mixin.h
index c2dcdbf..b91dd2e 100644
--- a/telepathy-glib/message-mixin.h
+++ b/telepathy-glib/message-mixin.h
@@ -45,9 +45,11 @@ struct _TpMessageMixin {
/* Receiving */
-guint tp_message_mixin_take_received (GObject *object,
- time_t timestamp, TpHandle sender, TpChannelTextMessageType message_type,
- GPtrArray *content);
+typedef void (*TpMessageMixinCleanUpReceivedImpl) (GObject *object,
+ GPtrArray *parts, gpointer user_data);
+
+guint tp_message_mixin_take_received (GObject *object, GPtrArray *parts,
+ gpointer user_data);
/* Sending */
@@ -57,7 +59,6 @@ typedef struct _TpMessageMixinOutgoingMessagePrivate
typedef struct _TpMessageMixinOutgoingMessage {
guint flags;
- guint message_type;
GPtrArray *parts;
TpMessageMixinOutgoingMessagePrivate *priv;
} TpMessageMixinOutgoingMessage;
@@ -70,7 +71,8 @@ void tp_message_mixin_sent (GObject *object,
const GError *error);
void tp_message_mixin_implement_sending (GObject *object,
- TpMessageMixinSendImpl send);
+ TpMessageMixinSendImpl send, guint n_types,
+ const TpChannelTextMessageType *types);
/* Initialization */
@@ -78,10 +80,8 @@ void tp_message_mixin_text_iface_init (gpointer g_iface, gpointer iface_data);
void tp_message_mixin_messages_iface_init (gpointer g_iface,
gpointer iface_data);
-void tp_message_mixin_class_init (GObjectClass *obj_cls, gsize offset);
-
void tp_message_mixin_init (GObject *obj, gsize offset,
- TpHandleRepoIface *contact_repo);
+ TpMessageMixinCleanUpReceivedImpl clean_up_received);
void tp_message_mixin_finalize (GObject *obj);
G_END_DECLS
--
1.5.6.5
More information about the Telepathy-commits
mailing list