6 * Copyright (C) 2011-12 SIPE Project <http://sipe.sourceforge.net/>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "sipe-common.h"
33 #include "sipe-backend.h"
35 #include "sipe-core.h"
36 #include "sipe-core-private.h"
38 #include "sipe-ocs2005.h"
39 #include "sipe-ocs2007.h"
40 #include "sipe-schedule.h"
41 #include "sipe-status.h"
42 #include "sipe-utils.h"
44 #define SIPE_IDLE_SET_DELAY 1 /* seconds */
48 const gchar
*status_id
;
50 } const sipe_activity_map
[SIPE_ACTIVITY_NUM_TYPES
] = {
52 * This has nothing to do with Availability numbers, like 3500 (online).
53 * Just a mapping of Communicator Activities to tokens/translations
55 /* @TODO: NULL means "default translation from Pidgin"?
56 * What about other backends? */
57 /* SIPE_ACTIVITY_UNSET */ { "unset", NULL
},
58 /* SIPE_ACTIVITY_AVAILABLE */ { "available", NULL
},
59 /* SIPE_ACTIVITY_ONLINE */ { "online", NULL
},
60 /* SIPE_ACTIVITY_INACTIVE */ { "idle", N_("Inactive") },
61 /* SIPE_ACTIVITY_BUSY */ { "busy", N_("Busy") },
62 /* SIPE_ACTIVITY_BUSYIDLE */ { "busyidle", N_("Busy-Idle") },
63 /* SIPE_ACTIVITY_DND */ { "do-not-disturb", NULL
},
64 /* SIPE_ACTIVITY_BRB */ { "be-right-back", N_("Be right back") },
65 /* SIPE_ACTIVITY_AWAY */ { "away", NULL
},
66 /* SIPE_ACTIVITY_LUNCH */ { "out-to-lunch", N_("Out to lunch") },
67 /* SIPE_ACTIVITY_INVISIBLE */ { "invisible", NULL
},
68 /* SIPE_ACTIVITY_OFFLINE */ { "offline", NULL
},
69 /* SIPE_ACTIVITY_ON_PHONE */ { "on-the-phone", N_("In a call") },
70 /* SIPE_ACTIVITY_IN_CONF */ { "in-a-conference", N_("In a conference") },
71 /* SIPE_ACTIVITY_IN_MEETING */ { "in-a-meeting", N_("In a meeting") },
72 /* SIPE_ACTIVITY_OOF */ { "out-of-office", N_("Out of office") },
73 /* SIPE_ACTIVITY_URGENT_ONLY */ { "urgent-interruptions-only", N_("Urgent interruptions only") },
76 static GHashTable
*token_map
;
78 void sipe_status_init(void)
82 token_map
= g_hash_table_new(g_str_hash
, g_str_equal
);
83 for (index
= SIPE_ACTIVITY_UNSET
;
84 index
< SIPE_ACTIVITY_NUM_TYPES
;
86 g_hash_table_insert(token_map
,
87 (gchar
*) sipe_activity_map
[index
].status_id
,
88 GUINT_TO_POINTER(index
));
92 void sipe_status_shutdown(void)
94 g_hash_table_destroy(token_map
);
97 /* type == SIPE_ACTIVITY_xxx (see sipe-core.h) */
98 const gchar
*sipe_status_activity_to_token(guint type
)
100 return(sipe_activity_map
[type
].status_id
);
103 guint
sipe_status_token_to_activity(const gchar
*token
)
105 if (!token
) return(SIPE_ACTIVITY_UNSET
);
106 return(GPOINTER_TO_UINT(g_hash_table_lookup(token_map
, token
)));
109 const gchar
*sipe_core_activity_description(guint type
)
111 return(gettext(sipe_activity_map
[type
].desc
));
114 void sipe_status_set_token(struct sipe_core_private
*sipe_private
,
115 const gchar
*status_id
)
117 g_free(sipe_private
->status
);
118 sipe_private
->status
= g_strdup(status_id
);
121 void sipe_status_set_activity(struct sipe_core_private
*sipe_private
,
124 sipe_status_set_token(sipe_private
,
125 sipe_status_activity_to_token(activity
));
128 void sipe_core_reset_status(struct sipe_core_public
*sipe_public
)
130 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
131 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007
))
132 sipe_ocs2007_reset_status(sipe_private
);
134 sipe_ocs2005_reset_status(sipe_private
);
137 void sipe_status_and_note(struct sipe_core_private
*sipe_private
,
138 const gchar
*status_id
)
143 status_id
= sipe_private
->status
;
145 SIPE_DEBUG_INFO("sipe_status_and_note: switch to '%s' for the account", status_id
);
147 activity
= sipe_status_token_to_activity(status_id
);
148 if (sipe_backend_status_changed(SIPE_CORE_PUBLIC
,
150 sipe_private
->note
)) {
151 /* status has changed */
152 sipe_private
->do_not_publish
[activity
] = time(NULL
);
153 SIPE_DEBUG_INFO("sipe_status_and_note: do_not_publish[%s]=%d [now]",
155 (int) sipe_private
->do_not_publish
[activity
]);
157 /* update backend status */
158 sipe_backend_status_and_note(SIPE_CORE_PUBLIC
,
164 void sipe_status_update(struct sipe_core_private
*sipe_private
,
165 SIPE_UNUSED_PARAMETER gpointer unused
)
167 guint activity
= sipe_backend_status(SIPE_CORE_PUBLIC
);
169 if (activity
== SIPE_ACTIVITY_UNSET
) return;
171 SIPE_DEBUG_INFO("sipe_status_update: status: %s (%s)",
172 sipe_status_activity_to_token(activity
),
173 sipe_status_changed_by_user(sipe_private
) ? "USER" : "MACHINE");
175 sipe_cal_presence_publish(sipe_private
, FALSE
);
178 void sipe_core_status_set(struct sipe_core_public
*sipe_public
,
182 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
185 time_t now
= time(NULL
);
186 const gchar
*status_id
= sipe_status_activity_to_token(activity
);
187 gboolean do_not_publish
= ((now
- sipe_private
->do_not_publish
[activity
]) <= 2);
189 /* when other point of presence clears note, but we are keeping
192 if (do_not_publish
&&
194 sipe_private
->calendar
&&
195 sipe_private
->calendar
->oof_note
) {
196 SIPE_DEBUG_INFO_NOFORMAT("sipe_core_status_set: enabling publication as OOF note keepers.");
197 do_not_publish
= FALSE
;
200 SIPE_DEBUG_INFO("sipe_core_status_set: was: sipe_private->do_not_publish[%s]=%d [?] now(time)=%d",
201 status_id
, (int)sipe_private
->do_not_publish
[activity
], (int)now
);
203 sipe_private
->do_not_publish
[activity
] = 0;
204 SIPE_DEBUG_INFO("sipe_core_status_set: set: sipe_private->do_not_publish[%s]=%d [0]",
205 status_id
, (int)sipe_private
->do_not_publish
[activity
]);
207 if (do_not_publish
) {
208 SIPE_DEBUG_INFO_NOFORMAT("sipe_core_status_set: publication was switched off, exiting.");
212 sipe_status_set_token(sipe_private
, status_id
);
214 /* hack to escape apostrof before comparison */
215 tmp
= note
? sipe_utils_str_replace(note
, "'", "'") : NULL
;
217 /* this will preserve OOF flag as well */
218 if (!sipe_strequal(tmp
, sipe_private
->note
)) {
219 SIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE
);
220 g_free(sipe_private
->note
);
221 sipe_private
->note
= g_strdup(note
);
222 sipe_private
->note_since
= time(NULL
);
226 /* schedule 2 sec to capture idle flag */
227 action_name
= g_strdup("<+set-status>");
228 sipe_schedule_seconds(sipe_private
,
238 * Whether user manually changed status or
239 * it was changed automatically due to user
240 * became inactive/active again
242 gboolean
sipe_status_changed_by_user(struct sipe_core_private
*sipe_private
)
245 time_t now
= time(NULL
);
247 SIPE_DEBUG_INFO("sipe_status_changed_by_user: sipe_private->idle_switch : %s",
248 asctime(localtime(&(sipe_private
->idle_switch
))));
249 SIPE_DEBUG_INFO("sipe_status_changed_by_user: now : %s",
250 asctime(localtime(&now
)));
252 res
= ((now
- SIPE_IDLE_SET_DELAY
* 2) >= sipe_private
->idle_switch
);
254 SIPE_DEBUG_INFO("sipe_status_changed_by_user: res = %s",
255 res
? "USER" : "MACHINE");
259 void sipe_core_status_idle(struct sipe_core_public
*sipe_public
)
261 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
263 sipe_private
->idle_switch
= time(NULL
);
264 SIPE_DEBUG_INFO("sipe_core_status_idle: sipe_private->idle_switch : %s",
265 asctime(localtime(&(sipe_private
->idle_switch
))));