26
26
#include <glib/gi18n-lib.h>
27
27
#include <dbus/dbus-glib.h>
29
#include <telepathy-glib/account-manager.h>
29
30
#include <telepathy-glib/dbus.h>
30
31
#include <telepathy-glib/util.h>
32
#include "empathy-account-manager.h"
33
33
#include "empathy-idle.h"
34
34
#include "empathy-utils.h"
35
35
#include "empathy-connectivity.h"
40
40
/* Number of seconds before entering extended autoaway. */
41
41
#define EXT_AWAY_TIME (30*60)
43
/* Number of seconds to consider an account in the "just connected" state
45
#define ACCOUNT_IS_JUST_CONNECTED_SECONDS 10
43
47
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIdle)
45
49
DBusGProxy *gs_proxy;
46
50
EmpathyConnectivity *connectivity;
47
51
gulong state_change_signal_id;
49
55
TpConnectionPresenceType state;
51
57
TpConnectionPresenceType flash_state;
59
65
guint ext_away_timeout;
61
EmpathyAccountManager *manager;
67
TpAccountManager *manager;
69
/* pointer to a TpAccount --> glong of time of connection */
70
GHashTable *connect_times;
72
TpConnectionPresenceType requested_presence_type;
73
gchar *requested_status_message;
82
95
static EmpathyIdle * idle_singleton = NULL;
97
static const gchar *presence_type_to_status[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
85
idle_presence_changed_cb (EmpathyAccountManager *manager,
110
idle_presence_changed_cb (TpAccountManager *manager,
86
111
TpConnectionPresenceType state,
88
113
gchar *status_message,
215
240
new_status = priv->status;
218
DEBUG ("Restoring state to %d, reset status to %s",
219
priv->away_saved_state, new_status);
243
/* Only try and set the presence if the away saved state is not
244
* unset. This is an odd case because it means that the session
245
* didn't notify us of the state change to idle, and as a
246
* result, we couldn't save the current state at that time.
248
if (priv->away_saved_state != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
249
DEBUG ("Restoring state to %d, reset status to %s",
250
priv->away_saved_state, new_status);
221
empathy_idle_set_presence (idle,
222
priv->away_saved_state,
252
empathy_idle_set_presence (idle,
253
priv->away_saved_state,
256
DEBUG ("Away saved state is unset. This means that we "
257
"weren't told when the session went idle. "
258
"As a result, I'm not trying to set presence");
225
261
priv->away_saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
453
account_status_changed_cb (TpAccount *account,
457
gchar *dbus_error_name,
461
EmpathyIdle *idle = EMPATHY_IDLE (user_data);
462
EmpathyIdlePriv *priv = GET_PRIV (idle);
465
if (new_status == TP_CONNECTION_STATUS_CONNECTED) {
466
g_get_current_time (&val);
467
g_hash_table_insert (priv->connect_times, account,
468
GINT_TO_POINTER (val.tv_sec));
469
} else if (new_status == TP_CONNECTION_STATUS_DISCONNECTED) {
470
g_hash_table_remove (priv->connect_times, account);
475
account_manager_ready_cb (GObject *source_object,
476
GAsyncResult *result,
479
EmpathyIdle *idle = EMPATHY_IDLE (user_data);
480
TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
481
EmpathyIdlePriv *priv = GET_PRIV (idle);
482
TpConnectionPresenceType state;
483
gchar *status, *status_message;
485
GError *error = NULL;
489
if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
490
DEBUG ("Failed to prepare account manager: %s", error->message);
491
g_error_free (error);
495
state = tp_account_manager_get_most_available_presence (priv->manager,
496
&status, &status_message);
498
idle_presence_changed_cb (account_manager, state, status,
499
status_message, idle);
501
accounts = tp_account_manager_get_valid_accounts (priv->manager);
502
for (l = accounts; l != NULL; l = l->next) {
503
empathy_signal_connect_weak (l->data, "status-changed",
504
G_CALLBACK (account_status_changed_cb),
507
g_list_free (accounts);
510
g_free (status_message);
413
514
empathy_idle_init (EmpathyIdle *idle)
415
516
EmpathyIdlePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle,
418
519
idle->priv = priv;
419
520
priv->is_idle = FALSE;
421
priv->manager = empathy_account_manager_dup_singleton ();
422
priv->state = empathy_account_manager_get_global_presence (priv->manager,
423
NULL, &priv->status);
426
g_signal_connect (priv->manager, "global-presence-changed",
522
priv->manager = tp_account_manager_dup ();
524
tp_account_manager_prepare_async (priv->manager, NULL,
525
account_manager_ready_cb, idle);
527
g_signal_connect (priv->manager, "most-available-presence-changed",
427
528
G_CALLBACK (idle_presence_changed_cb), idle);
429
530
priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
443
544
priv->connectivity = empathy_connectivity_dup_singleton ();
444
545
priv->state_change_signal_id = g_signal_connect (priv->connectivity,
445
546
"state-change", G_CALLBACK (idle_state_change_cb), idle);
548
priv->connect_times = g_hash_table_new (g_direct_hash, g_direct_equal);
529
644
const gchar *status_message)
531
646
EmpathyIdlePriv *priv = GET_PRIV (idle);
532
const gchar *statuses[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
543
647
const gchar *status;
545
649
g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES);
547
status = statuses[status_type];
651
status = presence_type_to_status[status_type];
549
653
g_return_if_fail (status != NULL);
551
empathy_account_manager_request_global_presence (priv->manager,
655
/* We possibly should be sure that the account manager is prepared, but
656
* sometimes this isn't possible, like when exiting. In other words,
657
* we need a callback to empathy_idle_set_presence to be sure the
658
* presence is set on all accounts successfully.
659
* However, in practice, this is fine as we've already prepared the
660
* account manager here in _init. */
661
tp_account_manager_set_all_requested_presences (priv->manager,
552
662
status_type, status, status_message);
565
675
DEBUG ("Changing presence to %s (%d)", status, state);
677
g_free (priv->requested_status_message);
678
priv->requested_presence_type = state;
679
priv->requested_status_message = g_strdup (status);
567
681
/* Do not set translated default messages */
568
682
default_status = empathy_presence_get_default_message (state);
569
683
if (!tp_strdiff (status, default_status)) {
607
721
g_object_notify (G_OBJECT (idle), "auto-away");
724
TpConnectionPresenceType
725
empathy_idle_get_requested_presence (EmpathyIdle *idle,
727
gchar **status_message)
729
EmpathyIdlePriv *priv = GET_PRIV (idle);
731
if (status != NULL) {
732
*status = g_strdup (presence_type_to_status[priv->requested_presence_type]);
735
if (status_message != NULL) {
736
*status_message = g_strdup (priv->requested_status_message);
739
return priv->requested_presence_type;
742
/* This function returns %TRUE if EmpathyIdle considers the account
743
* @account as having just connected recently. Otherwise, it returns
744
* %FALSE. In doubt, %FALSE is returned. */
746
empathy_idle_account_is_just_connected (EmpathyIdle *idle,
749
EmpathyIdlePriv *priv = GET_PRIV (idle);
754
if (tp_account_get_connection_status (account, NULL)
755
!= TP_CONNECTION_STATUS_CONNECTED) {
759
ptr = g_hash_table_lookup (priv->connect_times, account);
765
t = GPOINTER_TO_INT (ptr);
767
g_get_current_time (&val);
769
return (val.tv_sec - t) < ACCOUNT_IS_JUST_CONNECTED_SECONDS;