]> git.0d.be Git - empathy.git/commitdiff
rename EmpathyIdle to EmpathyPresenceManager (#640532)
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Tue, 25 Jan 2011 10:13:51 +0000 (11:13 +0100)
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Tue, 25 Jan 2011 11:28:16 +0000 (12:28 +0100)
It's doing more than idle management now.

13 files changed:
libempathy-gtk/empathy-presence-chooser.c
libempathy-gtk/empathy-ui-utils.c
libempathy/Makefile.am
libempathy/empathy-account-settings.c
libempathy/empathy-idle.c [deleted file]
libempathy/empathy-idle.h [deleted file]
libempathy/empathy-presence-manager.c [new file with mode: 0644]
libempathy/empathy-presence-manager.h [new file with mode: 0644]
libempathy/empathy-utils.c
src/empathy-chat.c
src/empathy-event-manager.c
src/empathy-main-window.c
src/empathy.c

index 33bf02811bf37a47954e5ca7444c49c321384d01..2c8a3c8717a82363ee4dbca34fdbc5973f1a5645 100644 (file)
@@ -37,7 +37,7 @@
 #include <telepathy-glib/util.h>
 
 #include <libempathy/empathy-connectivity.h>
-#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-presence-manager.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-status-presets.h>
 
@@ -99,7 +99,7 @@ typedef enum  {
 } PresenceChooserEntryType;
 
 typedef struct {
-       EmpathyIdle *idle;
+       EmpathyPresenceManager *presence_mgr;
        EmpathyConnectivity *connectivity;
 
        gboolean     editing_status;
@@ -433,7 +433,7 @@ mc_set_custom_state (EmpathyPresenceChooser *self)
 
        DEBUG ("Sending state to MC-> %d (%s)", priv->state, status);
 
-       empathy_idle_set_presence (priv->idle, priv->state, status);
+       empathy_presence_manager_set_presence (priv->presence_mgr, priv->state, status);
 }
 
 static void
@@ -664,7 +664,7 @@ presence_chooser_changed_cb (GtkComboBox *self, gpointer user_data)
                                    COL_STATUS_TEXT, &status,
                                    -1);
 
-               empathy_idle_set_presence (priv->idle, priv->state, status);
+               empathy_presence_manager_set_presence (priv->presence_mgr, priv->state, status);
 
                g_free (status);
        }
@@ -922,7 +922,7 @@ presence_chooser_constructed (GObject *object)
                        G_CALLBACK (presence_chooser_entry_focus_out_cb),
                        chooser);
 
-       priv->idle = empathy_idle_dup_singleton ();
+       priv->presence_mgr = empathy_presence_manager_dup_singleton ();
 
        priv->account_manager = tp_account_manager_dup ();
        g_signal_connect_swapped (priv->account_manager,
@@ -970,10 +970,10 @@ presence_chooser_finalize (GObject *object)
        if (priv->account_manager != NULL)
                g_object_unref (priv->account_manager);
 
-       g_signal_handlers_disconnect_by_func (priv->idle,
+       g_signal_handlers_disconnect_by_func (priv->presence_mgr,
                                              presence_chooser_presence_changed_cb,
                                              object);
-       g_object_unref (priv->idle);
+       g_object_unref (priv->presence_mgr);
 
        g_object_unref (priv->connectivity);
        if (priv->not_favorite_pixbuf != NULL)
@@ -1197,11 +1197,11 @@ static void
 presence_chooser_set_state (TpConnectionPresenceType state,
                            const gchar *status)
 {
-       EmpathyIdle *idle;
+       EmpathyPresenceManager *presence_mgr;
 
-       idle = empathy_idle_dup_singleton ();
-       empathy_idle_set_presence (idle, state, status);
-       g_object_unref (idle);
+       presence_mgr = empathy_presence_manager_dup_singleton ();
+       empathy_presence_manager_set_presence (presence_mgr, state, status);
+       g_object_unref (presence_mgr);
 }
 
 static void
index e2946e513be62b72b50e9fddecfcec449e85021c..ca63a0c2c165ea07cdcf9f8cecdf7b63a8f476bb 100644 (file)
@@ -50,7 +50,6 @@
 #include <libempathy/empathy-debug.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-dispatcher.h>
-#include <libempathy/empathy-idle.h>
 #include <libempathy/empathy-ft-factory.h>
 
 void
index ef85581b1a1b7353a4b27b35bea02e51f03286f3..25153eab891fca2d5167d6439bd4d8e8afdac2a4 100644 (file)
@@ -43,7 +43,7 @@ libempathy_headers =                          \
        empathy-ft-factory.h                    \
        empathy-ft-handler.h                    \
        empathy-gsettings.h                     \
-       empathy-idle.h                          \
+       empathy-presence-manager.h                              \
        empathy-individual-manager.h            \
        empathy-irc-network-manager.h           \
        empathy-irc-network.h                   \
@@ -84,7 +84,7 @@ libempathy_la_SOURCES =                                       \
        empathy-dispatcher.c                            \
        empathy-ft-factory.c                            \
        empathy-ft-handler.c                            \
-       empathy-idle.c                                  \
+       empathy-presence-manager.c                                      \
        empathy-individual-manager.c                    \
        empathy-irc-network-manager.c                   \
        empathy-irc-network.c                           \
index a90aaa8f4158d0f96937282b1f7b3bb1b4e3a6fe..8c673dfcf4a204e2422c034224fdd69ff82fccab 100644 (file)
@@ -31,7 +31,7 @@
 #include "empathy-connection-managers.h"
 #include "empathy-keyring.h"
 #include "empathy-utils.h"
-#include "empathy-idle.h"
+#include "empathy-presence-manager.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
 #include <libempathy/empathy-debug.h>
@@ -1499,13 +1499,14 @@ empathy_account_settings_do_create_account (EmpathyAccountSettings *settings)
   TpConnectionPresenceType type;
   gchar *status;
   gchar *message;
-  EmpathyIdle *idle;
+  EmpathyPresenceManager *presence_mgr;
 
   properties = tp_asv_new (NULL, NULL);
 
-  idle = empathy_idle_dup_singleton ();
-  type = empathy_idle_get_requested_presence (idle, &status, &message);
-  g_object_unref (idle);
+  presence_mgr = empathy_presence_manager_dup_singleton ();
+  type = empathy_presence_manager_get_requested_presence (presence_mgr, &status,
+      &message);
+  g_object_unref (presence_mgr);
 
   if (type != TP_CONNECTION_PRESENCE_TYPE_UNSET)
     {
diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c
deleted file mode 100644 (file)
index 12686da..0000000
+++ /dev/null
@@ -1,732 +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 <glib/gi18n-lib.h>
-#include <dbus/dbus-glib.h>
-
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/util.h>
-
-#include "empathy-idle.h"
-#include "empathy-utils.h"
-#include "empathy-connectivity.h"
-
-#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
-#include "empathy-debug.h"
-
-/* Number of seconds before entering extended autoaway. */
-#define EXT_AWAY_TIME (30*60)
-
-/* Number of seconds to consider an account in the "just connected" state
- * for. */
-#define ACCOUNT_IS_JUST_CONNECTED_SECONDS 10
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIdle)
-typedef struct {
-       DBusGProxy     *gs_proxy;
-       EmpathyConnectivity *connectivity;
-       gulong state_change_signal_id;
-
-       gboolean ready;
-
-       TpConnectionPresenceType      state;
-       gchar          *status;
-       gboolean        auto_away;
-
-       TpConnectionPresenceType      away_saved_state;
-       TpConnectionPresenceType      saved_state;
-       gchar          *saved_status;
-
-       gboolean        is_idle;
-       guint           ext_away_timeout;
-
-       TpAccountManager *manager;
-       gulong idle_presence_changed_id;
-
-       /* pointer to a TpAccount --> glong of time of connection */
-       GHashTable *connect_times;
-
-       TpConnectionPresenceType requested_presence_type;
-       gchar *requested_status_message;
-
-} EmpathyIdlePriv;
-
-typedef enum {
-       SESSION_STATUS_AVAILABLE,
-       SESSION_STATUS_INVISIBLE,
-       SESSION_STATUS_BUSY,
-       SESSION_STATUS_IDLE,
-       SESSION_STATUS_UNKNOWN
-} SessionStatus;
-
-enum {
-       PROP_0,
-       PROP_STATE,
-       PROP_STATUS,
-       PROP_AUTO_AWAY
-};
-
-G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT);
-
-static EmpathyIdle * idle_singleton = NULL;
-
-static const gchar *presence_type_to_status[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
-       NULL,
-       "offline",
-       "available",
-       "away",
-       "xa",
-       "hidden",
-       "busy",
-       NULL,
-       NULL,
-};
-
-static void
-idle_presence_changed_cb (TpAccountManager *manager,
-                         TpConnectionPresenceType state,
-                         gchar          *status,
-                         gchar          *status_message,
-                         EmpathyIdle    *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (state == TP_CONNECTION_PRESENCE_TYPE_UNSET)
-               /* Assume our presence is offline if MC reports UNSET */
-               state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
-
-       DEBUG ("Presence changed to '%s' (%d) \"%s\"", status, state,
-               status_message);
-
-       g_free (priv->status);
-       priv->state = state;
-       if (EMP_STR_EMPTY (status_message))
-               priv->status = NULL;
-       else
-               priv->status = g_strdup (status_message);
-
-       g_object_notify (G_OBJECT (idle), "state");
-       g_object_notify (G_OBJECT (idle), "status");
-}
-
-static gboolean
-idle_ext_away_cb (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       DEBUG ("Going to extended autoaway");
-       empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY);
-       priv->ext_away_timeout = 0;
-
-       return FALSE;
-}
-
-static void
-idle_ext_away_stop (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (priv->ext_away_timeout) {
-               g_source_remove (priv->ext_away_timeout);
-               priv->ext_away_timeout = 0;
-       }
-}
-
-static void
-idle_ext_away_start (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (priv->ext_away_timeout != 0) {
-               return;
-       }
-       priv->ext_away_timeout = g_timeout_add_seconds (EXT_AWAY_TIME,
-                                                       (GSourceFunc) idle_ext_away_cb,
-                                                       idle);
-}
-
-static void
-idle_session_status_changed_cb (DBusGProxy    *gs_proxy,
-                               SessionStatus  status,
-                               EmpathyIdle   *idle)
-{
-       EmpathyIdlePriv *priv;
-       gboolean is_idle;
-
-       priv = GET_PRIV (idle);
-
-       is_idle = (status == SESSION_STATUS_IDLE);
-
-       DEBUG ("Session idle state changed, %s -> %s",
-               priv->is_idle ? "yes" : "no",
-               is_idle ? "yes" : "no");
-
-       if (!priv->auto_away ||
-           (priv->saved_state == TP_CONNECTION_PRESENCE_TYPE_UNSET &&
-            (priv->state <= TP_CONNECTION_PRESENCE_TYPE_OFFLINE ||
-             priv->state == TP_CONNECTION_PRESENCE_TYPE_HIDDEN))) {
-               /* We don't want to go auto away OR we explicitely asked to be
-                * offline, nothing to do here */
-               priv->is_idle = is_idle;
-               return;
-       }
-
-       if (is_idle && !priv->is_idle) {
-               TpConnectionPresenceType new_state;
-               /* We are now idle */
-
-               idle_ext_away_start (idle);
-
-               if (priv->saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
-                       /* We are disconnected, when coming back from away
-                        * we want to restore the presence before the
-                        * disconnection. */
-                       priv->away_saved_state = priv->saved_state;
-               } else {
-                       priv->away_saved_state = priv->state;
-               }
-
-               new_state = TP_CONNECTION_PRESENCE_TYPE_AWAY;
-               if (priv->state == TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY) {
-                       new_state = TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY;
-               }
-
-               DEBUG ("Going to autoaway. Saved state=%d, new state=%d",
-                       priv->away_saved_state, new_state);
-               empathy_idle_set_state (idle, new_state);
-       } else if (!is_idle && priv->is_idle) {
-               /* We are no more idle, restore state */
-
-               idle_ext_away_stop (idle);
-
-               /* Only try and set the presence if the away saved state is not
-                * unset. This is an odd case because it means that the session
-                * didn't notify us of the state change to idle, and as a
-                * result, we couldn't save the current state at that time.
-                */
-               if (priv->away_saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
-                       DEBUG ("Restoring state to %d",
-                               priv->away_saved_state);
-
-                       empathy_idle_set_state (idle,priv->away_saved_state);
-               } else {
-                       DEBUG ("Away saved state is unset. This means that we "
-                              "weren't told when the session went idle. "
-                              "As a result, I'm not trying to set presence");
-               }
-
-               priv->away_saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
-       }
-
-       priv->is_idle = is_idle;
-}
-
-static void
-idle_state_change_cb (EmpathyConnectivity *connectivity,
-                     gboolean new_online,
-                     EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (!new_online) {
-               /* We are no longer connected */
-               DEBUG ("Disconnected: Save state %d (%s)",
-                               priv->state, priv->status);
-               priv->saved_state = priv->state;
-               g_free (priv->saved_status);
-               priv->saved_status = g_strdup (priv->status);
-               empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
-       }
-       else if (new_online
-                       && priv->saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
-               /* We are now connected */
-               DEBUG ("Reconnected: Restore state %d (%s)",
-                               priv->saved_state, priv->saved_status);
-               empathy_idle_set_presence (idle,
-                               priv->saved_state,
-                               priv->saved_status);
-               priv->saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
-               g_free (priv->saved_status);
-               priv->saved_status = NULL;
-       }
-}
-
-static void
-idle_finalize (GObject *object)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (object);
-
-       g_free (priv->status);
-       g_free (priv->requested_status_message);
-
-       if (priv->gs_proxy) {
-               g_object_unref (priv->gs_proxy);
-       }
-
-       g_signal_handler_disconnect (priv->connectivity,
-                                    priv->state_change_signal_id);
-       priv->state_change_signal_id = 0;
-
-       if (priv->manager != NULL) {
-               g_signal_handler_disconnect (priv->manager,
-                       priv->idle_presence_changed_id);
-               g_object_unref (priv->manager);
-       }
-
-       g_object_unref (priv->connectivity);
-
-       g_hash_table_destroy (priv->connect_times);
-       priv->connect_times = NULL;
-
-       idle_ext_away_stop (EMPATHY_IDLE (object));
-}
-
-static GObject *
-idle_constructor (GType type,
-                 guint n_props,
-                 GObjectConstructParam *props)
-{
-       GObject *retval;
-
-       if (idle_singleton) {
-               retval = g_object_ref (idle_singleton);
-       } else {
-               retval = G_OBJECT_CLASS (empathy_idle_parent_class)->constructor
-                       (type, n_props, props);
-
-               idle_singleton = EMPATHY_IDLE (retval);
-               g_object_add_weak_pointer (retval, (gpointer) &idle_singleton);
-       }
-
-       return retval;
-}
-
-static const gchar *
-empathy_idle_get_status (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (G_UNLIKELY (!priv->ready))
-               g_critical (G_STRLOC ": %s called before AccountManager ready",
-                               G_STRFUNC);
-
-       if (!priv->status) {
-               return empathy_presence_get_default_message (priv->state);
-       }
-
-       return priv->status;
-}
-
-static void
-idle_get_property (GObject    *object,
-                  guint       param_id,
-                  GValue     *value,
-                  GParamSpec *pspec)
-{
-       EmpathyIdlePriv *priv;
-       EmpathyIdle     *idle;
-
-       priv = GET_PRIV (object);
-       idle = EMPATHY_IDLE (object);
-
-       switch (param_id) {
-       case PROP_STATE:
-               g_value_set_enum (value, empathy_idle_get_state (idle));
-               break;
-       case PROP_STATUS:
-               g_value_set_string (value, empathy_idle_get_status (idle));
-               break;
-       case PROP_AUTO_AWAY:
-               g_value_set_boolean (value, empathy_idle_get_auto_away (idle));
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-               break;
-       };
-}
-
-static void
-idle_set_property (GObject      *object,
-                  guint         param_id,
-                  const GValue *value,
-                  GParamSpec   *pspec)
-{
-       EmpathyIdlePriv *priv;
-       EmpathyIdle     *idle;
-
-       priv = GET_PRIV (object);
-       idle = EMPATHY_IDLE (object);
-
-       switch (param_id) {
-       case PROP_STATE:
-               empathy_idle_set_state (idle, g_value_get_enum (value));
-               break;
-       case PROP_STATUS:
-               empathy_idle_set_status (idle, g_value_get_string (value));
-               break;
-       case PROP_AUTO_AWAY:
-               empathy_idle_set_auto_away (idle, g_value_get_boolean (value));
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-               break;
-       };
-}
-
-static void
-empathy_idle_class_init (EmpathyIdleClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = idle_finalize;
-       object_class->constructor = idle_constructor;
-       object_class->get_property = idle_get_property;
-       object_class->set_property = idle_set_property;
-
-       g_object_class_install_property (object_class,
-                                        PROP_STATE,
-                                        g_param_spec_uint ("state",
-                                                           "state",
-                                                           "state",
-                                                           0, NUM_TP_CONNECTION_PRESENCE_TYPES,
-                                                           TP_CONNECTION_PRESENCE_TYPE_UNSET,
-                                                           G_PARAM_READWRITE));
-       g_object_class_install_property (object_class,
-                                        PROP_STATUS,
-                                        g_param_spec_string ("status",
-                                                             "status",
-                                                             "status",
-                                                             NULL,
-                                                             G_PARAM_READWRITE));
-
-        g_object_class_install_property (object_class,
-                                         PROP_AUTO_AWAY,
-                                         g_param_spec_boolean ("auto-away",
-                                                               "Automatic set presence to away",
-                                                               "Should it set presence to away if inactive",
-                                                               FALSE,
-                                                               G_PARAM_READWRITE));
-
-       g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv));
-}
-
-static void
-account_status_changed_cb (TpAccount  *account,
-                          guint       old_status,
-                          guint       new_status,
-                          guint       reason,
-                          gchar      *dbus_error_name,
-                          GHashTable *details,
-                          gpointer    user_data)
-{
-       EmpathyIdle *idle = EMPATHY_IDLE (user_data);
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-       GTimeVal val;
-
-       if (new_status == TP_CONNECTION_STATUS_CONNECTED) {
-               g_get_current_time (&val);
-               g_hash_table_insert (priv->connect_times, account,
-                                    GINT_TO_POINTER (val.tv_sec));
-       } else if (new_status == TP_CONNECTION_STATUS_DISCONNECTED) {
-               g_hash_table_remove (priv->connect_times, account);
-       }
-}
-
-static void
-account_manager_ready_cb (GObject *source_object,
-                         GAsyncResult *result,
-                         gpointer user_data)
-{
-       EmpathyIdle *idle = user_data;
-       TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
-       EmpathyIdlePriv *priv;
-       TpConnectionPresenceType state;
-       gchar *status, *status_message;
-       GList *accounts, *l;
-       GError *error = NULL;
-
-       /* In case we've been finalized before reading this callback */
-       if (idle_singleton == NULL)
-               return;
-
-       priv = GET_PRIV (idle);
-       priv->ready = TRUE;
-
-       if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
-               DEBUG ("Failed to prepare account manager: %s", error->message);
-               g_error_free (error);
-               return;
-       }
-
-       state = tp_account_manager_get_most_available_presence (priv->manager,
-               &status, &status_message);
-
-       idle_presence_changed_cb (account_manager, state, status,
-               status_message, idle);
-
-       accounts = tp_account_manager_get_valid_accounts (priv->manager);
-       for (l = accounts; l != NULL; l = l->next) {
-               tp_g_signal_connect_object (l->data, "status-changed",
-                                            G_CALLBACK (account_status_changed_cb),
-                                            idle, 0);
-       }
-       g_list_free (accounts);
-
-       g_free (status);
-       g_free (status_message);
-}
-
-static void
-empathy_idle_init (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle,
-               EMPATHY_TYPE_IDLE, EmpathyIdlePriv);
-       TpDBusDaemon *dbus;
-
-       idle->priv = priv;
-       priv->is_idle = FALSE;
-
-       priv->manager = tp_account_manager_dup ();
-
-       tp_account_manager_prepare_async (priv->manager, NULL,
-           account_manager_ready_cb, idle);
-
-       priv->idle_presence_changed_id = g_signal_connect (priv->manager,
-               "most-available-presence-changed",
-               G_CALLBACK (idle_presence_changed_cb), idle);
-
-       dbus = tp_dbus_daemon_dup (NULL);
-
-       priv->gs_proxy = dbus_g_proxy_new_for_name (
-                                                   tp_proxy_get_dbus_connection (dbus),
-                                                   "org.gnome.SessionManager",
-                                                   "/org/gnome/SessionManager/Presence",
-                                                   "org.gnome.SessionManager.Presence");
-       if (priv->gs_proxy) {
-               dbus_g_proxy_add_signal (priv->gs_proxy, "StatusChanged",
-                                        G_TYPE_UINT, G_TYPE_INVALID);
-               dbus_g_proxy_connect_signal (priv->gs_proxy, "StatusChanged",
-                                            G_CALLBACK (idle_session_status_changed_cb),
-                                            idle, NULL);
-       } else {
-               DEBUG ("Failed to get gs proxy");
-       }
-
-       g_object_unref (dbus);
-
-       priv->connectivity = empathy_connectivity_dup_singleton ();
-       priv->state_change_signal_id = g_signal_connect (priv->connectivity,
-           "state-change", G_CALLBACK (idle_state_change_cb), idle);
-
-       priv->connect_times = g_hash_table_new (g_direct_hash, g_direct_equal);
-}
-
-EmpathyIdle *
-empathy_idle_dup_singleton (void)
-{
-       return g_object_new (EMPATHY_TYPE_IDLE, NULL);
-}
-
-TpConnectionPresenceType
-empathy_idle_get_state (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       if (G_UNLIKELY (!priv->ready))
-               g_critical (G_STRLOC ": %s called before AccountManager ready",
-                               G_STRFUNC);
-
-       return priv->state;
-}
-
-void
-empathy_idle_set_state (EmpathyIdle *idle,
-                       TpConnectionPresenceType   state)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       empathy_idle_set_presence (idle, state, priv->status);
-}
-
-void
-empathy_idle_set_status (EmpathyIdle *idle,
-                        const gchar *status)
-{
-       EmpathyIdlePriv *priv;
-
-       priv = GET_PRIV (idle);
-
-       empathy_idle_set_presence (idle, priv->state, status);
-}
-
-static void
-empathy_idle_do_set_presence (EmpathyIdle *idle,
-                          TpConnectionPresenceType status_type,
-                          const gchar *status_message)
-{
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-       const gchar *status;
-
-       g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES);
-
-       status = presence_type_to_status[status_type];
-
-       g_return_if_fail (status != NULL);
-
-       /* We possibly should be sure that the account manager is prepared, but
-        * sometimes this isn't possible, like when exiting. In other words,
-        * we need a callback to empathy_idle_set_presence to be sure the
-        * presence is set on all accounts successfully.
-        * However, in practice, this is fine as we've already prepared the
-        * account manager here in _init. */
-       tp_account_manager_set_all_requested_presences (priv->manager,
-               status_type, status, status_message);
-}
-
-void
-empathy_idle_set_presence (EmpathyIdle *idle,
-                          TpConnectionPresenceType   state,
-                          const gchar *status)
-{
-       EmpathyIdlePriv *priv;
-       const gchar     *default_status;
-
-       priv = GET_PRIV (idle);
-
-       DEBUG ("Changing presence to %s (%d)", status, state);
-
-       g_free (priv->requested_status_message);
-       priv->requested_presence_type = state;
-       priv->requested_status_message = g_strdup (status);
-
-       /* Do not set translated default messages */
-       default_status = empathy_presence_get_default_message (state);
-       if (!tp_strdiff (status, default_status)) {
-               status = NULL;
-       }
-
-       if (state != TP_CONNECTION_PRESENCE_TYPE_OFFLINE &&
-                       !empathy_connectivity_is_online (priv->connectivity)) {
-               DEBUG ("Empathy is not online");
-
-               priv->saved_state = state;
-               if (tp_strdiff (priv->status, status)) {
-                       g_free (priv->saved_status);
-                       priv->saved_status = NULL;
-                       if (!EMP_STR_EMPTY (status)) {
-                               priv->saved_status = g_strdup (status);
-                       }
-               }
-               return;
-       }
-
-       empathy_idle_do_set_presence (idle, state, status);
-}
-
-gboolean
-empathy_idle_get_auto_away (EmpathyIdle *idle)
-{
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-
-       return priv->auto_away;
-}
-
-void
-empathy_idle_set_auto_away (EmpathyIdle *idle,
-                           gboolean     auto_away)
-{
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-
-       priv->auto_away = auto_away;
-
-       g_object_notify (G_OBJECT (idle), "auto-away");
-}
-
-TpConnectionPresenceType
-empathy_idle_get_requested_presence (EmpathyIdle *idle,
-    gchar **status,
-    gchar **status_message)
-{
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-
-       if (status != NULL) {
-               *status = g_strdup (presence_type_to_status[priv->requested_presence_type]);
-       }
-
-       if (status_message != NULL) {
-               *status_message = g_strdup (priv->requested_status_message);
-       }
-
-       return priv->requested_presence_type;
-}
-
-/* This function returns %TRUE if EmpathyIdle considers the account
- * @account as having just connected recently. Otherwise, it returns
- * %FALSE. In doubt, %FALSE is returned. */
-gboolean
-empathy_idle_account_is_just_connected (EmpathyIdle *idle,
-                                       TpAccount *account)
-{
-       EmpathyIdlePriv *priv = GET_PRIV (idle);
-       GTimeVal val;
-       gpointer ptr;
-       glong t;
-
-       if (tp_account_get_connection_status (account, NULL)
-           != TP_CONNECTION_STATUS_CONNECTED) {
-               return FALSE;
-       }
-
-       ptr = g_hash_table_lookup (priv->connect_times, account);
-
-       if (ptr == NULL) {
-               return FALSE;
-       }
-
-       t = GPOINTER_TO_INT (ptr);
-
-       g_get_current_time (&val);
-
-       return (val.tv_sec - t) < ACCOUNT_IS_JUST_CONNECTED_SECONDS;
-}
diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h
deleted file mode 100644 (file)
index 95b99dc..0000000
+++ /dev/null
@@ -1,74 +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>
- */
-
-#ifndef __EMPATHY_IDLE_H__
-#define __EMPATHY_IDLE_H__
-
-#include <glib.h>
-
-#include <telepathy-glib/account.h>
-#include <telepathy-glib/enums.h>
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_IDLE         (empathy_idle_get_type ())
-#define EMPATHY_IDLE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_IDLE, EmpathyIdle))
-#define EMPATHY_IDLE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_IDLE, EmpathyIdleClass))
-#define EMPATHY_IS_IDLE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_IDLE))
-#define EMPATHY_IS_IDLE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_IDLE))
-#define EMPATHY_IDLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IDLE, EmpathyIdleClass))
-
-typedef struct _EmpathyIdle      EmpathyIdle;
-typedef struct _EmpathyIdleClass EmpathyIdleClass;
-
-struct _EmpathyIdle {
-       GObject parent;
-       gpointer priv;
-};
-
-struct _EmpathyIdleClass {
-       GObjectClass parent_class;
-};
-
-GType        empathy_idle_get_type            (void) G_GNUC_CONST;
-EmpathyIdle *empathy_idle_dup_singleton       (void);
-TpConnectionPresenceType   empathy_idle_get_state           (EmpathyIdle *idle);
-void         empathy_idle_set_state           (EmpathyIdle *idle,
-                                              TpConnectionPresenceType   state);
-void         empathy_idle_set_status          (EmpathyIdle *idle,
-                                              const gchar *status);
-void         empathy_idle_set_presence        (EmpathyIdle *idle,
-                                              TpConnectionPresenceType   state,
-                                              const gchar *status);
-gboolean     empathy_idle_get_auto_away       (EmpathyIdle *idle);
-void         empathy_idle_set_auto_away       (EmpathyIdle *idle,
-                                              gboolean     auto_away);
-
-TpConnectionPresenceType empathy_idle_get_requested_presence (EmpathyIdle *idle,
-                                                             gchar **status,
-                                                             gchar **status_message);
-
-gboolean empathy_idle_account_is_just_connected (EmpathyIdle *idle,
-                                                TpAccount *account);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_IDLE_H__ */
diff --git a/libempathy/empathy-presence-manager.c b/libempathy/empathy-presence-manager.c
new file mode 100644 (file)
index 0000000..035b50a
--- /dev/null
@@ -0,0 +1,733 @@
+/* -*- 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 "empathy-presence-manager.h"
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/account-manager.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/util.h>
+
+#include "empathy-utils.h"
+#include "empathy-connectivity.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
+#include "empathy-debug.h"
+
+/* Number of seconds before entering extended autoaway. */
+#define EXT_AWAY_TIME (30*60)
+
+/* Number of seconds to consider an account in the "just connected" state
+ * for. */
+#define ACCOUNT_IS_JUST_CONNECTED_SECONDS 10
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyPresenceManager)
+typedef struct {
+       DBusGProxy     *gs_proxy;
+       EmpathyConnectivity *connectivity;
+       gulong state_change_signal_id;
+
+       gboolean ready;
+
+       TpConnectionPresenceType      state;
+       gchar          *status;
+       gboolean        auto_away;
+
+       TpConnectionPresenceType      away_saved_state;
+       TpConnectionPresenceType      saved_state;
+       gchar          *saved_status;
+
+       gboolean        is_idle;
+       guint           ext_away_timeout;
+
+       TpAccountManager *manager;
+       gulong idle_presence_changed_id;
+
+       /* pointer to a TpAccount --> glong of time of connection */
+       GHashTable *connect_times;
+
+       TpConnectionPresenceType requested_presence_type;
+       gchar *requested_status_message;
+
+} EmpathyPresenceManagerPriv;
+
+typedef enum {
+       SESSION_STATUS_AVAILABLE,
+       SESSION_STATUS_INVISIBLE,
+       SESSION_STATUS_BUSY,
+       SESSION_STATUS_IDLE,
+       SESSION_STATUS_UNKNOWN
+} SessionStatus;
+
+enum {
+       PROP_0,
+       PROP_STATE,
+       PROP_STATUS,
+       PROP_AUTO_AWAY
+};
+
+G_DEFINE_TYPE (EmpathyPresenceManager, empathy_presence_manager, G_TYPE_OBJECT);
+
+static EmpathyPresenceManager * idle_singleton = NULL;
+
+static const gchar *presence_type_to_status[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
+       NULL,
+       "offline",
+       "available",
+       "away",
+       "xa",
+       "hidden",
+       "busy",
+       NULL,
+       NULL,
+};
+
+static void
+idle_presence_changed_cb (TpAccountManager *manager,
+                         TpConnectionPresenceType state,
+                         gchar          *status,
+                         gchar          *status_message,
+                         EmpathyPresenceManager    *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (state == TP_CONNECTION_PRESENCE_TYPE_UNSET)
+               /* Assume our presence is offline if MC reports UNSET */
+               state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
+
+       DEBUG ("Presence changed to '%s' (%d) \"%s\"", status, state,
+               status_message);
+
+       g_free (priv->status);
+       priv->state = state;
+       if (EMP_STR_EMPTY (status_message))
+               priv->status = NULL;
+       else
+               priv->status = g_strdup (status_message);
+
+       g_object_notify (G_OBJECT (idle), "state");
+       g_object_notify (G_OBJECT (idle), "status");
+}
+
+static gboolean
+idle_ext_away_cb (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       DEBUG ("Going to extended autoaway");
+       empathy_presence_manager_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY);
+       priv->ext_away_timeout = 0;
+
+       return FALSE;
+}
+
+static void
+idle_ext_away_stop (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (priv->ext_away_timeout) {
+               g_source_remove (priv->ext_away_timeout);
+               priv->ext_away_timeout = 0;
+       }
+}
+
+static void
+idle_ext_away_start (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (priv->ext_away_timeout != 0) {
+               return;
+       }
+       priv->ext_away_timeout = g_timeout_add_seconds (EXT_AWAY_TIME,
+                                                       (GSourceFunc) idle_ext_away_cb,
+                                                       idle);
+}
+
+static void
+idle_session_status_changed_cb (DBusGProxy    *gs_proxy,
+                               SessionStatus  status,
+                               EmpathyPresenceManager   *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+       gboolean is_idle;
+
+       priv = GET_PRIV (idle);
+
+       is_idle = (status == SESSION_STATUS_IDLE);
+
+       DEBUG ("Session idle state changed, %s -> %s",
+               priv->is_idle ? "yes" : "no",
+               is_idle ? "yes" : "no");
+
+       if (!priv->auto_away ||
+           (priv->saved_state == TP_CONNECTION_PRESENCE_TYPE_UNSET &&
+            (priv->state <= TP_CONNECTION_PRESENCE_TYPE_OFFLINE ||
+             priv->state == TP_CONNECTION_PRESENCE_TYPE_HIDDEN))) {
+               /* We don't want to go auto away OR we explicitely asked to be
+                * offline, nothing to do here */
+               priv->is_idle = is_idle;
+               return;
+       }
+
+       if (is_idle && !priv->is_idle) {
+               TpConnectionPresenceType new_state;
+               /* We are now idle */
+
+               idle_ext_away_start (idle);
+
+               if (priv->saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
+                       /* We are disconnected, when coming back from away
+                        * we want to restore the presence before the
+                        * disconnection. */
+                       priv->away_saved_state = priv->saved_state;
+               } else {
+                       priv->away_saved_state = priv->state;
+               }
+
+               new_state = TP_CONNECTION_PRESENCE_TYPE_AWAY;
+               if (priv->state == TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY) {
+                       new_state = TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY;
+               }
+
+               DEBUG ("Going to autoaway. Saved state=%d, new state=%d",
+                       priv->away_saved_state, new_state);
+               empathy_presence_manager_set_state (idle, new_state);
+       } else if (!is_idle && priv->is_idle) {
+               /* We are no more idle, restore state */
+
+               idle_ext_away_stop (idle);
+
+               /* Only try and set the presence if the away saved state is not
+                * unset. This is an odd case because it means that the session
+                * didn't notify us of the state change to idle, and as a
+                * result, we couldn't save the current state at that time.
+                */
+               if (priv->away_saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
+                       DEBUG ("Restoring state to %d",
+                               priv->away_saved_state);
+
+                       empathy_presence_manager_set_state (idle,priv->away_saved_state);
+               } else {
+                       DEBUG ("Away saved state is unset. This means that we "
+                              "weren't told when the session went idle. "
+                              "As a result, I'm not trying to set presence");
+               }
+
+               priv->away_saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
+       }
+
+       priv->is_idle = is_idle;
+}
+
+static void
+idle_state_change_cb (EmpathyConnectivity *connectivity,
+                     gboolean new_online,
+                     EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (!new_online) {
+               /* We are no longer connected */
+               DEBUG ("Disconnected: Save state %d (%s)",
+                               priv->state, priv->status);
+               priv->saved_state = priv->state;
+               g_free (priv->saved_status);
+               priv->saved_status = g_strdup (priv->status);
+               empathy_presence_manager_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
+       }
+       else if (new_online
+                       && priv->saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
+               /* We are now connected */
+               DEBUG ("Reconnected: Restore state %d (%s)",
+                               priv->saved_state, priv->saved_status);
+               empathy_presence_manager_set_presence (idle,
+                               priv->saved_state,
+                               priv->saved_status);
+               priv->saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
+               g_free (priv->saved_status);
+               priv->saved_status = NULL;
+       }
+}
+
+static void
+idle_finalize (GObject *object)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       g_free (priv->status);
+       g_free (priv->requested_status_message);
+
+       if (priv->gs_proxy) {
+               g_object_unref (priv->gs_proxy);
+       }
+
+       g_signal_handler_disconnect (priv->connectivity,
+                                    priv->state_change_signal_id);
+       priv->state_change_signal_id = 0;
+
+       if (priv->manager != NULL) {
+               g_signal_handler_disconnect (priv->manager,
+                       priv->idle_presence_changed_id);
+               g_object_unref (priv->manager);
+       }
+
+       g_object_unref (priv->connectivity);
+
+       g_hash_table_destroy (priv->connect_times);
+       priv->connect_times = NULL;
+
+       idle_ext_away_stop (EMPATHY_PRESENCE_MANAGER (object));
+}
+
+static GObject *
+idle_constructor (GType type,
+                 guint n_props,
+                 GObjectConstructParam *props)
+{
+       GObject *retval;
+
+       if (idle_singleton) {
+               retval = g_object_ref (idle_singleton);
+       } else {
+               retval = G_OBJECT_CLASS (empathy_presence_manager_parent_class)->constructor
+                       (type, n_props, props);
+
+               idle_singleton = EMPATHY_PRESENCE_MANAGER (retval);
+               g_object_add_weak_pointer (retval, (gpointer) &idle_singleton);
+       }
+
+       return retval;
+}
+
+static const gchar *
+empathy_presence_manager_get_status (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (G_UNLIKELY (!priv->ready))
+               g_critical (G_STRLOC ": %s called before AccountManager ready",
+                               G_STRFUNC);
+
+       if (!priv->status) {
+               return empathy_presence_get_default_message (priv->state);
+       }
+
+       return priv->status;
+}
+
+static void
+idle_get_property (GObject    *object,
+                  guint       param_id,
+                  GValue     *value,
+                  GParamSpec *pspec)
+{
+       EmpathyPresenceManagerPriv *priv;
+       EmpathyPresenceManager     *idle;
+
+       priv = GET_PRIV (object);
+       idle = EMPATHY_PRESENCE_MANAGER (object);
+
+       switch (param_id) {
+       case PROP_STATE:
+               g_value_set_enum (value, empathy_presence_manager_get_state (idle));
+               break;
+       case PROP_STATUS:
+               g_value_set_string (value, empathy_presence_manager_get_status (idle));
+               break;
+       case PROP_AUTO_AWAY:
+               g_value_set_boolean (value, empathy_presence_manager_get_auto_away (idle));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       };
+}
+
+static void
+idle_set_property (GObject      *object,
+                  guint         param_id,
+                  const GValue *value,
+                  GParamSpec   *pspec)
+{
+       EmpathyPresenceManagerPriv *priv;
+       EmpathyPresenceManager     *idle;
+
+       priv = GET_PRIV (object);
+       idle = EMPATHY_PRESENCE_MANAGER (object);
+
+       switch (param_id) {
+       case PROP_STATE:
+               empathy_presence_manager_set_state (idle, g_value_get_enum (value));
+               break;
+       case PROP_STATUS:
+               empathy_presence_manager_set_status (idle, g_value_get_string (value));
+               break;
+       case PROP_AUTO_AWAY:
+               empathy_presence_manager_set_auto_away (idle, g_value_get_boolean (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       };
+}
+
+static void
+empathy_presence_manager_class_init (EmpathyPresenceManagerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = idle_finalize;
+       object_class->constructor = idle_constructor;
+       object_class->get_property = idle_get_property;
+       object_class->set_property = idle_set_property;
+
+       g_object_class_install_property (object_class,
+                                        PROP_STATE,
+                                        g_param_spec_uint ("state",
+                                                           "state",
+                                                           "state",
+                                                           0, NUM_TP_CONNECTION_PRESENCE_TYPES,
+                                                           TP_CONNECTION_PRESENCE_TYPE_UNSET,
+                                                           G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_STATUS,
+                                        g_param_spec_string ("status",
+                                                             "status",
+                                                             "status",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+        g_object_class_install_property (object_class,
+                                         PROP_AUTO_AWAY,
+                                         g_param_spec_boolean ("auto-away",
+                                                               "Automatic set presence to away",
+                                                               "Should it set presence to away if inactive",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE));
+
+       g_type_class_add_private (object_class, sizeof (EmpathyPresenceManagerPriv));
+}
+
+static void
+account_status_changed_cb (TpAccount  *account,
+                          guint       old_status,
+                          guint       new_status,
+                          guint       reason,
+                          gchar      *dbus_error_name,
+                          GHashTable *details,
+                          gpointer    user_data)
+{
+       EmpathyPresenceManager *idle = EMPATHY_PRESENCE_MANAGER (user_data);
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+       GTimeVal val;
+
+       if (new_status == TP_CONNECTION_STATUS_CONNECTED) {
+               g_get_current_time (&val);
+               g_hash_table_insert (priv->connect_times, account,
+                                    GINT_TO_POINTER (val.tv_sec));
+       } else if (new_status == TP_CONNECTION_STATUS_DISCONNECTED) {
+               g_hash_table_remove (priv->connect_times, account);
+       }
+}
+
+static void
+account_manager_ready_cb (GObject *source_object,
+                         GAsyncResult *result,
+                         gpointer user_data)
+{
+       EmpathyPresenceManager *idle = user_data;
+       TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
+       EmpathyPresenceManagerPriv *priv;
+       TpConnectionPresenceType state;
+       gchar *status, *status_message;
+       GList *accounts, *l;
+       GError *error = NULL;
+
+       /* In case we've been finalized before reading this callback */
+       if (idle_singleton == NULL)
+               return;
+
+       priv = GET_PRIV (idle);
+       priv->ready = TRUE;
+
+       if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
+               DEBUG ("Failed to prepare account manager: %s", error->message);
+               g_error_free (error);
+               return;
+       }
+
+       state = tp_account_manager_get_most_available_presence (priv->manager,
+               &status, &status_message);
+
+       idle_presence_changed_cb (account_manager, state, status,
+               status_message, idle);
+
+       accounts = tp_account_manager_get_valid_accounts (priv->manager);
+       for (l = accounts; l != NULL; l = l->next) {
+               tp_g_signal_connect_object (l->data, "status-changed",
+                                            G_CALLBACK (account_status_changed_cb),
+                                            idle, 0);
+       }
+       g_list_free (accounts);
+
+       g_free (status);
+       g_free (status_message);
+}
+
+static void
+empathy_presence_manager_init (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle,
+               EMPATHY_TYPE_PRESENCE_MANAGER, EmpathyPresenceManagerPriv);
+       TpDBusDaemon *dbus;
+
+       idle->priv = priv;
+       priv->is_idle = FALSE;
+
+       priv->manager = tp_account_manager_dup ();
+
+       tp_account_manager_prepare_async (priv->manager, NULL,
+           account_manager_ready_cb, idle);
+
+       priv->idle_presence_changed_id = g_signal_connect (priv->manager,
+               "most-available-presence-changed",
+               G_CALLBACK (idle_presence_changed_cb), idle);
+
+       dbus = tp_dbus_daemon_dup (NULL);
+
+       priv->gs_proxy = dbus_g_proxy_new_for_name (
+                                                   tp_proxy_get_dbus_connection (dbus),
+                                                   "org.gnome.SessionManager",
+                                                   "/org/gnome/SessionManager/Presence",
+                                                   "org.gnome.SessionManager.Presence");
+       if (priv->gs_proxy) {
+               dbus_g_proxy_add_signal (priv->gs_proxy, "StatusChanged",
+                                        G_TYPE_UINT, G_TYPE_INVALID);
+               dbus_g_proxy_connect_signal (priv->gs_proxy, "StatusChanged",
+                                            G_CALLBACK (idle_session_status_changed_cb),
+                                            idle, NULL);
+       } else {
+               DEBUG ("Failed to get gs proxy");
+       }
+
+       g_object_unref (dbus);
+
+       priv->connectivity = empathy_connectivity_dup_singleton ();
+       priv->state_change_signal_id = g_signal_connect (priv->connectivity,
+           "state-change", G_CALLBACK (idle_state_change_cb), idle);
+
+       priv->connect_times = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+EmpathyPresenceManager *
+empathy_presence_manager_dup_singleton (void)
+{
+       return g_object_new (EMPATHY_TYPE_PRESENCE_MANAGER, NULL);
+}
+
+TpConnectionPresenceType
+empathy_presence_manager_get_state (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       if (G_UNLIKELY (!priv->ready))
+               g_critical (G_STRLOC ": %s called before AccountManager ready",
+                               G_STRFUNC);
+
+       return priv->state;
+}
+
+void
+empathy_presence_manager_set_state (EmpathyPresenceManager *idle,
+                       TpConnectionPresenceType   state)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       empathy_presence_manager_set_presence (idle, state, priv->status);
+}
+
+void
+empathy_presence_manager_set_status (EmpathyPresenceManager *idle,
+                        const gchar *status)
+{
+       EmpathyPresenceManagerPriv *priv;
+
+       priv = GET_PRIV (idle);
+
+       empathy_presence_manager_set_presence (idle, priv->state, status);
+}
+
+static void
+empathy_presence_manager_do_set_presence (EmpathyPresenceManager *idle,
+                          TpConnectionPresenceType status_type,
+                          const gchar *status_message)
+{
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+       const gchar *status;
+
+       g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES);
+
+       status = presence_type_to_status[status_type];
+
+       g_return_if_fail (status != NULL);
+
+       /* We possibly should be sure that the account manager is prepared, but
+        * sometimes this isn't possible, like when exiting. In other words,
+        * we need a callback to empathy_presence_manager_set_presence to be sure the
+        * presence is set on all accounts successfully.
+        * However, in practice, this is fine as we've already prepared the
+        * account manager here in _init. */
+       tp_account_manager_set_all_requested_presences (priv->manager,
+               status_type, status, status_message);
+}
+
+void
+empathy_presence_manager_set_presence (EmpathyPresenceManager *idle,
+                          TpConnectionPresenceType   state,
+                          const gchar *status)
+{
+       EmpathyPresenceManagerPriv *priv;
+       const gchar     *default_status;
+
+       priv = GET_PRIV (idle);
+
+       DEBUG ("Changing presence to %s (%d)", status, state);
+
+       g_free (priv->requested_status_message);
+       priv->requested_presence_type = state;
+       priv->requested_status_message = g_strdup (status);
+
+       /* Do not set translated default messages */
+       default_status = empathy_presence_get_default_message (state);
+       if (!tp_strdiff (status, default_status)) {
+               status = NULL;
+       }
+
+       if (state != TP_CONNECTION_PRESENCE_TYPE_OFFLINE &&
+                       !empathy_connectivity_is_online (priv->connectivity)) {
+               DEBUG ("Empathy is not online");
+
+               priv->saved_state = state;
+               if (tp_strdiff (priv->status, status)) {
+                       g_free (priv->saved_status);
+                       priv->saved_status = NULL;
+                       if (!EMP_STR_EMPTY (status)) {
+                               priv->saved_status = g_strdup (status);
+                       }
+               }
+               return;
+       }
+
+       empathy_presence_manager_do_set_presence (idle, state, status);
+}
+
+gboolean
+empathy_presence_manager_get_auto_away (EmpathyPresenceManager *idle)
+{
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+
+       return priv->auto_away;
+}
+
+void
+empathy_presence_manager_set_auto_away (EmpathyPresenceManager *idle,
+                           gboolean     auto_away)
+{
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+
+       priv->auto_away = auto_away;
+
+       g_object_notify (G_OBJECT (idle), "auto-away");
+}
+
+TpConnectionPresenceType
+empathy_presence_manager_get_requested_presence (EmpathyPresenceManager *idle,
+    gchar **status,
+    gchar **status_message)
+{
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+
+       if (status != NULL) {
+               *status = g_strdup (presence_type_to_status[priv->requested_presence_type]);
+       }
+
+       if (status_message != NULL) {
+               *status_message = g_strdup (priv->requested_status_message);
+       }
+
+       return priv->requested_presence_type;
+}
+
+/* This function returns %TRUE if EmpathyPresenceManager considers the account
+ * @account as having just connected recently. Otherwise, it returns
+ * %FALSE. In doubt, %FALSE is returned. */
+gboolean
+empathy_presence_manager_account_is_just_connected (EmpathyPresenceManager *idle,
+                                       TpAccount *account)
+{
+       EmpathyPresenceManagerPriv *priv = GET_PRIV (idle);
+       GTimeVal val;
+       gpointer ptr;
+       glong t;
+
+       if (tp_account_get_connection_status (account, NULL)
+           != TP_CONNECTION_STATUS_CONNECTED) {
+               return FALSE;
+       }
+
+       ptr = g_hash_table_lookup (priv->connect_times, account);
+
+       if (ptr == NULL) {
+               return FALSE;
+       }
+
+       t = GPOINTER_TO_INT (ptr);
+
+       g_get_current_time (&val);
+
+       return (val.tv_sec - t) < ACCOUNT_IS_JUST_CONNECTED_SECONDS;
+}
diff --git a/libempathy/empathy-presence-manager.h b/libempathy/empathy-presence-manager.h
new file mode 100644 (file)
index 0000000..bdbe4cf
--- /dev/null
@@ -0,0 +1,74 @@
+/* -*- 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>
+ */
+
+#ifndef __EMPATHY_PRESENCE_MANAGER_H__
+#define __EMPATHY_PRESENCE_MANAGER_H__
+
+#include <glib.h>
+
+#include <telepathy-glib/account.h>
+#include <telepathy-glib/enums.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_PRESENCE_MANAGER         (empathy_presence_manager_get_type ())
+#define EMPATHY_PRESENCE_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_PRESENCE_MANAGER, EmpathyPresenceManager))
+#define EMPATHY_PRESENCE_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_PRESENCE_MANAGER, EmpathyPresenceManagerClass))
+#define EMPATHY_IS_PRESENCE_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_PRESENCE_MANAGER))
+#define EMPATHY_IS_PRESENCE_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_PRESENCE_MANAGER))
+#define EMPATHY_PRESENCE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_PRESENCE_MANAGER, EmpathyPresenceManagerClass))
+
+typedef struct _EmpathyPresenceManager      EmpathyPresenceManager;
+typedef struct _EmpathyPresenceManagerClass EmpathyPresenceManagerClass;
+
+struct _EmpathyPresenceManager {
+       GObject parent;
+       gpointer priv;
+};
+
+struct _EmpathyPresenceManagerClass {
+       GObjectClass parent_class;
+};
+
+GType        empathy_presence_manager_get_type            (void) G_GNUC_CONST;
+EmpathyPresenceManager *empathy_presence_manager_dup_singleton       (void);
+TpConnectionPresenceType   empathy_presence_manager_get_state           (EmpathyPresenceManager *idle);
+void         empathy_presence_manager_set_state           (EmpathyPresenceManager *idle,
+                                              TpConnectionPresenceType   state);
+void         empathy_presence_manager_set_status          (EmpathyPresenceManager *idle,
+                                              const gchar *status);
+void         empathy_presence_manager_set_presence        (EmpathyPresenceManager *idle,
+                                              TpConnectionPresenceType   state,
+                                              const gchar *status);
+gboolean     empathy_presence_manager_get_auto_away       (EmpathyPresenceManager *idle);
+void         empathy_presence_manager_set_auto_away       (EmpathyPresenceManager *idle,
+                                              gboolean     auto_away);
+
+TpConnectionPresenceType empathy_presence_manager_get_requested_presence (EmpathyPresenceManager *idle,
+                                                             gchar **status,
+                                                             gchar **status_message);
+
+gboolean empathy_presence_manager_account_is_just_connected (EmpathyPresenceManager *idle,
+                                                TpAccount *account);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_PRESENCE_MANAGER_H__ */
index 6bbd53f86d4395832b64ff967d843414e73f608f..3730e43a8fc74ac62bd4ce502d14b4d22eec66ce 100644 (file)
@@ -49,7 +49,7 @@
 #include "empathy-contact-manager.h"
 #include "empathy-individual-manager.h"
 #include "empathy-dispatcher.h"
-#include "empathy-idle.h"
+#include "empathy-presence-manager.h"
 #include "empathy-tp-call.h"
 #include "empathy-tp-contact-factory.h"
 
@@ -482,11 +482,11 @@ gboolean
 empathy_check_available_state (void)
 {
        TpConnectionPresenceType presence;
-       EmpathyIdle *idle;
+       EmpathyPresenceManager *presence_mgr;
 
-       idle = empathy_idle_dup_singleton ();
-       presence = empathy_idle_get_state (idle);
-       g_object_unref (idle);
+       presence_mgr = empathy_presence_manager_dup_singleton ();
+       presence = empathy_presence_manager_get_state (presence_mgr);
+       g_object_unref (presence_mgr);
 
        if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
                presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
index 7d8fcd323c9dedd11385f05e20ecf112cd2e1ebb..db4000e66036f06e28068207c68abdab1d69bff6 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <telepathy-glib/debug-sender.h>
 
-#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-presence-manager.h>
 #include <libempathy-gtk/empathy-ui-utils.h>
 
 #include "empathy-chat-manager.h"
@@ -95,7 +95,7 @@ main (int argc,
   TpDebugSender *debug_sender;
 #endif
   GError *error = NULL;
-  EmpathyIdle *idle;
+  EmpathyPresenceManager *presence_mgr;
   gint retval;
 
   /* Init */
@@ -133,7 +133,7 @@ main (int argc,
 #endif
 
   /* Setting up Idle */
-  idle = empathy_idle_dup_singleton ();
+  presence_mgr = empathy_presence_manager_dup_singleton ();
 
   if (g_getenv ("EMPATHY_PERSIST") != NULL)
     {
@@ -152,7 +152,7 @@ main (int argc,
   retval = g_application_run (G_APPLICATION (app), argc, argv);
 
   g_object_unref (app);
-  g_object_unref (idle);
+  g_object_unref (presence_mgr);
   tp_clear_object (&chat_mgr);
 
 #ifdef ENABLE_DEBUG
index c7dd660a0f03877930c7d4488103c42b3aaadf66..b20f1719f076c1090c5bd6ededfa9e56a2a65be5 100644 (file)
@@ -29,7 +29,7 @@
 #include <telepathy-glib/interfaces.h>
 #include <telepathy-glib/simple-approver.h>
 
-#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-presence-manager.h>
 #include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
 #include <libempathy/empathy-tp-chat.h>
@@ -1092,13 +1092,13 @@ event_manager_presence_changed_cb (EmpathyContact *contact,
   EmpathyEventManagerPriv *priv = GET_PRIV (manager);
   TpAccount *account;
   gchar *header = NULL;
-  EmpathyIdle *idle;
+  EmpathyPresenceManager *presence_mgr;
   GtkWidget *window = empathy_main_window_dup ();
 
   account = empathy_contact_get_account (contact);
-  idle = empathy_idle_dup_singleton ();
+  presence_mgr = empathy_presence_manager_dup_singleton ();
 
-  if (empathy_idle_account_is_just_connected (idle, account))
+  if (empathy_presence_manager_account_is_just_connected (presence_mgr, account))
     goto out;
 
   if (tp_connection_presence_type_cmp_availability (previous,
@@ -1149,7 +1149,7 @@ event_manager_presence_changed_cb (EmpathyContact *contact,
   g_free (header);
 
 out:
-  g_object_unref (idle);
+  g_object_unref (presence_mgr);
   g_object_unref (window);
 }
 
index d7422d874db17d908105cdc1c9d6ca330be881dd..97e03dc043fd0a7f0f736259abc13cde10152e0a 100644 (file)
@@ -34,7 +34,6 @@
 #include <folks/folks.h>
 
 #include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-idle.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-dispatcher.h>
 #include <libempathy/empathy-chatroom-manager.h>
index 357b47e8e8398e6df9dc628131978a9c4da1e37f..c5de83bbee126f060cc40353d8397da2e2169457 100644 (file)
@@ -46,7 +46,7 @@
 
 #include <telepathy-logger/log-manager.h>
 
-#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-presence-manager.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-chatroom-manager.h>
 #include <libempathy/empathy-account-settings.h>
@@ -114,7 +114,7 @@ struct _EmpathyApp
   TplLogManager *log_manager;
   EmpathyChatroomManager *chatroom_manager;
   EmpathyFTFactory  *ft_factory;
-  EmpathyIdle *idle;
+  EmpathyPresenceManager *presence_mgr;
   EmpathyConnectivity *connectivity;
   GSettings *gsettings;
   EmpathyNotificationsApprover *notifications_approver;
@@ -136,16 +136,17 @@ empathy_app_dispose (GObject *object)
   void (*dispose) (GObject *) =
     G_OBJECT_CLASS (empathy_app_parent_class)->dispose;
 
-  if (self->idle != NULL)
+  if (self->presence_mgr != NULL)
     {
-      empathy_idle_set_state (self->idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
+      empathy_presence_manager_set_state (self->presence_mgr,
+          TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
     }
 
 #ifdef ENABLE_DEBUG
   tp_clear_object (&self->debug_sender);
 #endif
 
-  tp_clear_object (&self->idle);
+  tp_clear_object (&self->presence_mgr);
   tp_clear_object (&self->connectivity);
   tp_clear_object (&self->icon);
   tp_clear_object (&self->account_manager);
@@ -520,7 +521,7 @@ account_manager_ready_cb (GObject *source_object,
           (presence, TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
             <= 0)
       /* if current state is Offline, then put it online */
-      empathy_idle_set_state (self->idle,
+      empathy_presence_manager_set_state (self->presence_mgr,
           TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
 
   /* Pop up the accounts dialog if we don't have any account */
@@ -612,13 +613,13 @@ chatroom_manager_ready_cb (EmpathyChatroomManager *chatroom_manager,
 }
 
 static void
-empathy_idle_set_auto_away_cb (GSettings *gsettings,
+empathy_presence_manager_set_auto_away_cb (GSettings *gsettings,
                                const gchar *key,
                                gpointer user_data)
 {
-       EmpathyIdle *idle = user_data;
+       EmpathyPresenceManager *presence_mgr = user_data;
 
-       empathy_idle_set_auto_away (idle,
+       empathy_presence_manager_set_auto_away (presence_mgr,
       g_settings_get_boolean (gsettings, key));
 }
 
@@ -643,16 +644,17 @@ empathy_app_constructed (GObject *object)
   notify_init (_(PACKAGE_NAME));
 
   /* Setting up Idle */
-  self->idle = empathy_idle_dup_singleton ();
+  self->presence_mgr = empathy_presence_manager_dup_singleton ();
 
   self->gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
   autoaway = g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOAWAY);
 
   g_signal_connect (self->gsettings,
       "changed::" EMPATHY_PREFS_AUTOAWAY,
-      G_CALLBACK (empathy_idle_set_auto_away_cb), self->idle);
+      G_CALLBACK (empathy_presence_manager_set_auto_away_cb),
+      self->presence_mgr);
 
-  empathy_idle_set_auto_away (self->idle, autoaway);
+  empathy_presence_manager_set_auto_away (self->presence_mgr, autoaway);
 
   /* Setting up Connectivity */
   self->connectivity = empathy_connectivity_dup_singleton ();