]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-chat.c
individual-menu: remove link-contacts-activated signal
[empathy.git] / libempathy / empathy-tp-chat.c
index 27003561e7f28dd151cdd5808e03aa7cf152a613..4e26a769b5f4e803ea37de5f62c43f06e0ca161a 100644 (file)
@@ -30,7 +30,6 @@
 #include "empathy-tp-chat.h"
 #include "empathy-tp-contact-factory.h"
 #include "empathy-contact-list.h"
-#include "empathy-marshal.h"
 #include "empathy-request-util.h"
 #include "empathy-time.h"
 #include "empathy-utils.h"
@@ -47,8 +46,17 @@ struct _EmpathyTpChatPrivate {
        GQueue                *messages_queue;
        /* Queue of messages signalled but not acked yet */
        GQueue                *pending_messages_queue;
-       gboolean               had_properties_list;
-       GPtrArray             *properties;
+
+       /* Subject */
+       gboolean               supports_subject;
+       gboolean               can_set_subject;
+       gchar                 *subject;
+       gchar                 *subject_actor;
+
+       /* Room config (for now, we only track the title and don't support
+        * setting it) */
+       gchar                 *title;
+
        gboolean               can_upgrade_to_muc;
 
        GHashTable            *messages_being_sent;
@@ -62,15 +70,17 @@ static void tp_chat_iface_init         (EmpathyContactListIface *iface);
 enum {
        PROP_0,
        PROP_ACCOUNT,
+       PROP_SELF_CONTACT,
        PROP_REMOTE_CONTACT,
        PROP_N_MESSAGES_SENDING,
+       PROP_TITLE,
+       PROP_SUBJECT,
 };
 
 enum {
        MESSAGE_RECEIVED,
        SEND_ERROR,
        CHAT_STATE_CHANGED,
-       PROPERTY_CHANGED,
        MESSAGE_ACKNOWLEDGED,
        LAST_SIGNAL
 };
@@ -357,7 +367,8 @@ handle_delivery_report (EmpathyTpChat *self,
                tp_chat_set_delivery_status (self, delivery_token,
                        EMPATHY_DELIVERY_STATUS_NONE);
                goto out;
-       } else if (delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED) {
+       } else if (delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED &&
+                  delivery_status != TP_DELIVERY_STATUS_TEMPORARILY_FAILED) {
                goto out;
        }
 
@@ -585,220 +596,164 @@ list_pending_messages (EmpathyTpChat *self)
 }
 
 static void
-tp_chat_property_flags_changed_cb (TpProxy         *proxy,
-                                  const GPtrArray *properties,
-                                  gpointer         user_data,
-                                  GObject         *chat)
+update_subject (EmpathyTpChat *self,
+               GHashTable *properties)
 {
-       EmpathyTpChat *self = (EmpathyTpChat *) chat;
-       guint              i, j;
+       EmpathyTpChatPrivate *priv = self->priv;
+       gboolean can_set, valid;
+       const gchar *subject;
 
-       if (!self->priv->had_properties_list || !properties) {
-               return;
+       can_set = tp_asv_get_boolean (properties, "CanSet", &valid);
+       if (valid) {
+               priv->can_set_subject = can_set;
        }
 
-       for (i = 0; i < properties->len; i++) {
-               GValueArray           *prop_struct;
-               EmpathyTpChatProperty *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 < self->priv->properties->len; j++) {
-                       property = g_ptr_array_index (self->priv->properties, j);
-                       if (property->id == id) {
-                               property->flags = flags;
-                               DEBUG ("property %s flags changed: %d",
-                                       property->name, property->flags);
-                               break;
-                       }
-               }
+       subject = tp_asv_get_string (properties, "Subject");
+       if (subject != NULL) {
+               const gchar *actor;
+
+               g_free (priv->subject);
+               priv->subject = g_strdup (subject);
+
+               /* If the actor is included with this update, use it;
+                * otherwise, clear it to avoid showing stale information.
+                * Why might it not be included? When you join an IRC channel,
+                * you get a pair of messages: first, the current topic; next,
+                * who set it, and when. Idle reports these in two separate
+                * signals.
+                */
+               actor = tp_asv_get_string (properties, "Actor");
+               g_free (priv->subject_actor);
+               priv->subject_actor = g_strdup (actor);
+
+               g_object_notify (G_OBJECT (self), "subject");
        }
+
+       /* TODO: track Timestamp. */
 }
 
 static void
-tp_chat_properties_changed_cb (TpProxy         *proxy,
-                              const GPtrArray *properties,
-                              gpointer         user_data,
-                              GObject         *chat)
+tp_chat_get_all_subject_cb (TpProxy      *proxy,
+                           GHashTable   *properties,
+                           const GError *error,
+                           gpointer      user_data G_GNUC_UNUSED,
+                           GObject      *chat)
 {
-       EmpathyTpChat *self = (EmpathyTpChat *) chat;
-       guint              i, j;
+       EmpathyTpChat *self = EMPATHY_TP_CHAT (chat);
+       EmpathyTpChatPrivate *priv = self->priv;
 
-       if (!self->priv->had_properties_list || !properties) {
+       if (error) {
+               DEBUG ("Error fetching subject: %s", error->message);
                return;
        }
 
-       for (i = 0; i < properties->len; i++) {
-               GValueArray           *prop_struct;
-               EmpathyTpChatProperty *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 < self->priv->properties->len; j++) {
-                       property = g_ptr_array_index (self->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;
-                       }
+       priv->supports_subject = TRUE;
+       update_subject (self, properties);
+}
+
+static void
+update_title (EmpathyTpChat *self,
+             GHashTable *properties)
+{
+       EmpathyTpChatPrivate *priv = self->priv;
+       const gchar *title = tp_asv_get_string (properties, "Title");
+
+       if (title != NULL) {
+               if (tp_str_empty (title)) {
+                       title = NULL;
                }
+
+               g_free (priv->title);
+               priv->title = g_strdup (title);
+               g_object_notify (G_OBJECT (self), "title");
        }
 }
 
 static void
-tp_chat_get_properties_cb (TpProxy         *proxy,
-                          const GPtrArray *properties,
-                          const GError    *error,
-                          gpointer         user_data,
-                          GObject         *chat)
+tp_chat_get_all_room_config_cb (TpProxy      *proxy,
+                               GHashTable   *properties,
+                               const GError *error,
+                               gpointer      user_data G_GNUC_UNUSED,
+                               GObject      *chat)
 {
+       EmpathyTpChat *self = EMPATHY_TP_CHAT (chat);
+
        if (error) {
-               DEBUG ("Error getting properties: %s", error->message);
+               DEBUG ("Error fetching room config: %s", error->message);
                return;
        }
 
-       tp_chat_properties_changed_cb (proxy, properties, user_data, chat);
+       update_title (self, properties);
 }
 
 static void
-tp_chat_list_properties_cb (TpProxy         *proxy,
-                           const GPtrArray *properties,
-                           const GError    *error,
-                           gpointer         user_data,
-                           GObject         *chat)
+tp_chat_dbus_properties_changed_cb (TpProxy *proxy,
+                                   const gchar *interface_name,
+                                   GHashTable *changed,
+                                   const gchar **invalidated,
+                                   gpointer user_data,
+                                   GObject *chat)
 {
-       EmpathyTpChat *self = (EmpathyTpChat *) chat;
-       GArray            *ids;
-       guint              i;
+       EmpathyTpChat *self = EMPATHY_TP_CHAT (chat);
 
-       self->priv->had_properties_list = TRUE;
-
-       if (error) {
-               DEBUG ("Error listing properties: %s", error->message);
-               return;
+       if (!tp_strdiff (interface_name, TP_IFACE_CHANNEL_INTERFACE_SUBJECT)) {
+               update_subject (self, changed);
        }
 
-       ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), properties->len);
-       self->priv->properties = g_ptr_array_sized_new (properties->len);
-       for (i = 0; i < properties->len; i++) {
-               GValueArray           *prop_struct;
-               EmpathyTpChatProperty *property;
-
-               prop_struct = g_ptr_array_index (properties, i);
-               property = g_slice_new0 (EmpathyTpChatProperty);
-               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 (self->priv->properties, property);
-               if (property->flags & TP_PROPERTY_FLAG_READ) {
-                       g_array_append_val (ids, property->id);
-               }
+       if (!tp_strdiff (interface_name, TP_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG)) {
+               update_title (self, changed);
        }
-
-       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 *self,
-                             const gchar   *name,
-                             const GValue  *value)
+empathy_tp_chat_set_subject (EmpathyTpChat *self,
+                            const gchar   *subject)
 {
-       EmpathyTpChatProperty *property;
-       guint                  i;
-
-       if (!self->priv->had_properties_list) {
-               return;
-       }
-
-       for (i = 0; i < self->priv->properties->len; i++) {
-               property = g_ptr_array_index (self->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);
+       tp_cli_channel_interface_subject_call_set_subject (TP_CHANNEL (self), -1,
+                                                          subject,
+                                                          tp_chat_async_cb,
+                                                          "while setting subject", NULL,
+                                                          G_OBJECT (self));
+}
 
-                       properties = g_ptr_array_sized_new (1);
-                       g_ptr_array_add (properties, prop);
+const gchar *
+empathy_tp_chat_get_title (EmpathyTpChat *self)
+{
+       EmpathyTpChatPrivate *priv = self->priv;
 
-                       DEBUG ("Set property %s", name);
-                       tp_cli_properties_interface_call_set_properties (self, -1,
-                                                                        properties,
-                                                                        (tp_cli_properties_interface_callback_for_set_properties)
-                                                                        tp_chat_async_cb,
-                                                                        "Seting property", NULL,
-                                                                        G_OBJECT (self));
+       return priv->title;
+}
 
-                       g_ptr_array_free (properties, TRUE);
-                       g_value_array_free (prop);
+gboolean
+empathy_tp_chat_supports_subject (EmpathyTpChat *self)
+{
+       EmpathyTpChatPrivate *priv = self->priv;
 
-                       break;
-               }
-       }
+       return priv->supports_subject;
 }
 
-EmpathyTpChatProperty *
-empathy_tp_chat_get_property (EmpathyTpChat *self,
-                             const gchar   *name)
+gboolean
+empathy_tp_chat_can_set_subject (EmpathyTpChat *self)
 {
-       EmpathyTpChatProperty *property;
-       guint                  i;
+       EmpathyTpChatPrivate *priv = self->priv;
 
-       if (!self->priv->had_properties_list) {
-               return NULL;
-       }
+       return priv->can_set_subject;
+}
 
-       for (i = 0; i < self->priv->properties->len; i++) {
-               property = g_ptr_array_index (self->priv->properties, i);
-               if (!tp_strdiff (property->name, name)) {
-                       return property;
-               }
-       }
+const gchar *
+empathy_tp_chat_get_subject (EmpathyTpChat *self)
+{
+       EmpathyTpChatPrivate *priv = self->priv;
 
-       return NULL;
+       return priv->subject;
 }
 
-GPtrArray *
-empathy_tp_chat_get_properties (EmpathyTpChat *self)
+const gchar *
+empathy_tp_chat_get_subject_actor (EmpathyTpChat *self)
 {
-       return self->priv->properties;
+       EmpathyTpChatPrivate *priv = self->priv;
+
+       return priv->subject_actor;
 }
 
 static void
@@ -827,27 +782,16 @@ static void
 tp_chat_finalize (GObject *object)
 {
        EmpathyTpChat *self = (EmpathyTpChat *) object;
-       guint              i;
 
        DEBUG ("Finalize: %p", object);
 
-       if (self->priv->properties) {
-               for (i = 0; i < self->priv->properties->len; i++) {
-                       EmpathyTpChatProperty *property;
-
-                       property = g_ptr_array_index (self->priv->properties, i);
-                       g_free (property->name);
-                       if (property->value) {
-                               tp_g_value_slice_free (property->value);
-                       }
-                       g_slice_free (EmpathyTpChatProperty, property);
-               }
-               g_ptr_array_free (self->priv->properties, TRUE);
-       }
-
        g_queue_free (self->priv->messages_queue);
        g_queue_free (self->priv->pending_messages_queue);
-       g_hash_table_destroy (self->priv->messages_being_sent);
+       g_hash_table_unref (self->priv->messages_being_sent);
+
+       g_free (self->priv->title);
+       g_free (self->priv->subject);
+       g_free (self->priv->subject_actor);
 
        G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
 }
@@ -889,66 +833,6 @@ check_almost_ready (EmpathyTpChat *self)
        check_ready (self);
 }
 
-static void
-tp_chat_update_remote_contact (EmpathyTpChat *self)
-{
-       TpChannel *channel = (TpChannel *) self;
-       EmpathyContact *contact = NULL;
-       TpHandle self_handle;
-       TpHandleType handle_type;
-       GList *l;
-
-       /* If this is a named chatroom, never pretend it is a private chat */
-       tp_channel_get_handle (channel, &handle_type);
-       if (handle_type == TP_HANDLE_TYPE_ROOM) {
-               return;
-       }
-
-       /* This is an MSN chat, but it's the new style where 1-1 chats don't
-        * have the group interface. If it has the conference interface, then
-        * it is indeed a MUC. */
-       if (tp_proxy_has_interface_by_id (self,
-                                         TP_IFACE_QUARK_CHANNEL_INTERFACE_CONFERENCE)) {
-               return;
-       }
-
-       /* This is an MSN-like chat where anyone can join the chat at anytime.
-        * If there is only one non-self contact member, we are in a private
-        * chat and we set the "remote-contact" property to that contact. If
-        * there are more, set the "remote-contact" property to NULL and the
-        * UI will display a contact list. */
-       self_handle = tp_channel_group_get_self_handle (channel);
-       for (l = self->priv->members; l; l = l->next) {
-               /* Skip self contact if member */
-               if (empathy_contact_get_handle (l->data) == self_handle) {
-                       continue;
-               }
-
-               /* We have more than one remote contact, break */
-               if (contact != NULL) {
-                       contact = NULL;
-                       break;
-               }
-
-               /* If we didn't find yet a remote contact, keep this one */
-               contact = l->data;
-       }
-
-       if (self->priv->remote_contact == contact) {
-               return;
-       }
-
-       DEBUG ("Changing remote contact from %p to %p",
-               self->priv->remote_contact, contact);
-
-       if (self->priv->remote_contact) {
-               g_object_unref (self->priv->remote_contact);
-       }
-
-       self->priv->remote_contact = contact ? g_object_ref (contact) : NULL;
-       g_object_notify (G_OBJECT (self), "remote-contact");
-}
-
 static void
 tp_chat_got_added_contacts_cb (TpConnection            *connection,
                               guint                    n_contacts,
@@ -984,7 +868,6 @@ tp_chat_got_added_contacts_cb (TpConnection            *connection,
                }
        }
 
-       tp_chat_update_remote_contact (EMPATHY_TP_CHAT (chat));
        check_almost_ready (EMPATHY_TP_CHAT (chat));
 }
 
@@ -1090,9 +973,9 @@ tp_chat_got_renamed_contacts_cb (TpConnection            *connection,
                /* We change our nick */
                tp_clear_object (&self->priv->user);
                self->priv->user = g_object_ref (new);
+               g_object_notify (chat, "self-contact");
        }
 
-       tp_chat_update_remote_contact (self);
        check_almost_ready (self);
 }
 
@@ -1168,8 +1051,6 @@ tp_chat_group_members_changed_cb (TpChannel     *channel,
                        G_OBJECT (self));
        }
 
-       tp_chat_update_remote_contact (self);
-
        if (actor_contact != NULL) {
                g_object_unref (actor_contact);
        }
@@ -1213,6 +1094,7 @@ tp_chat_got_self_contact_cb (TpConnection            *connection,
 
        self->priv->user = g_object_ref (contact);
        empathy_contact_set_is_user (self->priv->user, TRUE);
+       g_object_notify (chat, "self-contact");
        check_almost_ready (self);
 }
 
@@ -1228,6 +1110,9 @@ tp_chat_get_property (GObject    *object,
        case PROP_ACCOUNT:
                g_value_set_object (value, self->priv->account);
                break;
+       case PROP_SELF_CONTACT:
+               g_value_set_object (value, self->priv->user);
+               break;
        case PROP_REMOTE_CONTACT:
                g_value_set_object (value, self->priv->remote_contact);
                break;
@@ -1235,6 +1120,14 @@ tp_chat_get_property (GObject    *object,
                g_value_set_uint (value,
                        g_hash_table_size (self->priv->messages_being_sent));
                break;
+       case PROP_TITLE:
+               g_value_set_string (value,
+                       empathy_tp_chat_get_title (self));
+               break;
+       case PROP_SUBJECT:
+               g_value_set_string (value,
+                       empathy_tp_chat_get_subject (self));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -1308,6 +1201,19 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                                                              G_PARAM_CONSTRUCT_ONLY |
                                                              G_PARAM_STATIC_STRINGS));
 
+       /**
+        * EmpathyTpChat:self-contact:
+        *
+        * Not to be confused with TpChannel:group-self-contact.
+        */
+       g_object_class_install_property (object_class,
+                                        PROP_SELF_CONTACT,
+                                        g_param_spec_object ("self-contact",
+                                                             "The local contact",
+                                                             "The EmpathyContact for the local user on this channel",
+                                                             EMPATHY_TYPE_CONTACT,
+                                                             G_PARAM_READABLE));
+
        g_object_class_install_property (object_class,
                                         PROP_REMOTE_CONTACT,
                                         g_param_spec_object ("remote-contact",
@@ -1324,6 +1230,24 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                                                            0, G_MAXUINT, 0,
                                                            G_PARAM_READABLE));
 
+       g_object_class_install_property (object_class,
+                                        PROP_TITLE,
+                                        g_param_spec_string ("title",
+                                                             "Title",
+                                                             "A human-readable name for the room, if any",
+                                                             NULL,
+                                                             G_PARAM_READABLE |
+                                                             G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (object_class,
+                                        PROP_SUBJECT,
+                                        g_param_spec_string ("subject",
+                                                             "Subject",
+                                                             "The room's current subject, if any",
+                                                             NULL,
+                                                             G_PARAM_READABLE |
+                                                             G_PARAM_STATIC_STRINGS));
+
        /* Signals */
        signals[MESSAGE_RECEIVED] =
                g_signal_new ("message-received-empathy",
@@ -1331,7 +1255,7 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
+                             g_cclosure_marshal_generic,
                              G_TYPE_NONE,
                              1, EMPATHY_TYPE_MESSAGE);
 
@@ -1341,7 +1265,7 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             _empathy_marshal_VOID__STRING_UINT_STRING,
+                             g_cclosure_marshal_generic,
                              G_TYPE_NONE,
                              3, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
 
@@ -1351,27 +1275,17 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             _empathy_marshal_VOID__OBJECT_UINT,
+                             g_cclosure_marshal_generic,
                              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[MESSAGE_ACKNOWLEDGED] =
                g_signal_new ("message-acknowledged",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
+                             g_cclosure_marshal_generic,
                              G_TYPE_NONE,
                              1, EMPATHY_TYPE_MESSAGE);
 
@@ -1571,7 +1485,7 @@ empathy_tp_chat_join (EmpathyTpChat *self)
        tp_cli_channel_interface_group_call_add_members ((TpChannel *) self, -1, members,
                "", add_members_cb, NULL, NULL, G_OBJECT (self));
 
-       g_array_free (members, TRUE);
+       g_array_unref (members);
 }
 
 gboolean
@@ -1622,6 +1536,7 @@ tp_chat_prepare_ready_async (TpProxy *proxy,
        EmpathyTpChat *self = (EmpathyTpChat *) proxy;
        TpChannel *channel = (TpChannel *) proxy;
        TpConnection *connection;
+       gboolean listen_for_dbus_properties_changed = FALSE;
 
        g_assert (self->priv->ready_result == NULL);
        self->priv->ready_result = g_simple_async_result_new (G_OBJECT (self),
@@ -1688,18 +1603,29 @@ tp_chat_prepare_ready_async (TpProxy *proxy,
        }
 
        if (tp_proxy_has_interface_by_id (self,
-                                         TP_IFACE_QUARK_PROPERTIES_INTERFACE)) {
-               tp_cli_properties_interface_call_list_properties (channel, -1,
-                                                                 tp_chat_list_properties_cb,
-                                                                 NULL, NULL,
-                                                                 G_OBJECT (self));
-               tp_cli_properties_interface_connect_to_properties_changed (channel,
-                                                                          tp_chat_properties_changed_cb,
-                                                                          NULL, NULL,
-                                                                          G_OBJECT (self), NULL);
-               tp_cli_properties_interface_connect_to_property_flags_changed (channel,
-                                                                              tp_chat_property_flags_changed_cb,
-                                                                              NULL, NULL,
-                                                                              G_OBJECT (self), NULL);
+                                         TP_IFACE_QUARK_CHANNEL_INTERFACE_SUBJECT)) {
+               tp_cli_dbus_properties_call_get_all (channel, -1,
+                                                    TP_IFACE_CHANNEL_INTERFACE_SUBJECT,
+                                                    tp_chat_get_all_subject_cb,
+                                                    NULL, NULL,
+                                                    G_OBJECT (self));
+               listen_for_dbus_properties_changed = TRUE;
+       }
+
+       if (tp_proxy_has_interface_by_id (self,
+                                         TP_IFACE_QUARK_CHANNEL_INTERFACE_ROOM_CONFIG)) {
+               tp_cli_dbus_properties_call_get_all (channel, -1,
+                                                    TP_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG,
+                                                    tp_chat_get_all_room_config_cb,
+                                                    NULL, NULL,
+                                                    G_OBJECT (self));
+               listen_for_dbus_properties_changed = TRUE;
+       }
+
+       if (listen_for_dbus_properties_changed) {
+               tp_cli_dbus_properties_connect_to_properties_changed (channel,
+                                                                     tp_chat_dbus_properties_changed_cb,
+                                                                     NULL, NULL,
+                                                                     G_OBJECT (self), NULL);
        }
 }