aboutsummaryrefslogtreecommitdiffstats
path: root/gnome-2-26/libempathy/empathy-tp-chat.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-2-26/libempathy/empathy-tp-chat.c')
-rw-r--r--gnome-2-26/libempathy/empathy-tp-chat.c1421
1 files changed, 0 insertions, 1421 deletions
diff --git a/gnome-2-26/libempathy/empathy-tp-chat.c b/gnome-2-26/libempathy/empathy-tp-chat.c
deleted file mode 100644
index 49870b41b..000000000
--- a/gnome-2-26/libempathy/empathy-tp-chat.c
+++ /dev/null
@@ -1,1421 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/util.h>
-
-#include "empathy-tp-chat.h"
-#include "empathy-tp-group.h"
-#include "empathy-contact-factory.h"
-#include "empathy-contact-monitor.h"
-#include "empathy-contact-list.h"
-#include "empathy-marshal.h"
-#include "empathy-time.h"
-#include "empathy-utils.h"
-
-#define DEBUG_FLAG EMPATHY_DEBUG_TP | EMPATHY_DEBUG_CHAT
-#include "empathy-debug.h"
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpChat)
-typedef struct {
- gboolean dispose_has_run;
- EmpathyContactFactory *factory;
- EmpathyContactMonitor *contact_monitor;
- EmpathyContact *user;
- EmpathyContact *remote_contact;
- EmpathyTpGroup *group;
- McAccount *account;
- TpChannel *channel;
- gchar *id;
- gboolean listing_pending_messages;
- /* Queue of messages not signalled yet */
- GQueue *messages_queue;
- /* Queue of messages signalled but not acked yet */
- GQueue *pending_messages_queue;
- gboolean had_properties_list;
- GPtrArray *properties;
- gboolean ready;
- guint members_count;
-} EmpathyTpChatPriv;
-
-typedef struct {
- gchar *name;
- guint id;
- TpPropertyFlags flags;
- GValue *value;
-} TpChatProperty;
-
-static void tp_chat_iface_init (EmpathyContactListIface *iface);
-
-enum {
- PROP_0,
- PROP_CHANNEL,
- PROP_REMOTE_CONTACT,
- PROP_READY,
-};
-
-enum {
- MESSAGE_RECEIVED,
- SEND_ERROR,
- CHAT_STATE_CHANGED,
- PROPERTY_CHANGED,
- DESTROY,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-G_DEFINE_TYPE_WITH_CODE (EmpathyTpChat, empathy_tp_chat, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
- tp_chat_iface_init));
-
-static void acknowledge_messages (EmpathyTpChat *chat, GArray *ids);
-
-static void
-tp_chat_invalidated_cb (TpProxy *proxy,
- guint domain,
- gint code,
- gchar *message,
- EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_object_unref (priv->channel);
- priv->channel = NULL;
-
- DEBUG ("Channel invalidated: %s", message);
- g_signal_emit (chat, signals[DESTROY], 0);
-
-}
-
-static void
-tp_chat_async_cb (TpChannel *proxy,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- if (error) {
- DEBUG ("Error %s: %s", (gchar*) user_data, error->message);
- }
-}
-
-static void
-tp_chat_member_added_cb (EmpathyTpGroup *group,
- EmpathyContact *contact,
- EmpathyContact *actor,
- guint reason,
- const gchar *message,
- EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint handle_type = 0;
-
- if (priv->channel == NULL)
- return;
-
- priv->members_count++;
- g_signal_emit_by_name (chat, "members-changed",
- contact, actor, reason, message,
- TRUE);
-
- g_object_get (priv->channel, "handle-type", &handle_type, NULL);
- if (handle_type == TP_HANDLE_TYPE_ROOM) {
- return;
- }
-
- if (priv->members_count > 2 && priv->remote_contact) {
- /* We now have more than 2 members, this is not a p2p chat
- * anymore. Remove the remote-contact as it makes no sense, the
- * EmpathyContactList interface must be used now. */
- g_object_unref (priv->remote_contact);
- priv->remote_contact = NULL;
- g_object_notify (G_OBJECT (chat), "remote-contact");
- }
- if (priv->members_count <= 2 && !priv->remote_contact &&
- !empathy_contact_is_user (contact)) {
- /* This is a p2p chat, if it's not ourself that means this is
- * the remote contact with who we are chatting. This is to
- * avoid forcing the usage of the EmpathyContactList interface
- * for p2p chats. */
- priv->remote_contact = g_object_ref (contact);
- g_object_notify (G_OBJECT (chat), "remote-contact");
- }
-}
-
-static void
-tp_chat_member_removed_cb (EmpathyTpGroup *group,
- EmpathyContact *contact,
- EmpathyContact *actor,
- guint reason,
- const gchar *message,
- EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint handle_type = 0;
-
- if (priv->channel == NULL)
- return;
-
- priv->members_count--;
- g_signal_emit_by_name (chat, "members-changed",
- contact, actor, reason, message,
- FALSE);
-
- g_object_get (priv->channel, "handle-type", &handle_type, NULL);
- if (handle_type == TP_HANDLE_TYPE_ROOM) {
- return;
- }
-
- if (priv->members_count <= 2 && !priv->remote_contact) {
- GList *members, *l;
-
- /* We are not a MUC anymore, get the remote contact back */
- members = empathy_tp_group_get_members (group);
- for (l = members; l; l = l->next) {
- if (!empathy_contact_is_user (l->data)) {
- priv->remote_contact = g_object_ref (l->data);
- g_object_notify (G_OBJECT (chat), "remote-contact");
- break;
- }
- }
- g_list_foreach (members, (GFunc) g_object_unref, NULL);
- g_list_free (members);
- }
-}
-
-static void
-tp_chat_local_pending_cb (EmpathyTpGroup *group,
- EmpathyContact *contact,
- EmpathyContact *actor,
- guint reason,
- const gchar *message,
- EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- if (priv->channel == NULL)
- return;
-
- g_signal_emit_by_name (chat, "pendings-changed",
- contact, actor, reason, message,
- TRUE);
-}
-
-static void
-tp_chat_add (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (list);
- TpHandle handle;
- GArray handles = {(gchar *) &handle, 1};
-
- g_return_if_fail (EMPATHY_IS_TP_CHAT (list));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- handle = empathy_contact_get_handle (contact);
- tp_cli_channel_interface_group_call_add_members (priv->channel, -1,
- &handles, NULL,
- NULL, NULL, NULL,
- NULL);
-}
-
-static void
-tp_chat_remove (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (list);
- TpHandle handle;
- GArray handles = {(gchar *) &handle, 1};
-
- g_return_if_fail (EMPATHY_IS_TP_CHAT (list));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- handle = empathy_contact_get_handle (contact);
- tp_cli_channel_interface_group_call_remove_members (priv->channel, -1,
- &handles, NULL,
- NULL, NULL, NULL,
- NULL);
-}
-
-static GList *
-tp_chat_get_members (EmpathyContactList *list)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (list);
- GList *members = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (list), NULL);
-
- if (priv->group) {
- members = empathy_tp_group_get_members (priv->group);
- } else {
- members = g_list_prepend (members, g_object_ref (priv->user));
- members = g_list_prepend (members, g_object_ref (priv->remote_contact));
- }
-
- return members;
-}
-
-static EmpathyContactMonitor *
-tp_chat_get_monitor (EmpathyContactList *list)
-{
- EmpathyTpChatPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (list), NULL);
-
- priv = GET_PRIV (list);
-
- if (priv->contact_monitor == NULL) {
- priv->contact_monitor = empathy_contact_monitor_new_for_iface (list);
- }
-
- return priv->contact_monitor;
-}
-
-static EmpathyMessage *
-tp_chat_build_message (EmpathyTpChat *chat,
- guint id,
- guint type,
- guint timestamp,
- guint from_handle,
- const gchar *message_body)
-{
- EmpathyTpChatPriv *priv;
- EmpathyMessage *message;
- EmpathyContact *sender;
-
- priv = GET_PRIV (chat);
-
- if (from_handle == 0) {
- sender = g_object_ref (priv->user);
- } else {
- sender = empathy_contact_factory_get_from_handle (priv->factory,
- priv->account,
- from_handle);
- }
-
- message = empathy_message_new (message_body);
- empathy_message_set_tptype (message, type);
- empathy_message_set_sender (message, sender);
- empathy_message_set_receiver (message, priv->user);
- empathy_message_set_timestamp (message, timestamp);
- empathy_message_set_id (message, id);
-
- g_object_unref (sender);
-
- return message;
-}
-
-static void
-tp_chat_sender_ready_notify_cb (EmpathyContact *contact,
- GParamSpec *param_spec,
- EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- EmpathyMessage *message;
- EmpathyContactReady ready;
- EmpathyContact *sender = NULL;
- gboolean removed = FALSE;
-
- /* Emit all messages queued until we find a message with not
- * ready sender (in case of a MUC we could have more than one sender).
- * When leaving this loop, sender is the first not ready contact queued
- * and removed tells if at least one message got removed
- * from the queue. */
- while ((message = g_queue_peek_head (priv->messages_queue)) != NULL) {
- sender = empathy_message_get_sender (message);
- ready = empathy_contact_get_ready (sender);
-
- if ((ready & EMPATHY_CONTACT_READY_NAME) == 0 ||
- (ready & EMPATHY_CONTACT_READY_ID) == 0) {
- break;
- }
-
- DEBUG ("Queued message ready");
- message = g_queue_pop_head (priv->messages_queue);
- g_queue_push_tail (priv->pending_messages_queue, message);
- g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
- removed = TRUE;
- }
-
- if (removed) {
- /* We removed at least one message from the queue, disconnect
- * the ready signal from the previous contact */
- g_signal_handlers_disconnect_by_func (contact,
- tp_chat_sender_ready_notify_cb,
- chat);
-
- if (g_queue_get_length (priv->messages_queue) > 0) {
- /* We still have queued message, connect the ready
- * signal on the new first message sender. */
- g_signal_connect (sender, "notify::ready",
- G_CALLBACK (tp_chat_sender_ready_notify_cb),
- chat);
- }
- }
-}
-
-static void
-tp_chat_emit_or_queue_message (EmpathyTpChat *chat,
- EmpathyMessage *message)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- EmpathyContact *sender;
- EmpathyContactReady ready;
-
- if (g_queue_get_length (priv->messages_queue) > 0) {
- DEBUG ("Message queue not empty");
- g_queue_push_tail (priv->messages_queue, g_object_ref (message));
- return;
- }
-
-
- sender = empathy_message_get_sender (message);
- ready = empathy_contact_get_ready (sender);
- if ((ready & EMPATHY_CONTACT_READY_NAME) &&
- (ready & EMPATHY_CONTACT_READY_ID)) {
- DEBUG ("Message queue empty and sender ready");
- g_queue_push_tail (priv->pending_messages_queue, g_object_ref (message));
- g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
- return;
- }
-
- DEBUG ("Sender not ready");
- g_queue_push_tail (priv->messages_queue, g_object_ref (message));
- g_signal_connect (sender, "notify::ready",
- G_CALLBACK (tp_chat_sender_ready_notify_cb),
- chat);
-}
-
-static void
-tp_chat_received_cb (TpChannel *channel,
- guint message_id,
- guint timestamp,
- guint from_handle,
- guint message_type,
- guint message_flags,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat_)
-{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- EmpathyMessage *message;
-
- if (priv->channel == NULL)
- return;
-
- if (priv->listing_pending_messages) {
- return;
- }
-
- DEBUG ("Message received: %s", message_body);
-
- if (message_flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT &&
- !tp_strdiff (message_body, "")) {
- GArray *ids;
-
- DEBUG ("Empty message with NonTextContent, ignoring and acking.");
-
- ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
- g_array_append_val (ids, message_id);
- acknowledge_messages (chat, ids);
- g_array_free (ids, TRUE);
-
- return;
- }
-
- message = tp_chat_build_message (chat,
- message_id,
- message_type,
- timestamp,
- from_handle,
- message_body);
-
- tp_chat_emit_or_queue_message (chat, message);
- g_object_unref (message);
-}
-
-static void
-tp_chat_sent_cb (TpChannel *channel,
- guint timestamp,
- guint message_type,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat_)
-{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- EmpathyMessage *message;
-
- if (priv->channel == NULL)
- return;
-
- DEBUG ("Message sent: %s", message_body);
-
- message = tp_chat_build_message (chat,
- 0,
- message_type,
- timestamp,
- 0,
- message_body);
-
- tp_chat_emit_or_queue_message (chat, message);
- g_object_unref (message);
-}
-
-static void
-tp_chat_send_error_cb (TpChannel *channel,
- guint error_code,
- guint timestamp,
- guint message_type,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyMessage *message;
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- if (priv->channel == NULL)
- return;
-
- DEBUG ("Message sent error: %s (%d)", message_body, error_code);
-
- message = tp_chat_build_message (EMPATHY_TP_CHAT (chat),
- 0,
- message_type,
- timestamp,
- 0,
- message_body);
-
- g_signal_emit (chat, signals[SEND_ERROR], 0, message, error_code);
- g_object_unref (message);
-}
-
-static void
-tp_chat_send_cb (TpChannel *proxy,
- const GError *error,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyMessage *message = EMPATHY_MESSAGE (user_data);
-
- if (error) {
- DEBUG ("Error: %s", error->message);
- g_signal_emit (chat, signals[SEND_ERROR], 0, message,
- TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN);
- }
-}
-
-static void
-tp_chat_state_changed_cb (TpChannel *channel,
- guint handle,
- guint state,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- EmpathyContact *contact;
-
- if (priv->channel == NULL)
- return;
-
- contact = empathy_contact_factory_get_from_handle (priv->factory,
- priv->account,
- handle);
-
- DEBUG ("Chat state changed for %s (%d): %d",
- empathy_contact_get_name (contact), handle, state);
-
- g_signal_emit (chat, signals[CHAT_STATE_CHANGED], 0, contact, state);
- g_object_unref (contact);
-}
-
-static void
-tp_chat_list_pending_messages_cb (TpChannel *channel,
- const GPtrArray *messages_list,
- const GError *error,
- gpointer user_data,
- GObject *chat_)
-{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint i;
- GArray *empty_non_text_content_ids = NULL;
-
- priv->listing_pending_messages = FALSE;
-
- if (priv->channel == NULL)
- return;
-
- if (error) {
- DEBUG ("Error listing pending messages: %s", error->message);
- return;
- }
-
- for (i = 0; i < messages_list->len; i++) {
- EmpathyMessage *message;
- GValueArray *message_struct;
- const gchar *message_body;
- guint message_id;
- guint timestamp;
- guint from_handle;
- guint message_type;
- guint message_flags;
-
- message_struct = g_ptr_array_index (messages_list, i);
-
- message_id = g_value_get_uint (g_value_array_get_nth (message_struct, 0));
- timestamp = g_value_get_uint (g_value_array_get_nth (message_struct, 1));
- from_handle = g_value_get_uint (g_value_array_get_nth (message_struct, 2));
- message_type = g_value_get_uint (g_value_array_get_nth (message_struct, 3));
- message_flags = g_value_get_uint (g_value_array_get_nth (message_struct, 4));
- message_body = g_value_get_string (g_value_array_get_nth (message_struct, 5));
-
- DEBUG ("Message pending: %s", message_body);
-
- if (message_flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT &&
- !tp_strdiff (message_body, "")) {
- DEBUG ("Empty message with NonTextContent, ignoring and acking.");
-
- if (empty_non_text_content_ids == NULL) {
- empty_non_text_content_ids = g_array_new (FALSE, FALSE, sizeof (guint));
- }
-
- g_array_append_val (empty_non_text_content_ids, message_id);
- continue;
- }
-
- message = tp_chat_build_message (chat,
- message_id,
- message_type,
- timestamp,
- from_handle,
- message_body);
-
- tp_chat_emit_or_queue_message (chat, message);
- g_object_unref (message);
- }
-
- if (empty_non_text_content_ids != NULL) {
- acknowledge_messages (chat, empty_non_text_content_ids);
- g_array_free (empty_non_text_content_ids, TRUE);
- }
-}
-
-static void
-tp_chat_property_flags_changed_cb (TpProxy *proxy,
- const GPtrArray *properties,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint i, j;
-
- if (priv->channel == NULL)
- return;
-
- if (!priv->had_properties_list || !properties) {
- return;
- }
-
- for (i = 0; i < properties->len; i++) {
- GValueArray *prop_struct;
- TpChatProperty *property;
- guint id;
- guint flags;
-
- prop_struct = g_ptr_array_index (properties, i);
- id = g_value_get_uint (g_value_array_get_nth (prop_struct, 0));
- flags = g_value_get_uint (g_value_array_get_nth (prop_struct, 1));
-
- for (j = 0; j < priv->properties->len; j++) {
- property = g_ptr_array_index (priv->properties, j);
- if (property->id == id) {
- property->flags = flags;
- DEBUG ("property %s flags changed: %d",
- property->name, property->flags);
- break;
- }
- }
- }
-}
-
-static void
-tp_chat_properties_changed_cb (TpProxy *proxy,
- const GPtrArray *properties,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint i, j;
-
- if (priv->channel == NULL)
- return;
-
- if (!priv->had_properties_list || !properties) {
- return;
- }
-
- for (i = 0; i < properties->len; i++) {
- GValueArray *prop_struct;
- TpChatProperty *property;
- guint id;
- GValue *src_value;
-
- prop_struct = g_ptr_array_index (properties, i);
- id = g_value_get_uint (g_value_array_get_nth (prop_struct, 0));
- src_value = g_value_get_boxed (g_value_array_get_nth (prop_struct, 1));
-
- for (j = 0; j < priv->properties->len; j++) {
- property = g_ptr_array_index (priv->properties, j);
- if (property->id == id) {
- if (property->value) {
- g_value_copy (src_value, property->value);
- } else {
- property->value = tp_g_value_slice_dup (src_value);
- }
-
- DEBUG ("property %s changed", property->name);
- g_signal_emit (chat, signals[PROPERTY_CHANGED], 0,
- property->name, property->value);
- break;
- }
- }
- }
-}
-
-static void
-tp_chat_get_properties_cb (TpProxy *proxy,
- const GPtrArray *properties,
- const GError *error,
- gpointer user_data,
- GObject *chat)
-{
- if (error) {
- DEBUG ("Error getting properties: %s", error->message);
- return;
- }
-
- tp_chat_properties_changed_cb (proxy, properties, user_data, chat);
-}
-
-static void
-tp_chat_list_properties_cb (TpProxy *proxy,
- const GPtrArray *properties,
- const GError *error,
- gpointer user_data,
- GObject *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- GArray *ids;
- guint i;
-
- if (priv->channel == NULL)
- return;
-
- priv->had_properties_list = TRUE;
-
- if (error) {
- DEBUG ("Error listing properties: %s", error->message);
- return;
- }
-
- ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), properties->len);
- priv->properties = g_ptr_array_sized_new (properties->len);
- for (i = 0; i < properties->len; i++) {
- GValueArray *prop_struct;
- TpChatProperty *property;
-
- prop_struct = g_ptr_array_index (properties, i);
- property = g_slice_new0 (TpChatProperty);
- property->id = g_value_get_uint (g_value_array_get_nth (prop_struct, 0));
- property->name = g_value_dup_string (g_value_array_get_nth (prop_struct, 1));
- property->flags = g_value_get_uint (g_value_array_get_nth (prop_struct, 3));
-
- DEBUG ("Adding property name=%s id=%d flags=%d",
- property->name, property->id, property->flags);
- g_ptr_array_add (priv->properties, property);
- if (property->flags & TP_PROPERTY_FLAG_READ) {
- g_array_append_val (ids, property->id);
- }
- }
-
- tp_cli_properties_interface_call_get_properties (proxy, -1,
- ids,
- tp_chat_get_properties_cb,
- NULL, NULL,
- chat);
-
- g_array_free (ids, TRUE);
-}
-
-void
-empathy_tp_chat_set_property (EmpathyTpChat *chat,
- const gchar *name,
- const GValue *value)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- TpChatProperty *property;
- guint i;
-
- g_return_if_fail (priv->ready);
-
- for (i = 0; i < priv->properties->len; i++) {
- property = g_ptr_array_index (priv->properties, i);
- if (!tp_strdiff (property->name, name)) {
- GPtrArray *properties;
- GValueArray *prop;
- GValue id = {0, };
- GValue dest_value = {0, };
-
- if (!(property->flags & TP_PROPERTY_FLAG_WRITE)) {
- break;
- }
-
- g_value_init (&id, G_TYPE_UINT);
- g_value_init (&dest_value, G_TYPE_VALUE);
- g_value_set_uint (&id, property->id);
- g_value_set_boxed (&dest_value, value);
-
- prop = g_value_array_new (2);
- g_value_array_append (prop, &id);
- g_value_array_append (prop, &dest_value);
-
- properties = g_ptr_array_sized_new (1);
- g_ptr_array_add (properties, prop);
-
- DEBUG ("Set property %s", name);
- tp_cli_properties_interface_call_set_properties (priv->channel, -1,
- properties,
- (tp_cli_properties_interface_callback_for_set_properties)
- tp_chat_async_cb,
- "Seting property", NULL,
- G_OBJECT (chat));
-
- g_ptr_array_free (properties, TRUE);
- g_value_array_free (prop);
-
- break;
- }
- }
-}
-
-static void
-tp_chat_channel_ready_cb (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- TpConnection *connection;
- guint handle, handle_type;
-
- if (priv->channel == NULL)
- return;
-
- DEBUG ("Channel ready");
-
- g_object_get (priv->channel,
- "connection", &connection,
- "handle", &handle,
- "handle_type", &handle_type,
- NULL);
-
- if (handle_type != TP_HANDLE_TYPE_NONE && handle != 0) {
- GArray *handles;
- gchar **names;
-
- handles = g_array_new (FALSE, FALSE, sizeof (guint));
- g_array_append_val (handles, handle);
- tp_cli_connection_run_inspect_handles (connection, -1,
- handle_type, handles,
- &names, NULL, NULL);
- priv->id = *names;
- g_array_free (handles, TRUE);
- g_free (names);
- }
-
- if (handle_type == TP_HANDLE_TYPE_CONTACT && handle != 0) {
- priv->remote_contact = empathy_contact_factory_get_from_handle (priv->factory,
- priv->account,
- handle);
- g_object_notify (G_OBJECT (chat), "remote-contact");
- }
-
- if (tp_proxy_has_interface_by_id (priv->channel,
- TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) {
- priv->group = empathy_tp_group_new (priv->channel);
-
- g_signal_connect (priv->group, "member-added",
- G_CALLBACK (tp_chat_member_added_cb),
- chat);
- g_signal_connect (priv->group, "member-removed",
- G_CALLBACK (tp_chat_member_removed_cb),
- chat);
- g_signal_connect (priv->group, "local-pending",
- G_CALLBACK (tp_chat_local_pending_cb),
- chat);
- empathy_run_until_ready (priv->group);
- } else {
- priv->members_count = 2;
- }
-
- if (tp_proxy_has_interface_by_id (priv->channel,
- TP_IFACE_QUARK_PROPERTIES_INTERFACE)) {
- tp_cli_properties_interface_call_list_properties (priv->channel, -1,
- tp_chat_list_properties_cb,
- NULL, NULL,
- G_OBJECT (chat));
- tp_cli_properties_interface_connect_to_properties_changed (priv->channel,
- tp_chat_properties_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_properties_interface_connect_to_property_flags_changed (priv->channel,
- tp_chat_property_flags_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- }
-
- priv->listing_pending_messages = TRUE;
- tp_cli_channel_type_text_call_list_pending_messages (priv->channel, -1,
- FALSE,
- tp_chat_list_pending_messages_cb,
- NULL, NULL,
- G_OBJECT (chat));
-
- tp_cli_channel_type_text_connect_to_received (priv->channel,
- tp_chat_received_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_type_text_connect_to_sent (priv->channel,
- tp_chat_sent_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_type_text_connect_to_send_error (priv->channel,
- tp_chat_send_error_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_interface_chat_state_connect_to_chat_state_changed (priv->channel,
- tp_chat_state_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_interface_chat_state_connect_to_chat_state_changed (priv->channel,
- tp_chat_state_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
-
- priv->ready = TRUE;
- g_object_notify (G_OBJECT (chat), "ready");
-}
-
-static void
-tp_chat_dispose (GObject *object)
-{
- EmpathyTpChat *self = EMPATHY_TP_CHAT (object);
- EmpathyTpChatPriv *priv = GET_PRIV (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- if (priv->channel != NULL)
- {
- g_signal_handlers_disconnect_by_func (priv->channel,
- tp_chat_invalidated_cb, self);
- g_object_unref (priv->channel);
- priv->channel = NULL;
- }
-
- if (priv->remote_contact != NULL)
- g_object_unref (priv->remote_contact);
-
- priv->remote_contact = NULL;
-
- if (priv->group != NULL)
- g_object_unref (priv->group);
- priv->group = NULL;
-
- if (priv->factory != NULL)
- g_object_unref (priv->factory);
- priv->factory = NULL;
-
- if (priv->user != NULL);
- g_object_unref (priv->user);
- priv->user = NULL;
-
- if (priv->account != NULL);
- g_object_unref (priv->account);
- priv->account = NULL;
-
- if (priv->contact_monitor)
- g_object_unref (priv->contact_monitor);
- priv->contact_monitor = NULL;
-
- if (!g_queue_is_empty (priv->messages_queue)) {
- EmpathyMessage *message;
- EmpathyContact *contact;
-
- message = g_queue_peek_head (priv->messages_queue);
- contact = empathy_message_get_sender (message);
- g_signal_handlers_disconnect_by_func (contact,
- tp_chat_sender_ready_notify_cb, object);
- }
-
- g_list_foreach (priv->messages_queue->head,
- (GFunc) g_object_unref, NULL);
-
- g_list_foreach (priv->pending_messages_queue->head,
- (GFunc) g_object_unref, NULL);
-
- if (G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose)
- G_OBJECT_CLASS (empathy_tp_chat_parent_class)->dispose (object);
-}
-
-static void
-tp_chat_finalize (GObject *object)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (object);
- guint i;
-
- DEBUG ("Finalize: %p", object);
-
- if (priv->properties) {
- for (i = 0; i < priv->properties->len; i++) {
- TpChatProperty *property;
-
- property = g_ptr_array_index (priv->properties, i);
- g_free (property->name);
- if (property->value) {
- tp_g_value_slice_free (property->value);
- }
- g_slice_free (TpChatProperty, property);
- }
- g_ptr_array_free (priv->properties, TRUE);
- }
-
-
- g_free (priv->id);
- g_queue_free (priv->messages_queue);
- g_queue_free (priv->pending_messages_queue);
-
- G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
-}
-
-static GObject *
-tp_chat_constructor (GType type,
- guint n_props,
- GObjectConstructParam *props)
-{
- GObject *chat;
- EmpathyTpChatPriv *priv;
- gboolean channel_ready;
-
- chat = G_OBJECT_CLASS (empathy_tp_chat_parent_class)->constructor (type, n_props, props);
-
- priv = GET_PRIV (chat);
- priv->account = empathy_channel_get_account (priv->channel);
- priv->factory = empathy_contact_factory_dup_singleton ();
- priv->user = empathy_contact_factory_get_user (priv->factory, priv->account);
-
- g_signal_connect (priv->channel, "invalidated",
- G_CALLBACK (tp_chat_invalidated_cb),
- chat);
-
- g_object_get (priv->channel, "channel-ready", &channel_ready, NULL);
- if (channel_ready) {
- tp_chat_channel_ready_cb (EMPATHY_TP_CHAT (chat));
- } else {
- g_signal_connect_swapped (priv->channel, "notify::channel-ready",
- G_CALLBACK (tp_chat_channel_ready_cb),
- chat);
- }
-
- return chat;
-}
-
-static void
-tp_chat_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (object);
-
- switch (param_id) {
- case PROP_CHANNEL:
- g_value_set_object (value, priv->channel);
- break;
- case PROP_REMOTE_CONTACT:
- g_value_set_object (value, priv->remote_contact);
- break;
- case PROP_READY:
- g_value_set_boolean (value, priv->ready);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- };
-}
-
-static void
-tp_chat_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (object);
-
- switch (param_id) {
- case PROP_CHANNEL:
- priv->channel = g_value_dup_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- };
-}
-
-static void
-empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = tp_chat_dispose;
- object_class->finalize = tp_chat_finalize;
- object_class->constructor = tp_chat_constructor;
- object_class->get_property = tp_chat_get_property;
- object_class->set_property = tp_chat_set_property;
-
- g_object_class_install_property (object_class,
- PROP_CHANNEL,
- g_param_spec_object ("channel",
- "telepathy channel",
- "The text channel for the chat",
- TP_TYPE_CHANNEL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_REMOTE_CONTACT,
- g_param_spec_object ("remote-contact",
- "The remote contact",
- "The remote contact if there is no group iface on the channel",
- EMPATHY_TYPE_CONTACT,
- G_PARAM_READABLE));
- g_object_class_install_property (object_class,
- PROP_READY,
- g_param_spec_boolean ("ready",
- "Is the object ready",
- "This object can't be used until this becomes true",
- FALSE,
- G_PARAM_READABLE));
-
- /* Signals */
- signals[MESSAGE_RECEIVED] =
- g_signal_new ("message-received",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1, EMPATHY_TYPE_MESSAGE);
-
- signals[SEND_ERROR] =
- g_signal_new ("send-error",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _empathy_marshal_VOID__OBJECT_UINT,
- G_TYPE_NONE,
- 2, EMPATHY_TYPE_MESSAGE, G_TYPE_UINT);
-
- signals[CHAT_STATE_CHANGED] =
- g_signal_new ("chat-state-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _empathy_marshal_VOID__OBJECT_UINT,
- G_TYPE_NONE,
- 2, EMPATHY_TYPE_CONTACT, G_TYPE_UINT);
-
- signals[PROPERTY_CHANGED] =
- g_signal_new ("property-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _empathy_marshal_VOID__STRING_BOXED,
- G_TYPE_NONE,
- 2, G_TYPE_STRING, G_TYPE_VALUE);
-
- signals[DESTROY] =
- g_signal_new ("destroy",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- g_type_class_add_private (object_class, sizeof (EmpathyTpChatPriv));
-}
-
-static void
-empathy_tp_chat_init (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (chat,
- EMPATHY_TYPE_TP_CHAT, EmpathyTpChatPriv);
-
- chat->priv = priv;
- priv->contact_monitor = NULL;
- priv->messages_queue = g_queue_new ();
- priv->pending_messages_queue = g_queue_new ();
-}
-
-static void
-tp_chat_iface_init (EmpathyContactListIface *iface)
-{
- iface->add = tp_chat_add;
- iface->remove = tp_chat_remove;
- iface->get_members = tp_chat_get_members;
- iface->get_monitor = tp_chat_get_monitor;
-}
-
-EmpathyTpChat *
-empathy_tp_chat_new (TpChannel *channel)
-{
- return g_object_new (EMPATHY_TYPE_TP_CHAT,
- "channel", channel,
- NULL);
-}
-
-void
-empathy_tp_chat_close (EmpathyTpChat *chat) {
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- /* If there are still messages left, it'll come back..
- We loose the ordering of sent messages though */
- g_signal_handlers_disconnect_by_func (priv->channel,
- tp_chat_invalidated_cb, chat);
-
- tp_cli_channel_call_close (priv->channel, -1, tp_chat_async_cb,
- "closing channel", NULL, NULL);
-
- g_object_unref (priv->channel);
- priv->channel = NULL;
-
- g_signal_emit (chat, signals[DESTROY], 0);
-}
-
-const gchar *
-empathy_tp_chat_get_id (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
- g_return_val_if_fail (priv->ready, NULL);
-
- return priv->id;
-}
-
-EmpathyContact *
-empathy_tp_chat_get_remote_contact (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
-
- return priv->remote_contact;
-}
-
-McAccount *
-empathy_tp_chat_get_account (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), FALSE);
-
- return priv->account;
-}
-
-TpChannel *
-empathy_tp_chat_get_channel (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
-
- return priv->channel;
-}
-
-gboolean
-empathy_tp_chat_is_ready (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), FALSE);
-
- return priv->ready;
-}
-
-guint
-empathy_tp_chat_get_members_count (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), 0);
-
- return priv->members_count;
-}
-
-void
-empathy_tp_chat_send (EmpathyTpChat *chat,
- EmpathyMessage *message)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- const gchar *message_body;
- TpChannelTextMessageType message_type;
-
- g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
- g_return_if_fail (priv->ready);
-
- message_body = empathy_message_get_body (message);
- message_type = empathy_message_get_tptype (message);
-
- DEBUG ("Sending message: %s", message_body);
- tp_cli_channel_type_text_call_send (priv->channel, -1,
- message_type,
- message_body,
- tp_chat_send_cb,
- g_object_ref (message),
- (GDestroyNotify) g_object_unref,
- G_OBJECT (chat));
-}
-
-void
-empathy_tp_chat_set_state (EmpathyTpChat *chat,
- TpChannelChatState state)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
- g_return_if_fail (priv->ready);
-
- DEBUG ("Set state: %d", state);
- tp_cli_channel_interface_chat_state_call_set_chat_state (priv->channel, -1,
- state,
- tp_chat_async_cb,
- "setting chat state",
- NULL,
- G_OBJECT (chat));
-}
-
-
-const GList *
-empathy_tp_chat_get_pending_messages (EmpathyTpChat *chat)
-{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- return priv->pending_messages_queue->head;
-}
-
-static void
-acknowledge_messages (EmpathyTpChat *chat, GArray *ids) {
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- tp_cli_channel_type_text_call_acknowledge_pending_messages (
- priv->channel, -1, ids, tp_chat_async_cb,
- "acknowledging received message", NULL, G_OBJECT (chat));
-}
-
-void
-empathy_tp_chat_acknowledge_message (EmpathyTpChat *chat,
- EmpathyMessage *message) {
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- GArray *message_ids;
- GList *m;
- guint id;
-
- if (empathy_message_get_sender (message) == priv->user)
- goto out;
-
- message_ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
-
- id = empathy_message_get_id (message);
- g_array_append_val (message_ids, id);
- acknowledge_messages (chat, message_ids);
- g_array_free (message_ids, TRUE);
-
-out:
- m = g_queue_find (priv->pending_messages_queue, message);
- g_assert (m != NULL);
- g_queue_delete_link (priv->pending_messages_queue, m);
- g_object_unref (message);
-}
-
-void
-empathy_tp_chat_acknowledge_messages (EmpathyTpChat *chat,
- const GList *messages) {
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- /* Copy messages as the messges list (probably is) our own */
- GList *msgs = g_list_copy ((GList *) messages);
- GList *l;
- guint length;
- GArray *message_ids;
-
- length = g_list_length ((GList *)messages);
-
- if (length == 0)
- return;
-
- message_ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), length);
-
- for (l = msgs; l != NULL; l = g_list_next (l)) {
- GList *m;
-
- EmpathyMessage *message = EMPATHY_MESSAGE (l->data);
-
- m = g_queue_find (priv->pending_messages_queue, message);
- g_assert (m != NULL);
- g_queue_delete_link (priv->pending_messages_queue, m);
-
- if (empathy_message_get_sender (message) != priv->user) {
- guint id = empathy_message_get_id (message);
- g_array_append_val (message_ids, id);
- }
- }
-
- if (message_ids->len > 0)
- acknowledge_messages (chat, message_ids);
-
- g_array_free (message_ids, TRUE);
- g_list_free (msgs);
-}