]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-chat.c
Rename all filenames starting with "gossip" by "empathy", change namespace
[empathy.git] / libempathy / empathy-tp-chat.c
index f72655eca9b6bcc589a0a224d923e8f31b072654..e97b5d641720281a7f1864a89196df563cd491c9 100644 (file)
 
 #include <config.h>
 
-#include <libtelepathy/tp-helpers.h>
+#include <string.h>
+
 #include <libtelepathy/tp-chan-type-text-gen.h>
 #include <libtelepathy/tp-chan-iface-chat-state-gen.h>
 #include <libtelepathy/tp-conn.h>
+#include <libtelepathy/tp-helpers.h>
+#include <libtelepathy/tp-props-iface.h>
 
 #include "empathy-tp-chat.h"
 #include "empathy-contact-manager.h"
-#include "empathy-contact-list.h"
-#include "empathy-session.h"
+#include "empathy-tp-contact-list.h"
 #include "empathy-marshal.h"
-#include "gossip-debug.h"
-#include "gossip-time.h"
+#include "empathy-debug.h"
+#include "empathy-time.h"
+#include "empathy-utils.h"
 
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
                       EMPATHY_TYPE_TP_CHAT, EmpathyTpChatPriv))
 #define DEBUG_DOMAIN "TpChat"
 
 struct _EmpathyTpChatPriv {
-       EmpathyContactList *list;
-       McAccount          *account;
-       gchar              *id;
-       MissionControl     *mc;
-
-       TpChan             *tp_chan;
-       DBusGProxy         *text_iface;
-       DBusGProxy         *chat_state_iface;
+       EmpathyTpContactList  *list;
+       EmpathyContactManager *manager;
+       McAccount             *account;
+       gchar                 *id;
+       MissionControl        *mc;
+
+       TpChan                *tp_chan;
+       DBusGProxy            *props_iface;
+       DBusGProxy            *text_iface;
+       DBusGProxy            *chat_state_iface;
 };
 
-static void empathy_tp_chat_class_init (EmpathyTpChatClass *klass);
-static void empathy_tp_chat_init       (EmpathyTpChat      *chat);
-static void tp_chat_finalize           (GObject            *object);
-static void tp_chat_destroy_cb         (TpChan             *text_chan,
-                                       EmpathyTpChat      *chat);
-static void tp_chat_received_cb        (DBusGProxy         *text_iface,
-                                       guint               message_id,
-                                       guint               timestamp,
-                                       guint               from_handle,
-                                       guint               message_type,
-                                       guint               message_flags,
-                                       gchar              *message_body,
-                                       EmpathyTpChat      *chat);
-static void tp_chat_sent_cb            (DBusGProxy         *text_iface,
-                                       guint               timestamp,
-                                       guint               message_type,
-                                       gchar              *message_body,
-                                       EmpathyTpChat      *chat);
-static void tp_chat_state_changed_cb   (DBusGProxy         *chat_state_iface,
-                                       guint               handle,
-                                       EmpathyTpChatState  state,
-                                       EmpathyTpChat      *chat);
-static void tp_chat_emit_message       (EmpathyTpChat      *chat,
-                                       guint               type,
-                                       guint               timestamp,
-                                       guint               from_handle,
-                                       const gchar        *message_body);
+static void      empathy_tp_chat_class_init    (EmpathyTpChatClass        *klass);
+static void      empathy_tp_chat_init          (EmpathyTpChat             *chat);
+static void      tp_chat_finalize              (GObject                   *object);
+static GObject * tp_chat_constructor           (GType                      type,
+                                               guint                      n_props,
+                                               GObjectConstructParam     *props);
+static void      tp_chat_get_property          (GObject                   *object,
+                                               guint                      param_id,
+                                               GValue                    *value,
+                                               GParamSpec                *pspec);
+static void      tp_chat_set_property          (GObject                   *object,
+                                               guint                      param_id,
+                                               const GValue              *value,
+                                               GParamSpec                *pspec);
+static void      tp_chat_destroy_cb            (TpChan                    *text_chan,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_closed_cb             (TpChan                    *text_chan,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_received_cb           (DBusGProxy                *text_iface,
+                                               guint                      message_id,
+                                               guint                      timestamp,
+                                               guint                      from_handle,
+                                               guint                      message_type,
+                                               guint                      message_flags,
+                                               gchar                     *message_body,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_sent_cb               (DBusGProxy                *text_iface,
+                                               guint                      timestamp,
+                                               guint                      message_type,
+                                               gchar                     *message_body,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_state_changed_cb      (DBusGProxy                *chat_state_iface,
+                                               guint                      handle,
+                                               TelepathyChannelChatState  state,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_emit_message          (EmpathyTpChat             *chat,
+                                               guint                      type,
+                                               guint                      timestamp,
+                                               guint                      from_handle,
+                                               const gchar               *message_body);
+static void      tp_chat_properties_ready_cb   (TpPropsIface              *props_iface,
+                                               EmpathyTpChat             *chat);
+static void      tp_chat_properties_changed_cb (TpPropsIface              *props_iface,
+                                               guint                      prop_id,
+                                               TpPropsChanged             flag,
+                                               EmpathyTpChat             *chat);
+enum {
+       PROP_0,
+       PROP_ACCOUNT,
+       PROP_TP_CHAN,
+
+       PROP_ANONYMOUS,
+       PROP_INVITE_ONLY,
+       PROP_LIMIT,
+       PROP_LIMITED,
+       PROP_MODERATED,
+       PROP_NAME,
+       PROP_DESCRIPTION,
+       PROP_PASSWORD,
+       PROP_PASSWORD_REQUIRED,
+       PROP_PERSISTENT,
+       PROP_PRIVATE,
+       PROP_SUBJECT,
+       PROP_SUBJECT_CONTACT,
+       PROP_SUBJECT_TIMESTAMP
+};
 
 enum {
        MESSAGE_RECEIVED,
@@ -96,7 +140,136 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
        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;
+
+       /* Construct-only properties */
+       g_object_class_install_property (object_class,
+                                        PROP_ACCOUNT,
+                                        g_param_spec_object ("account",
+                                                             "channel Account",
+                                                             "The account associated with the channel",
+                                                             MC_TYPE_ACCOUNT,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_TP_CHAN,
+                                        g_param_spec_object ("tp-chan",
+                                                             "telepathy channel",
+                                                             "The text channel for the chat",
+                                                             TELEPATHY_CHAN_TYPE,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+
+       /* Properties of Text Channel */
+       g_object_class_install_property (object_class,
+                                        PROP_ANONYMOUS,
+                                        g_param_spec_boolean ("anonymous",
+                                                              "anonymous",
+                                                              "anonymous",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_INVITE_ONLY,
+                                        g_param_spec_boolean ("invite-only",
+                                                              "invite-only",
+                                                              "invite-only",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_LIMIT,
+                                        g_param_spec_uint ("limit",
+                                                           "limit",
+                                                           "limit",
+                                                           0,
+                                                           G_MAXUINT,
+                                                           0,
+                                                           G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_LIMITED,
+                                        g_param_spec_boolean ("limited",
+                                                              "limited",
+                                                              "limited",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_MODERATED,
+                                        g_param_spec_boolean ("moderated",
+                                                              "moderated",
+                                                              "moderated",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_NAME,
+                                        g_param_spec_string ("name",
+                                                             "name",
+                                                             "name",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_DESCRIPTION,
+                                        g_param_spec_string ("description",
+                                                             "description",
+                                                             "description",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_PASSWORD,
+                                        g_param_spec_string ("password",
+                                                             "password",
+                                                             "password",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_PASSWORD_REQUIRED,
+                                        g_param_spec_boolean ("password-required",
+                                                              "password-required",
+                                                              "password-required",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_PERSISTENT,
+                                        g_param_spec_boolean ("persistent",
+                                                              "persistent",
+                                                              "persistent",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_PRIVATE,
+                                        g_param_spec_boolean ("private",
+                                                              "private",
+                                                              "private"
+                                                              "private",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_SUBJECT,
+                                        g_param_spec_string ("subject",
+                                                             "subject",
+                                                             "subject",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_SUBJECT_CONTACT,
+                                        g_param_spec_uint ("subject-contact",
+                                                           "subject-contact",
+                                                           "subject-contact",
+                                                           0,
+                                                           G_MAXUINT,
+                                                           0,
+                                                           G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_SUBJECT_TIMESTAMP,
+                                        g_param_spec_uint ("subject-timestamp",
+                                                           "subject-timestamp",
+                                                           "subject-timestamp",
+                                                           0,
+                                                           G_MAXUINT,
+                                                           0,
+                                                           G_PARAM_READWRITE));
+
+       /* Signals */
        signals[MESSAGE_RECEIVED] =
                g_signal_new ("message-received",
                              G_TYPE_FROM_CLASS (klass),
@@ -105,7 +278,7 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                              NULL, NULL,
                              g_cclosure_marshal_VOID__OBJECT,
                              G_TYPE_NONE,
-                             1, GOSSIP_TYPE_MESSAGE);
+                             1, EMPATHY_TYPE_MESSAGE);
 
        signals[CHAT_STATE_CHANGED] =
                g_signal_new ("chat-state-changed",
@@ -115,7 +288,7 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                              NULL, NULL,
                              empathy_marshal_VOID__OBJECT_UINT,
                              G_TYPE_NONE,
-                             2, GOSSIP_TYPE_CONTACT, G_TYPE_UINT);
+                             2, EMPATHY_TYPE_CONTACT, G_TYPE_UINT);
 
        signals[DESTROY] =
                g_signal_new ("destroy",
@@ -147,14 +320,14 @@ tp_chat_finalize (GObject *object)
        priv = GET_PRIV (chat);
 
        if (priv->tp_chan) {
-               gossip_debug (DEBUG_DOMAIN, "Closing channel...");
+               empathy_debug (DEBUG_DOMAIN, "Closing channel...");
 
                g_signal_handlers_disconnect_by_func (priv->tp_chan,
                                                      tp_chat_destroy_cb,
                                                      object);
 
                if (!tp_chan_close (DBUS_G_PROXY (priv->tp_chan), &error)) {
-                       gossip_debug (DEBUG_DOMAIN, 
+                       empathy_debug (DEBUG_DOMAIN, 
                                      "Error closing text channel: %s",
                                      error ? error->message : "No error given");
                        g_clear_error (&error);
@@ -162,6 +335,9 @@ tp_chat_finalize (GObject *object)
                g_object_unref (priv->tp_chan);
        }
 
+       if (priv->manager) {
+               g_object_unref (priv->manager);
+       }
        if (priv->list) {
                g_object_unref (priv->list);
        }
@@ -176,35 +352,36 @@ tp_chat_finalize (GObject *object)
        G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
 }
 
-EmpathyTpChat *
-empathy_tp_chat_new (McAccount *account,
-                    TpChan    *tp_chan)
+static GObject *
+tp_chat_constructor (GType                  type,
+                    guint                  n_props,
+                    GObjectConstructParam *props)
 {
-       EmpathyTpChatPriv     *priv;
-       EmpathyTpChat         *chat;
-       EmpathyContactManager *manager;
+       GObject           *chat;
+       EmpathyTpChatPriv *priv;
 
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-       g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
+       chat = G_OBJECT_CLASS (empathy_tp_chat_parent_class)->constructor (type, n_props, props);
 
-       chat = g_object_new (EMPATHY_TYPE_TP_CHAT, NULL);
        priv = GET_PRIV (chat);
 
-       manager = empathy_session_get_contact_manager ();
-       priv->list = empathy_contact_manager_get_list (manager, account);
-       priv->tp_chan = g_object_ref (tp_chan);
-       priv->account = g_object_ref (account);
-       priv->mc = mission_control_new (tp_get_bus ());
+       priv->manager = empathy_contact_manager_new ();
+       priv->list = empathy_contact_manager_get_list (priv->manager, priv->account);
+       priv->mc = empathy_mission_control_new ();
        g_object_ref (priv->list);
 
-       priv->text_iface = tp_chan_get_interface (tp_chan,
+       priv->text_iface = tp_chan_get_interface (priv->tp_chan,
                                                  TELEPATHY_CHAN_IFACE_TEXT_QUARK);
-       priv->chat_state_iface = tp_chan_get_interface (tp_chan,
+       priv->chat_state_iface = tp_chan_get_interface (priv->tp_chan,
                                                        TELEPATHY_CHAN_IFACE_CHAT_STATE_QUARK);
+       priv->props_iface = tp_chan_get_interface (priv->tp_chan,
+                                                  TELEPATHY_PROPS_IFACE_QUARK);
 
        g_signal_connect (priv->tp_chan, "destroy",
                          G_CALLBACK (tp_chat_destroy_cb),
                          chat);
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
+                                    G_CALLBACK (tp_chat_closed_cb),
+                                    chat, NULL);
        dbus_g_proxy_connect_signal (priv->text_iface, "Received",
                                     G_CALLBACK (tp_chat_received_cb),
                                     chat, NULL);
@@ -218,12 +395,118 @@ empathy_tp_chat_new (McAccount *account,
                                             G_CALLBACK (tp_chat_state_changed_cb),
                                             chat, NULL);
        }
+       if (priv->props_iface != NULL) {
+               tp_props_iface_set_mapping (TELEPATHY_PROPS_IFACE (priv->props_iface),
+                                           "anonymous", PROP_ANONYMOUS,
+                                           "invite-only", PROP_INVITE_ONLY,
+                                           "limit", PROP_LIMIT,
+                                           "limited", PROP_LIMITED,
+                                           "moderated", PROP_MODERATED,
+                                           "name", PROP_NAME,
+                                           "description", PROP_DESCRIPTION,
+                                           "password", PROP_PASSWORD,
+                                           "password-required", PROP_PASSWORD_REQUIRED,
+                                           "persistent", PROP_PERSISTENT,
+                                           "private", PROP_PRIVATE,
+                                           "subject", PROP_SUBJECT,
+                                           "subject-contact", PROP_SUBJECT_CONTACT,
+                                           "subject-timestamp", PROP_SUBJECT_TIMESTAMP,
+                                           NULL);
+               g_signal_connect (priv->props_iface, "properties-ready",
+                                 G_CALLBACK (tp_chat_properties_ready_cb),
+                                 chat);
+               g_signal_connect (priv->props_iface, "properties-changed",
+                                 G_CALLBACK (tp_chat_properties_changed_cb),
+                                 chat);
+       }
 
        return chat;
 }
 
+static void
+tp_chat_get_property (GObject    *object,
+                     guint       param_id,
+                     GValue     *value,
+                     GParamSpec *pspec)
+{
+       EmpathyTpChatPriv *priv;
+       EmpathyTpChat     *chat;
+
+       priv = GET_PRIV (object);
+       chat = EMPATHY_TP_CHAT (object);
+
+       if (param_id >= PROP_ANONYMOUS &&
+           param_id <= PROP_SUBJECT_TIMESTAMP) {
+               if (priv->props_iface) {
+                       tp_props_iface_get_value (TELEPATHY_PROPS_IFACE (priv->props_iface),
+                                                 param_id,
+                                                 value);
+               }
+
+               return;
+       }
+
+       switch (param_id) {
+       case PROP_ACCOUNT:
+               g_value_set_object (value, priv->account);
+               break;
+       case PROP_TP_CHAN:
+               g_value_set_object (value, priv->tp_chan);
+               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;
+       EmpathyTpChat     *chat;
+
+       priv = GET_PRIV (object);
+       chat = EMPATHY_TP_CHAT (object);
+
+       if (param_id >= PROP_ANONYMOUS &&
+           param_id <= PROP_SUBJECT_TIMESTAMP) {
+               if (priv->props_iface) {
+                       tp_props_iface_set_value (TELEPATHY_PROPS_IFACE (priv->props_iface),
+                                                 param_id,
+                                                 value);
+               }
+
+               return;
+       }
+
+       switch (param_id) {
+       case PROP_ACCOUNT:
+               priv->account = g_object_ref (g_value_get_object (value));
+               break;
+       case PROP_TP_CHAN:
+               priv->tp_chan = g_object_ref (g_value_get_object (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       };
+}
+
 EmpathyTpChat *
-empathy_tp_chat_new_with_contact (GossipContact *contact)
+empathy_tp_chat_new (McAccount *account,
+                    TpChan    *tp_chan)
+{
+       return g_object_new (EMPATHY_TYPE_TP_CHAT, 
+                            "account", account,
+                            "tp-chan", tp_chan,
+                            NULL);
+}
+
+EmpathyTpChat *
+empathy_tp_chat_new_with_contact (EmpathyContact *contact)
 {
        EmpathyTpChat  *chat;
        MissionControl *mc;
@@ -233,10 +516,10 @@ empathy_tp_chat_new_with_contact (GossipContact *contact)
        const gchar    *bus_name;
        guint           handle;
 
-       g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
 
-       mc = mission_control_new (tp_get_bus ());
-       account = gossip_contact_get_account (contact);
+       mc = empathy_mission_control_new ();
+       account = empathy_contact_get_account (contact);
 
        if (mission_control_get_connection_status (mc, account, NULL) != 0) {
                /* The account is not connected, nothing to do. */
@@ -246,7 +529,7 @@ empathy_tp_chat_new_with_contact (GossipContact *contact)
        tp_conn = mission_control_get_connection (mc, account, NULL);
        g_return_val_if_fail (tp_conn != NULL, NULL);
        bus_name = dbus_g_proxy_get_bus_name (DBUS_G_PROXY (tp_conn));
-       handle = gossip_contact_get_handle (contact);
+       handle = empathy_contact_get_handle (contact);
 
        text_chan = tp_conn_new_channel (tp_get_bus (),
                                         tp_conn,
@@ -283,7 +566,7 @@ empathy_tp_chat_request_pending (EmpathyTpChat *chat)
                                                      TRUE,
                                                      &messages_list,
                                                      &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "Error retrieving pending messages: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -308,7 +591,7 @@ empathy_tp_chat_request_pending (EmpathyTpChat *chat)
                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));
 
-               gossip_debug (DEBUG_DOMAIN, "Message pending: %s", message_body);
+               empathy_debug (DEBUG_DOMAIN, "Message pending: %s", message_body);
 
                tp_chat_emit_message (chat,
                                      message_type,
@@ -324,27 +607,27 @@ empathy_tp_chat_request_pending (EmpathyTpChat *chat)
 
 void
 empathy_tp_chat_send (EmpathyTpChat *chat,
-                     GossipMessage *message)
+                     EmpathyMessage *message)
 {
        EmpathyTpChatPriv *priv;
        const gchar       *message_body;
-       GossipMessageType  message_type;
+       EmpathyMessageType  message_type;
        GError            *error = NULL;
 
        g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
-       g_return_if_fail (GOSSIP_IS_MESSAGE (message));
+       g_return_if_fail (EMPATHY_IS_MESSAGE (message));
 
        priv = GET_PRIV (chat);
 
-       message_body = gossip_message_get_body (message);
-       message_type = gossip_message_get_type (message);
+       message_body = empathy_message_get_body (message);
+       message_type = empathy_message_get_type (message);
 
-       gossip_debug (DEBUG_DOMAIN, "Sending message: %s", message_body);
+       empathy_debug (DEBUG_DOMAIN, "Sending message: %s", message_body);
        if (!tp_chan_type_text_send (priv->text_iface,
                                     message_type,
                                     message_body,
                                     &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "Send Error: %s", 
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -352,8 +635,8 @@ empathy_tp_chat_send (EmpathyTpChat *chat,
 }
 
 void
-empathy_tp_chat_send_state (EmpathyTpChat      *chat,
-                           EmpathyTpChatState  state)
+empathy_tp_chat_set_state (EmpathyTpChat             *chat,
+                          TelepathyChannelChatState  state)
 {
        EmpathyTpChatPriv *priv;
        GError            *error = NULL;
@@ -363,11 +646,11 @@ empathy_tp_chat_send_state (EmpathyTpChat      *chat,
        priv = GET_PRIV (chat);
 
        if (priv->chat_state_iface) {
-               gossip_debug (DEBUG_DOMAIN, "Set state: %d", state);
+               empathy_debug (DEBUG_DOMAIN, "Set state: %d", state);
                if (!tp_chan_iface_chat_state_set_chat_state (priv->chat_state_iface,
                                                              state,
                                                              &error)) {
-                       gossip_debug (DEBUG_DOMAIN,
+                       empathy_debug (DEBUG_DOMAIN,
                                      "Set Chat State Error: %s",
                                      error ? error->message : "No error given");
                        g_clear_error (&error);
@@ -378,11 +661,7 @@ empathy_tp_chat_send_state (EmpathyTpChat      *chat,
 const gchar *
 empathy_tp_chat_get_id (EmpathyTpChat *chat)
 {
-       EmpathyTpChatPriv  *priv;
-       TpConn             *tp_conn;
-       GArray             *handles;
-       gchar             **names;
-       GError             *error = NULL;
+       EmpathyTpChatPriv *priv;
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
 
@@ -392,32 +671,7 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat)
                return priv->id;
        }
 
-       tp_conn = mission_control_get_connection (priv->mc, priv->account, NULL);
-       handles = g_array_new (FALSE, FALSE, sizeof (guint));
-       g_array_append_val (handles, priv->tp_chan->handle);
-
-       if (!tp_conn_inspect_handles (DBUS_G_PROXY (tp_conn),
-                                     priv->tp_chan->handle_type,
-                                     handles,
-                                     &names,
-                                     &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
-                             "Couldn't get id: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               g_array_free (handles, TRUE);
-               g_object_unref (tp_conn);
-               
-               return NULL;
-       }
-
-       /* A handle name is unique only for a specific account */
-       priv->id = g_strdup_printf ("%s/%s",
-                                   mc_account_get_unique_name (priv->account),
-                                   *names);
-
-       g_strfreev (names);
-       g_object_unref (tp_conn);
+       priv->id = empathy_get_channel_id (priv->account, priv->tp_chan);
 
        return priv->id;
 }
@@ -430,16 +684,33 @@ tp_chat_destroy_cb (TpChan        *text_chan,
 
        priv = GET_PRIV (chat);
 
-       gossip_debug (DEBUG_DOMAIN, "Channel destroyed");
+       empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
 
        g_object_unref  (priv->tp_chan);
        priv->tp_chan = NULL;
        priv->text_iface = NULL;
        priv->chat_state_iface = NULL;
+       priv->props_iface = NULL;
 
        g_signal_emit (chat, signals[DESTROY], 0);
 }
 
+static void
+tp_chat_closed_cb (TpChan        *text_chan,
+                  EmpathyTpChat *chat)
+{
+       EmpathyTpChatPriv *priv;
+
+       priv = GET_PRIV (chat);
+
+       /* The channel is closed, do just like if the proxy was destroyed */
+       g_signal_handlers_disconnect_by_func (priv->tp_chan,
+                                             tp_chat_destroy_cb,
+                                             chat);
+       tp_chat_destroy_cb (text_chan, chat);
+
+}
+
 static void
 tp_chat_received_cb (DBusGProxy    *text_iface,
                     guint          message_id,
@@ -455,7 +726,7 @@ tp_chat_received_cb (DBusGProxy    *text_iface,
 
        priv = GET_PRIV (chat);
 
-       gossip_debug (DEBUG_DOMAIN, "Message received: %s", message_body);
+       empathy_debug (DEBUG_DOMAIN, "Message received: %s", message_body);
 
        tp_chat_emit_message (chat,
                              message_type,
@@ -477,7 +748,7 @@ tp_chat_sent_cb (DBusGProxy    *text_iface,
                 gchar         *message_body,
                 EmpathyTpChat *chat)
 {
-       gossip_debug (DEBUG_DOMAIN, "Message sent: %s", message_body);
+       empathy_debug (DEBUG_DOMAIN, "Message sent: %s", message_body);
 
        tp_chat_emit_message (chat,
                              message_type,
@@ -487,17 +758,22 @@ tp_chat_sent_cb (DBusGProxy    *text_iface,
 }
 
 static void
-tp_chat_state_changed_cb (DBusGProxy         *chat_state_iface,
-                         guint               handle,
-                         EmpathyTpChatState  state,
-                         EmpathyTpChat      *chat)
+tp_chat_state_changed_cb (DBusGProxy                *chat_state_iface,
+                         guint                      handle,
+                         TelepathyChannelChatState  state,
+                         EmpathyTpChat             *chat)
 {
        EmpathyTpChatPriv *priv;
-       GossipContact     *contact;
+       EmpathyContact     *contact;
 
        priv = GET_PRIV (chat);
 
-       contact = empathy_contact_list_get_from_handle (priv->list, handle);
+       contact = empathy_tp_contact_list_get_from_handle (priv->list, handle);
+
+       empathy_debug (DEBUG_DOMAIN, "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);
 
@@ -512,23 +788,25 @@ tp_chat_emit_message (EmpathyTpChat *chat,
                      const gchar   *message_body)
 {
        EmpathyTpChatPriv *priv;
-       GossipMessage     *message;
-       GossipContact     *sender;
+       EmpathyMessage     *message;
+       EmpathyContact     *sender;
+       EmpathyContact     *receiver;
 
        priv = GET_PRIV (chat);
 
+       receiver = empathy_tp_contact_list_get_user (priv->list);
        if (from_handle == 0) {
-               sender = empathy_contact_list_get_own (priv->list);
-               g_object_ref (sender);
+               sender = g_object_ref (receiver);
        } else {
-               sender = empathy_contact_list_get_from_handle (priv->list,
-                                                              from_handle);
+               sender = empathy_tp_contact_list_get_from_handle (priv->list,
+                                                                 from_handle);
        }
 
-       message = gossip_message_new (message_body);
-       gossip_message_set_type (message, type);
-       gossip_message_set_sender (message, sender);
-       gossip_message_set_timestamp (message, (GossipTime) timestamp);
+       message = empathy_message_new (message_body);
+       empathy_message_set_type (message, type);
+       empathy_message_set_sender (message, sender);
+       empathy_message_set_receiver (message, receiver);
+       empathy_message_set_timestamp (message, (EmpathyTime) timestamp);
 
        g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
 
@@ -536,3 +814,75 @@ tp_chat_emit_message (EmpathyTpChat *chat,
        g_object_unref (sender);
 }
 
+static void
+tp_chat_properties_ready_cb (TpPropsIface  *props_iface,
+                            EmpathyTpChat *chat)
+{
+       g_object_notify (G_OBJECT (chat), "anonymous");
+       g_object_notify (G_OBJECT (chat), "invite-only");
+       g_object_notify (G_OBJECT (chat), "limit");
+       g_object_notify (G_OBJECT (chat), "limited");
+       g_object_notify (G_OBJECT (chat), "moderated");
+       g_object_notify (G_OBJECT (chat), "name");
+       g_object_notify (G_OBJECT (chat), "description");
+       g_object_notify (G_OBJECT (chat), "password");
+       g_object_notify (G_OBJECT (chat), "password-required");
+       g_object_notify (G_OBJECT (chat), "persistent");
+       g_object_notify (G_OBJECT (chat), "private");
+       g_object_notify (G_OBJECT (chat), "subject");
+       g_object_notify (G_OBJECT (chat), "subject-contact");
+       g_object_notify (G_OBJECT (chat), "subject-timestamp");
+}
+
+static void
+tp_chat_properties_changed_cb (TpPropsIface   *props_iface,
+                              guint           prop_id,
+                              TpPropsChanged  flag,
+                              EmpathyTpChat  *chat)
+{
+       switch (prop_id) {
+       case PROP_ANONYMOUS:
+               g_object_notify (G_OBJECT (chat), "anonymous");
+               break;
+       case PROP_INVITE_ONLY:
+               g_object_notify (G_OBJECT (chat), "invite-only");
+               break;
+       case PROP_LIMIT:
+               g_object_notify (G_OBJECT (chat), "limit");
+               break;
+       case PROP_LIMITED:
+               g_object_notify (G_OBJECT (chat), "limited");
+               break;
+       case PROP_MODERATED:
+               g_object_notify (G_OBJECT (chat), "moderated");
+               break;
+       case PROP_NAME:
+               g_object_notify (G_OBJECT (chat), "name");
+               break;
+       case PROP_DESCRIPTION:
+               g_object_notify (G_OBJECT (chat), "description");
+               break;
+       case PROP_PASSWORD:
+               g_object_notify (G_OBJECT (chat), "password");
+               break;
+       case PROP_PASSWORD_REQUIRED:
+               g_object_notify (G_OBJECT (chat), "password-required");
+               break;
+       case PROP_PERSISTENT:
+               g_object_notify (G_OBJECT (chat), "persistent");
+               break;
+       case PROP_PRIVATE:
+               g_object_notify (G_OBJECT (chat), "private");
+               break;
+       case PROP_SUBJECT:
+               g_object_notify (G_OBJECT (chat), "subject");
+               break;
+       case PROP_SUBJECT_CONTACT:
+               g_object_notify (G_OBJECT (chat), "subject-contact");
+               break;
+       case PROP_SUBJECT_TIMESTAMP:
+               g_object_notify (G_OBJECT (chat), "subject-timestamp");
+               break;
+       }
+}
+