~bcurtiswx/ubuntu/precise/empathy/3.4.2.1-0ubuntu1

« back to all changes in this revision

Viewing changes to libempathy/empathy-idle.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2009-11-16 23:40:52 UTC
  • mfrom: (1.1.39 upstream)
  • mto: (6.3.7 experimental)
  • mto: This revision was merged to the branch mainline in revision 80.
  • Revision ID: james.westby@ubuntu.com-20091116234052-7hhwrpeln4mwdyw7
Tags: upstream-2.29.2
ImportĀ upstreamĀ versionĀ 2.29.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <glib/gi18n-lib.h>
27
27
#include <dbus/dbus-glib.h>
28
28
 
 
29
#include <telepathy-glib/account-manager.h>
29
30
#include <telepathy-glib/dbus.h>
30
31
#include <telepathy-glib/util.h>
31
32
 
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)
42
42
 
 
43
/* Number of seconds to consider an account in the "just connected" state
 
44
 * for. */
 
45
#define ACCOUNT_IS_JUST_CONNECTED_SECONDS 10
 
46
 
43
47
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIdle)
44
48
typedef struct {
45
49
        DBusGProxy     *gs_proxy;
46
50
        EmpathyConnectivity *connectivity;
47
51
        gulong state_change_signal_id;
48
52
 
 
53
        gboolean ready;
 
54
 
49
55
        TpConnectionPresenceType      state;
50
56
        gchar          *status;
51
57
        TpConnectionPresenceType      flash_state;
58
64
        gboolean        is_idle;
59
65
        guint           ext_away_timeout;
60
66
 
61
 
        EmpathyAccountManager *manager;
 
67
        TpAccountManager *manager;
 
68
 
 
69
        /* pointer to a TpAccount --> glong of time of connection */
 
70
        GHashTable *connect_times;
 
71
 
 
72
        TpConnectionPresenceType requested_presence_type;
 
73
        gchar *requested_status_message;
 
74
 
62
75
} EmpathyIdlePriv;
63
76
 
64
77
typedef enum {
81
94
 
82
95
static EmpathyIdle * idle_singleton = NULL;
83
96
 
 
97
static const gchar *presence_type_to_status[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
 
98
        NULL,
 
99
        "offline",
 
100
        "available",
 
101
        "away",
 
102
        "xa",
 
103
        "hidden",
 
104
        "busy",
 
105
        NULL,
 
106
        NULL,
 
107
};
 
108
 
84
109
static void
85
 
idle_presence_changed_cb (EmpathyAccountManager *manager,
 
110
idle_presence_changed_cb (TpAccountManager *manager,
86
111
                          TpConnectionPresenceType state,
87
112
                          gchar          *status,
88
113
                          gchar          *status_message,
215
240
                        new_status = priv->status;
216
241
                }
217
242
 
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.
 
247
                 */
 
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);
220
251
 
221
 
                empathy_idle_set_presence (idle,
222
 
                                           priv->away_saved_state,
223
 
                                           new_status);
 
252
                        empathy_idle_set_presence (idle,
 
253
                                                   priv->away_saved_state,
 
254
                                                   new_status);
 
255
                } else {
 
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");
 
259
                }
224
260
 
225
261
                priv->away_saved_state = TP_CONNECTION_PRESENCE_TYPE_UNSET;
226
262
        }
268
304
        priv = GET_PRIV (object);
269
305
 
270
306
        g_free (priv->status);
 
307
        g_free (priv->requested_status_message);
271
308
 
272
309
        if (priv->gs_proxy) {
273
310
                g_object_unref (priv->gs_proxy);
279
316
 
280
317
        g_object_unref (priv->connectivity);
281
318
 
 
319
        g_hash_table_destroy (priv->connect_times);
 
320
        priv->connect_times = NULL;
 
321
 
282
322
        idle_ext_away_stop (EMPATHY_IDLE (object));
283
323
}
284
324
 
410
450
}
411
451
 
412
452
static void
 
453
account_status_changed_cb (TpAccount  *account,
 
454
                           guint       old_status,
 
455
                           guint       new_status,
 
456
                           guint       reason,
 
457
                           gchar      *dbus_error_name,
 
458
                           GHashTable *details,
 
459
                           gpointer    user_data)
 
460
{
 
461
        EmpathyIdle *idle = EMPATHY_IDLE (user_data);
 
462
        EmpathyIdlePriv *priv = GET_PRIV (idle);
 
463
        GTimeVal val;
 
464
 
 
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);
 
471
        }
 
472
}
 
473
 
 
474
static void
 
475
account_manager_ready_cb (GObject *source_object,
 
476
                          GAsyncResult *result,
 
477
                          gpointer user_data)
 
478
{
 
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;
 
484
        GList *accounts, *l;
 
485
        GError *error = NULL;
 
486
 
 
487
        priv->ready = TRUE;
 
488
 
 
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);
 
492
                return;
 
493
        }
 
494
 
 
495
        state = tp_account_manager_get_most_available_presence (priv->manager,
 
496
                &status, &status_message);
 
497
 
 
498
        idle_presence_changed_cb (account_manager, state, status,
 
499
                status_message, idle);
 
500
 
 
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),
 
505
                                             G_OBJECT (idle));
 
506
        }
 
507
        g_list_free (accounts);
 
508
 
 
509
        g_free (status);
 
510
        g_free (status_message);
 
511
}
 
512
 
 
513
static void
413
514
empathy_idle_init (EmpathyIdle *idle)
414
515
{
415
516
        EmpathyIdlePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle,
418
519
        idle->priv = priv;
419
520
        priv->is_idle = FALSE;
420
521
 
421
 
        priv->manager = empathy_account_manager_dup_singleton ();
422
 
        priv->state = empathy_account_manager_get_global_presence (priv->manager,
423
 
                NULL, &priv->status);
424
 
 
425
 
 
426
 
        g_signal_connect (priv->manager, "global-presence-changed",
 
522
        priv->manager = tp_account_manager_dup ();
 
523
 
 
524
        tp_account_manager_prepare_async (priv->manager, NULL,
 
525
            account_manager_ready_cb, idle);
 
526
 
 
527
        g_signal_connect (priv->manager, "most-available-presence-changed",
427
528
                G_CALLBACK (idle_presence_changed_cb), idle);
428
529
 
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);
 
547
 
 
548
        priv->connect_times = g_hash_table_new (g_direct_hash, g_direct_equal);
446
549
}
447
550
 
448
551
EmpathyIdle *
458
561
 
459
562
        priv = GET_PRIV (idle);
460
563
 
 
564
        if (G_UNLIKELY (!priv->ready))
 
565
                g_critical (G_STRLOC ": %s called before AccountManager ready",
 
566
                                G_STRFUNC);
 
567
 
461
568
        return priv->state;
462
569
}
463
570
 
479
586
 
480
587
        priv = GET_PRIV (idle);
481
588
 
 
589
        if (G_UNLIKELY (!priv->ready))
 
590
                g_critical (G_STRLOC ": %s called before AccountManager ready",
 
591
                                G_STRFUNC);
 
592
 
482
593
        if (!priv->status) {
483
594
                return empathy_presence_get_default_message (priv->state);
484
595
        }
504
615
 
505
616
        priv = GET_PRIV (idle);
506
617
 
 
618
        if (G_UNLIKELY (!priv->ready))
 
619
                g_critical (G_STRLOC ": %s called before AccountManager ready",
 
620
                                G_STRFUNC);
 
621
 
507
622
        return priv->flash_state;
508
623
}
509
624
 
529
644
                           const gchar *status_message)
530
645
{
531
646
        EmpathyIdlePriv *priv = GET_PRIV (idle);
532
 
        const gchar *statuses[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
533
 
                NULL,
534
 
                "offline",
535
 
                "available",
536
 
                "away",
537
 
                "xa",
538
 
                "hidden",
539
 
                "busy",
540
 
                NULL,
541
 
                NULL,
542
 
        };
543
647
        const gchar *status;
544
648
 
545
649
        g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES);
546
650
 
547
 
        status = statuses[status_type];
 
651
        status = presence_type_to_status[status_type];
548
652
 
549
653
        g_return_if_fail (status != NULL);
550
654
 
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);
553
663
}
554
664
 
564
674
 
565
675
        DEBUG ("Changing presence to %s (%d)", status, state);
566
676
 
 
677
        g_free (priv->requested_status_message);
 
678
        priv->requested_presence_type = state;
 
679
        priv->requested_status_message = g_strdup (status);
 
680
 
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");
608
722
}
609
723
 
 
724
TpConnectionPresenceType
 
725
empathy_idle_get_requested_presence (EmpathyIdle *idle,
 
726
    gchar **status,
 
727
    gchar **status_message)
 
728
{
 
729
        EmpathyIdlePriv *priv = GET_PRIV (idle);
 
730
 
 
731
        if (status != NULL) {
 
732
                *status = g_strdup (presence_type_to_status[priv->requested_presence_type]);
 
733
        }
 
734
 
 
735
        if (status_message != NULL) {
 
736
                *status_message = g_strdup (priv->requested_status_message);
 
737
        }
 
738
 
 
739
        return priv->requested_presence_type;
 
740
}
 
741
 
 
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. */
 
745
gboolean
 
746
empathy_idle_account_is_just_connected (EmpathyIdle *idle,
 
747
                                        TpAccount *account)
 
748
{
 
749
        EmpathyIdlePriv *priv = GET_PRIV (idle);
 
750
        GTimeVal val;
 
751
        gpointer ptr;
 
752
        glong t;
 
753
 
 
754
        if (tp_account_get_connection_status (account, NULL)
 
755
            != TP_CONNECTION_STATUS_CONNECTED) {
 
756
                return FALSE;
 
757
        }
 
758
 
 
759
        ptr = g_hash_table_lookup (priv->connect_times, account);
 
760
 
 
761
        if (ptr == NULL) {
 
762
                return FALSE;
 
763
        }
 
764
 
 
765
        t = GPOINTER_TO_INT (ptr);
 
766
 
 
767
        g_get_current_time (&val);
 
768
 
 
769
        return (val.tv_sec - t) < ACCOUNT_IS_JUST_CONNECTED_SECONDS;
 
770
}