+static void
+chat_destroyed_cb (gpointer data,
+ GObject *object)
+{
+ EmpathyChatManager *self = data;
+ EmpathyChatManagerPriv *priv = GET_PRIV (self);
+
+ priv->num_displayed_chat--;
+
+ DEBUG ("Chat destroyed; we are now displaying %u chats",
+ priv->num_displayed_chat);
+
+ g_signal_emit (self, signals[DISPLAYED_CHATS_CHANGED], 0,
+ priv->num_displayed_chat);
+}
+
+static void
+join_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpChannel *channel = TP_CHANNEL (source);
+ GError *error = NULL;
+
+ if (!tp_channel_join_finish (channel, result, &error))
+ {
+ DEBUG ("Failed to join chat (%s): %s",
+ tp_channel_get_identifier (channel), error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+individual_mgr_cb (EmpathyChatWindow *window,
+ GParamSpec *spec,
+ EmpathyChatManager *self)
+{
+ EmpathyChatManagerPriv *priv = GET_PRIV (self);
+
+ if (priv->individual_mgr != NULL)
+ return;
+
+ priv->individual_mgr = empathy_chat_window_get_individual_manager (window);
+ g_object_ref (priv->individual_mgr);
+}
+
+static void
+process_tp_chat (EmpathyChatManager *self,
+ EmpathyTpChat *tp_chat,
+ TpAccount *account,
+ gint64 user_action_time)
+{
+ EmpathyChatManagerPriv *priv = GET_PRIV (self);
+ EmpathyChat *chat = NULL;
+ const gchar *id;
+ EmpathyChatWindow *window;
+
+ id = empathy_tp_chat_get_id (tp_chat);
+ if (!tp_str_empty (id))
+ {
+ chat = empathy_chat_window_find_chat (account, id,
+ tp_text_channel_is_sms_channel ((TpTextChannel *) tp_chat));
+ }
+
+ if (chat != NULL)
+ {
+ empathy_chat_set_tp_chat (chat, tp_chat);
+ }
+ else
+ {
+ GHashTable *chats = NULL;
+
+ chat = empathy_chat_new (tp_chat);
+ /* empathy_chat_new returns a floating reference as EmpathyChat is
+ * a GtkWidget. This reference will be taken by a container
+ * (a GtkNotebook) when we'll call empathy_chat_window_present_chat */
+
+ priv->num_displayed_chat++;
+
+ DEBUG ("Chat displayed; we are now displaying %u chat",
+ priv->num_displayed_chat);
+
+ g_signal_emit (self, signals[DISPLAYED_CHATS_CHANGED], 0,
+ priv->num_displayed_chat);
+
+ /* Set the saved message in the channel if we have one. */
+ chats = g_hash_table_lookup (priv->messages,
+ tp_proxy_get_object_path (account));
+
+ if (chats != NULL)
+ {
+ const gchar *msg = g_hash_table_lookup (chats, id);
+
+ if (msg != NULL)
+ empathy_chat_set_text (chat, msg);
+ }
+
+ g_object_weak_ref ((GObject *) chat, chat_destroyed_cb, self);
+ }
+
+ window = empathy_chat_window_present_chat (chat, user_action_time);
+
+ if (priv->individual_mgr == NULL)
+ {
+ /* We want to cache it as soon it's created */
+ tp_g_signal_connect_object (window, "notify::individual-manager",
+ G_CALLBACK (individual_mgr_cb), self, 0);
+ }
+
+ if (empathy_tp_chat_is_invited (tp_chat, NULL))
+ {
+ /* We have been invited to the room. Add ourself as member as this
+ * channel has been approved. */
+ tp_channel_join_async (TP_CHANNEL (tp_chat), "", join_cb, self);
+ }
+}
+
+static void
+handle_channels (TpSimpleHandler *handler,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ GList *requests_satisfied,
+ gint64 user_action_time,
+ TpHandleChannelsContext *context,
+ gpointer user_data)
+{
+ EmpathyChatManager *self = (EmpathyChatManager *) user_data;
+ GList *l;
+
+ for (l = channels; l != NULL; l = g_list_next (l))
+ {
+ EmpathyTpChat *tp_chat = l->data;
+
+ if (tp_proxy_get_invalidated (tp_chat) != NULL)
+ continue;
+
+ if (!EMPATHY_IS_TP_CHAT (tp_chat))
+ {
+ DEBUG ("Channel %s doesn't implement Messages; can't handle it",
+ tp_proxy_get_object_path (tp_chat));
+ continue;
+ }
+
+ DEBUG ("Now handling channel %s", tp_proxy_get_object_path (tp_chat));
+
+ process_tp_chat (self, tp_chat, account, user_action_time);
+ }
+
+ tp_handle_channels_context_accept (context);
+}
+