1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
25 #include <glib/gi18n.h>
26 #include <dbus/dbus-glib.h>
28 #include <libtelepathy/tp-helpers.h>
30 #include "empathy-idle.h"
31 #include "gossip-utils.h"
32 #include "gossip-debug.h"
34 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
35 EMPATHY_TYPE_IDLE, EmpathyIdlePriv))
37 #define DEBUG_DOMAIN "Idle"
39 /* Number of seconds before entering extended autoaway. */
40 #define EXT_AWAY_TIME (30*60)
46 struct _EmpathyIdlePriv {
51 McPresence slack_state;
53 McPresence saved_state;
55 guint ext_away_timeout;
58 static void empathy_idle_class_init (EmpathyIdleClass *klass);
59 static void empathy_idle_init (EmpathyIdle *idle);
60 static void idle_finalize (GObject *object);
61 static void idle_get_property (GObject *object,
65 static void idle_set_property (GObject *object,
69 static void idle_presence_changed_cb (MissionControl *mc,
72 static void idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
75 static void idle_ext_away_start (EmpathyIdle *idle);
76 static void idle_ext_away_stop (EmpathyIdle *idle);
77 static gboolean idle_ext_away_cb (EmpathyIdle *idle);
86 G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT)
89 empathy_idle_class_init (EmpathyIdleClass *klass)
91 GObjectClass *object_class = G_OBJECT_CLASS (klass);
93 object_class->finalize = idle_finalize;
94 object_class->get_property = idle_get_property;
95 object_class->set_property = idle_set_property;
97 g_object_class_install_property (object_class,
99 g_param_spec_uint ("state",
104 MC_PRESENCE_AVAILABLE,
106 g_object_class_install_property (object_class,
108 g_param_spec_string ("status",
113 g_object_class_install_property (object_class,
115 g_param_spec_uint ("slack-state",
123 g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv));
127 empathy_idle_init (EmpathyIdle *idle)
129 EmpathyIdlePriv *priv;
131 priv = GET_PRIV (idle);
133 priv->is_idle = FALSE;
134 priv->mc = gossip_mission_control_new ();
135 priv->state = mission_control_get_presence_actual (priv->mc, NULL);
136 priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
137 priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
138 "org.gnome.ScreenSaver",
139 "/org/gnome/ScreenSaver",
140 "org.gnome.ScreenSaver");
141 if (!priv->gs_proxy) {
142 gossip_debug (DEBUG_DOMAIN, "Failed to get gs proxy");
146 dbus_g_proxy_add_signal (priv->gs_proxy, "SessionIdleChanged",
149 dbus_g_proxy_connect_signal (priv->gs_proxy, "SessionIdleChanged",
150 G_CALLBACK (idle_session_idle_changed_cb),
152 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
153 "PresenceStatusActual",
154 G_CALLBACK (idle_presence_changed_cb),
159 idle_finalize (GObject *object)
161 EmpathyIdlePriv *priv;
163 priv = GET_PRIV (object);
165 g_free (priv->status);
166 g_free (priv->saved_status);
167 g_object_unref (priv->mc);
169 if (priv->gs_proxy) {
170 g_object_unref (priv->gs_proxy);
173 idle_ext_away_stop (EMPATHY_IDLE (object));
177 idle_get_property (GObject *object,
182 EmpathyIdlePriv *priv;
185 priv = GET_PRIV (object);
186 idle = EMPATHY_IDLE (object);
190 g_value_set_uint (value, empathy_idle_get_state (idle));
193 g_value_set_string (value, empathy_idle_get_status (idle));
195 case PROP_SLACK_STATE:
196 g_value_set_uint (value, empathy_idle_get_slack_state (idle));
199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
205 idle_set_property (GObject *object,
210 EmpathyIdlePriv *priv;
213 priv = GET_PRIV (object);
214 idle = EMPATHY_IDLE (object);
218 empathy_idle_set_state (idle, g_value_get_uint (value));
221 empathy_idle_set_status (idle, g_value_get_string (value));
223 case PROP_SLACK_STATE:
224 empathy_idle_set_slack_state (idle, g_value_get_uint (value));
227 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
233 empathy_idle_new (void)
235 static EmpathyIdle *idle = NULL;
238 idle = g_object_new (EMPATHY_TYPE_IDLE, NULL);
239 g_object_add_weak_pointer (G_OBJECT (idle), (gpointer) &idle);
248 empathy_idle_get_state (EmpathyIdle *idle)
250 EmpathyIdlePriv *priv;
252 priv = GET_PRIV (idle);
258 empathy_idle_set_state (EmpathyIdle *idle,
261 EmpathyIdlePriv *priv;
263 priv = GET_PRIV (idle);
265 mission_control_set_presence (priv->mc,
272 empathy_idle_get_status (EmpathyIdle *idle)
274 EmpathyIdlePriv *priv;
276 priv = GET_PRIV (idle);
282 empathy_idle_set_status (EmpathyIdle *idle,
285 EmpathyIdlePriv *priv;
287 priv = GET_PRIV (idle);
289 mission_control_set_presence (priv->mc,
296 empathy_idle_get_slack_state (EmpathyIdle *idle)
298 EmpathyIdlePriv *priv;
300 priv = GET_PRIV (idle);
302 return priv->slack_state;
306 empathy_idle_set_slack_state (EmpathyIdle *idle,
309 EmpathyIdlePriv *priv;
311 priv = GET_PRIV (idle);
313 priv->slack_state = state;
315 g_object_notify (G_OBJECT (idle), "slack-state");
319 idle_presence_changed_cb (MissionControl *mc,
323 EmpathyIdlePriv *priv;
325 priv = GET_PRIV (idle);
327 g_free (priv->status);
329 priv->status = mission_control_get_presence_message_actual (priv->mc, NULL);
331 if (G_STR_EMPTY (priv->status)) {
332 g_free (priv->status);
333 priv->status = g_strdup (gossip_presence_state_get_default_status (state));
336 g_object_notify (G_OBJECT (idle), "state");
337 g_object_notify (G_OBJECT (idle), "status");
341 idle_session_idle_changed_cb (DBusGProxy *gs_proxy,
345 EmpathyIdlePriv *priv;
347 priv = GET_PRIV (idle);
349 gossip_debug (DEBUG_DOMAIN, "Session idle state changed, %s -> %s",
350 priv->is_idle ? "yes" : "no",
351 is_idle ? "yes" : "no");
353 if (is_idle && !priv->is_idle) {
354 McPresence new_state;
355 /* We are now idle, set state to away */
357 if (priv->state <= MC_PRESENCE_OFFLINE ||
358 priv->state == MC_PRESENCE_HIDDEN) {
359 /* We are not online so nothing to do here */
361 } else if (priv->state == MC_PRESENCE_AWAY ||
362 priv->state == MC_PRESENCE_EXTENDED_AWAY) {
363 /* User set away manually, when coming back we restore
364 * default presence. */
365 new_state = priv->state;
366 priv->saved_state = MC_PRESENCE_AVAILABLE;
367 priv->saved_status = NULL;
369 new_state = MC_PRESENCE_AWAY;
370 priv->saved_state = priv->state;
371 priv->saved_status = g_strdup (priv->status);
374 gossip_debug (DEBUG_DOMAIN, "Going to autoaway");
375 empathy_idle_set_state (idle, new_state);
377 idle_ext_away_start (idle);
378 } else if (!is_idle && priv->is_idle) {
379 /* We are no more idle, restore state */
380 idle_ext_away_stop (idle);
382 gossip_debug (DEBUG_DOMAIN, "Restoring state to %d %s",
386 mission_control_set_presence (priv->mc,
391 g_free (priv->saved_status);
392 priv->saved_status = NULL;
395 priv->is_idle = is_idle;
399 idle_ext_away_start (EmpathyIdle *idle)
401 EmpathyIdlePriv *priv;
403 priv = GET_PRIV (idle);
405 idle_ext_away_stop (idle);
406 priv->ext_away_timeout = g_timeout_add (EXT_AWAY_TIME * 1000,
407 (GSourceFunc) idle_ext_away_cb,
412 idle_ext_away_stop (EmpathyIdle *idle)
414 EmpathyIdlePriv *priv;
416 priv = GET_PRIV (idle);
418 if (priv->ext_away_timeout) {
419 g_source_remove (priv->ext_away_timeout);
420 priv->ext_away_timeout = 0;
425 idle_ext_away_cb (EmpathyIdle *idle)
427 EmpathyIdlePriv *priv;
429 priv = GET_PRIV (idle);
431 gossip_debug (DEBUG_DOMAIN, "Going to extended autoaway");
432 mission_control_set_presence (priv->mc,
433 MC_PRESENCE_EXTENDED_AWAY,
437 priv->ext_away_timeout = 0;