adium: clean up paths in xcconfigs
[siplcs.git] / src / purple / purple-status.c
blob84c3095fd50f95937ef862fd8f0a56d3fcab994c
1 /**
2 * @file purple-status.c
4 * pidgin-sipe
6 * Copyright (C) 2011-2017 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <glib.h>
25 #include "account.h"
26 #include "savedstatuses.h"
28 #include "version.h"
29 #if !PURPLE_VERSION_CHECK(3,0,0)
30 #include "eventloop.h"
31 #define g_timeout_add_seconds(t, f, d) purple_timeout_add_seconds(t, f, d)
32 #define g_source_remove(t) purple_timeout_remove(t)
33 #endif
36 #include "sipe-backend.h"
37 #include "sipe-core.h"
39 #include "purple-private.h"
41 guint sipe_backend_status(struct sipe_core_public *sipe_public)
43 struct sipe_backend_private *purple_private = sipe_public->backend_private;
44 PurpleStatus *status = purple_account_get_active_status(purple_private->account);
45 if (!status) return(SIPE_ACTIVITY_UNSET);
46 return(sipe_purple_token_to_activity(purple_status_get_id(status)));
49 gboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public,
50 guint activity,
51 const gchar *message)
53 gboolean result = FALSE;
55 if ((activity == SIPE_ACTIVITY_AWAY) && purple_savedstatus_is_idleaway()) {
56 SIPE_DEBUG_INFO_NOFORMAT("sipe_backend_status_changed: user is already idle-away");
57 } else {
58 struct sipe_backend_private *purple_private = sipe_public->backend_private;
59 PurpleStatus *status = purple_account_get_active_status(purple_private->account);
60 const gchar *status_id = sipe_purple_activity_to_token(activity);
62 result = !(g_str_equal(status_id, purple_status_get_id(status)) &&
63 sipe_strequal(message,
64 purple_status_get_attr_string(status,
65 SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE)));
68 return(result);
71 /**
72 * This method motivates Purple's Host (e.g. Pidgin) to update its UI
73 * by using standard Purple's means of signals and saved statuses.
75 * Thus all UI elements get updated: Status Button with Note, docklet.
76 * This is ablolutely important as both our status and note can come
77 * inbound (roaming) or be updated programmatically (e.g. based on our
78 * calendar data).
80 void sipe_backend_status_and_note(struct sipe_core_public *sipe_public,
81 guint activity,
82 const gchar *message)
84 struct sipe_backend_private *purple_private = sipe_public->backend_private;
85 PurpleAccount *account = purple_private->account;
86 const gchar *status_id = sipe_purple_activity_to_token(activity);
87 PurpleSavedStatus *saved_status;
88 const PurpleStatusType *acct_status_type =
89 purple_status_type_find_with_id(purple_account_get_status_types(account),
90 status_id);
91 PurpleStatusPrimitive primitive = purple_status_type_get_primitive(acct_status_type);
93 /* code adapted from: pidgin/gtkstatusbox.c */
94 saved_status = purple_savedstatus_find_transient_by_type_and_message(primitive, message);
95 if (saved_status) {
96 purple_savedstatus_set_substatus(saved_status, account, acct_status_type, message);
97 } else {
98 /* This type+message is unique then create a new transient saved status */
99 GList *entry;
100 GList *active_accts = purple_accounts_get_all_active();
102 SIPE_DEBUG_INFO("sipe_backend_status_and_note: creating new saved status %s '%s'",
103 status_id, message ? message : "(null)");
105 saved_status = purple_savedstatus_new(NULL, primitive);
106 purple_savedstatus_set_message(saved_status, message);
108 for (entry = active_accts; entry != NULL; entry = entry->next)
109 purple_savedstatus_set_substatus(saved_status,
110 (PurpleAccount *) entry->data,
111 acct_status_type,
112 message);
113 g_list_free(active_accts);
116 /* Set the status for each account */
117 purple_private->status_changed_by_core = TRUE;
118 purple_savedstatus_activate(saved_status);
122 * Work around broken libpurple idle notification
124 * (1) user changes the status
125 * sipe_purple_set_status()
126 * -> user changed state
128 * (2) client detects that user is idle
129 * sipe_purple_set_status() [sometimes omitted?!?!?]
130 * sipe_purple_set_idle( != 0 )
131 * -> machine changed state
133 * (3) client detects that user is no longer idle
134 * sipe_purple_set_idle(0)
135 * sipe_purple_set_status()
136 * -> user changed state
138 * (4) core sends a status change
139 * sipe_backend_status_and_note()
140 * purple_savedstatus_activate()
141 * sipe_purple_set_status()
142 * -> status change must be ignored
144 * Cases (1) and (2) can only be differentiated by deferring the update.
146 static void sipe_purple_status_deferred_update(struct sipe_backend_private *purple_private,
147 gboolean changed_by_user)
149 gchar *note = purple_private->deferred_status_note;
151 purple_private->deferred_status_note = NULL;
152 purple_private->deferred_status_timeout = 0;
154 sipe_core_status_set(purple_private->public,
155 changed_by_user,
156 purple_private->deferred_status_activity,
157 note);
158 g_free(note);
161 static gboolean sipe_purple_status_timeout(gpointer data)
163 /* timeout expired -> no idle indication -> state changed by user */
164 sipe_purple_status_deferred_update(data, TRUE);
165 return(FALSE);
168 void sipe_purple_set_status(PurpleAccount *account,
169 PurpleStatus *status)
171 if (purple_account_get_connection(account) &&
172 purple_status_is_active(status)) {
173 struct sipe_core_public *sipe_public = PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC;
174 struct sipe_backend_private *purple_private = sipe_public->backend_private;
175 const gchar *status_id = purple_status_get_id(status);
176 guint activity = sipe_purple_token_to_activity(status_id);
177 const gchar *note = purple_status_get_attr_string(status,
178 SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE);
180 SIPE_DEBUG_INFO("sipe_purple_set_status[CB]: '%s'",
181 status_id);
183 if (purple_private->status_changed_by_core) {
184 SIPE_DEBUG_INFO_NOFORMAT("sipe_purple_set_status[CB]: triggered by core - ignoring");
186 } else if (purple_private->user_is_not_idle) {
187 sipe_core_status_set(sipe_public,
188 TRUE,
189 activity,
190 note);
192 } else {
193 if (purple_private->deferred_status_timeout)
194 g_source_remove(purple_private->deferred_status_timeout);
195 g_free(purple_private->deferred_status_note);
197 SIPE_DEBUG_INFO_NOFORMAT("sipe_purple_set_status[CB]: defer status update");
199 purple_private->deferred_status_note = g_strdup(note);
200 purple_private->deferred_status_activity = activity;
201 purple_private->deferred_status_timeout = g_timeout_add_seconds(1,
202 sipe_purple_status_timeout,
203 purple_private);
206 /* reset flags */
207 purple_private->status_changed_by_core = FALSE;
208 purple_private->user_is_not_idle = FALSE;
212 void sipe_purple_set_idle(PurpleConnection *gc,
213 int interval)
215 if (gc) {
216 struct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;
217 struct sipe_backend_private *purple_private = sipe_public->backend_private;
219 purple_private->user_is_not_idle = interval == 0;
221 SIPE_DEBUG_INFO("sipe_purple_set_idle[CB]: user is %sidle",
222 purple_private->user_is_not_idle ? "not " : "");
224 if (!purple_private->user_is_not_idle) {
225 /* timeout not expired -> state changed by machine */
226 if (purple_private->deferred_status_timeout)
227 g_source_remove(purple_private->deferred_status_timeout);
228 sipe_purple_status_deferred_update(purple_private, FALSE);
234 Local Variables:
235 mode: c
236 c-file-style: "bsd"
237 indent-tabs-mode: t
238 tab-width: 8
239 End: