libpurple/presence.c

changeset 40575
b82c365e04e8
parent 40574
98384d15c7a0
child 40576
9616360d5943
equal deleted inserted replaced
40574:98384d15c7a0 40575:b82c365e04e8
1 /* purple
2 *
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 */
21
22 #include <glib/gi18n-lib.h>
23
24 #include "internal.h"
25 #include "debug.h"
26 #include "presence.h"
27 #include "purpleprivate.h"
28
29 typedef struct {
30 gboolean idle;
31 time_t idle_time;
32 time_t login_time;
33
34 GHashTable *status_table;
35
36 PurpleStatus *active_status;
37 } PurplePresencePrivate;
38
39 enum {
40 PROP_0,
41 PROP_IDLE,
42 PROP_IDLE_TIME,
43 PROP_LOGIN_TIME,
44 PROP_ACTIVE_STATUS,
45 N_PROPERTIES
46 };
47 static GParamSpec *properties[N_PROPERTIES];
48
49 G_DEFINE_TYPE_WITH_PRIVATE(PurplePresence, purple_presence, G_TYPE_OBJECT)
50
51 /******************************************************************************
52 * Helpers
53 *****************************************************************************/
54 static void
55 purple_presence_set_active_status(PurplePresence *presence,
56 PurpleStatus *status)
57 {
58 PurplePresencePrivate *priv = NULL;
59
60 priv = purple_presence_get_instance_private(presence);
61
62 if(g_set_object(&priv->active_status, status)) {
63 g_object_notify_by_pspec(G_OBJECT(presence),
64 properties[PROP_ACTIVE_STATUS]);
65 }
66 }
67
68 /******************************************************************************
69 * GObject Implementation
70 *****************************************************************************/
71 static void
72 purple_presence_set_property(GObject *obj, guint param_id, const GValue *value,
73 GParamSpec *pspec)
74 {
75 PurplePresence *presence = PURPLE_PRESENCE(obj);
76
77 switch (param_id) {
78 case PROP_IDLE:
79 purple_presence_set_idle(presence, g_value_get_boolean(value), 0);
80 break;
81 case PROP_IDLE_TIME:
82 #if SIZEOF_TIME_T == 4
83 purple_presence_set_idle(presence, TRUE, g_value_get_int(value));
84 #elif SIZEOF_TIME_T == 8
85 purple_presence_set_idle(presence, TRUE, g_value_get_int64(value));
86 #else
87 #error Unknown size of time_t
88 #endif
89 break;
90 case PROP_LOGIN_TIME:
91 #if SIZEOF_TIME_T == 4
92 purple_presence_set_login_time(presence, g_value_get_int(value));
93 #elif SIZEOF_TIME_T == 8
94 purple_presence_set_login_time(presence, g_value_get_int64(value));
95 #else
96 #error Unknown size of time_t
97 #endif
98 break;
99 case PROP_ACTIVE_STATUS:
100 purple_presence_set_active_status(presence,
101 g_value_get_object(value));
102 break;
103 default:
104 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
105 break;
106 }
107 }
108
109 /* Get method for GObject properties */
110 static void
111 purple_presence_get_property(GObject *obj, guint param_id, GValue *value,
112 GParamSpec *pspec)
113 {
114 PurplePresence *presence = PURPLE_PRESENCE(obj);
115
116 switch (param_id) {
117 case PROP_IDLE:
118 g_value_set_boolean(value, purple_presence_is_idle(presence));
119 break;
120 case PROP_IDLE_TIME:
121 #if SIZEOF_TIME_T == 4
122 g_value_set_int(value, purple_presence_get_idle_time(presence));
123 #elif SIZEOF_TIME_T == 8
124 g_value_set_int64(value, purple_presence_get_idle_time(presence));
125 #else
126 #error Unknown size of time_t
127 #endif
128 break;
129 case PROP_LOGIN_TIME:
130 #if SIZEOF_TIME_T == 4
131 g_value_set_int(value, purple_presence_get_login_time(presence));
132 #elif SIZEOF_TIME_T == 8
133 g_value_set_int64(value, purple_presence_get_login_time(presence));
134 #else
135 #error Unknown size of time_t
136 #endif
137 break;
138 case PROP_ACTIVE_STATUS:
139 g_value_set_object(value, purple_presence_get_active_status(presence));
140 break;
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
143 break;
144 }
145 }
146
147 static void
148 purple_presence_init(PurplePresence *presence) {
149 PurplePresencePrivate *priv = NULL;
150
151 priv = purple_presence_get_instance_private(presence);
152
153 priv->status_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
154 NULL);
155 }
156
157 static void
158 purple_presence_finalize(GObject *obj)
159 {
160 PurplePresencePrivate *priv = NULL;
161
162 priv = purple_presence_get_instance_private(PURPLE_PRESENCE(obj));
163
164 g_hash_table_destroy(priv->status_table);
165 g_clear_object(&priv->active_status);
166
167 G_OBJECT_CLASS(purple_presence_parent_class)->finalize(obj);
168 }
169
170 /* Class initializer function */
171 static void purple_presence_class_init(PurplePresenceClass *klass)
172 {
173 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
174
175 obj_class->get_property = purple_presence_get_property;
176 obj_class->set_property = purple_presence_set_property;
177 obj_class->finalize = purple_presence_finalize;
178
179 properties[PROP_IDLE] = g_param_spec_boolean("idle", "Idle",
180 "Whether the presence is in idle state.", FALSE,
181 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
182
183 properties[PROP_IDLE_TIME] =
184 #if SIZEOF_TIME_T == 4
185 g_param_spec_int
186 #elif SIZEOF_TIME_T == 8
187 g_param_spec_int64
188 #else
189 #error Unknown size of time_t
190 #endif
191 ("idle-time", "Idle time",
192 "The idle time of the presence",
193 #if SIZEOF_TIME_T == 4
194 G_MININT, G_MAXINT, 0,
195 #elif SIZEOF_TIME_T == 8
196 G_MININT64, G_MAXINT64, 0,
197 #else
198 #error Unknown size of time_t
199 #endif
200 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
201
202 properties[PROP_LOGIN_TIME] =
203 #if SIZEOF_TIME_T == 4
204 g_param_spec_int
205 #elif SIZEOF_TIME_T == 8
206 g_param_spec_int64
207 #else
208 #error Unknown size of time_t
209 #endif
210 ("login-time", "Login time",
211 "The login time of the presence.",
212 #if SIZEOF_TIME_T == 4
213 G_MININT, G_MAXINT, 0,
214 #elif SIZEOF_TIME_T == 8
215 G_MININT64, G_MAXINT64, 0,
216 #else
217 #error Unknown size of time_t
218 #endif
219 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
220
221 properties[PROP_ACTIVE_STATUS] = g_param_spec_object("active-status",
222 "Active status",
223 "The active status for the presence.", PURPLE_TYPE_STATUS,
224 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
225
226 g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
227 }
228
229 /******************************************************************************
230 * Public API
231 *****************************************************************************/
232 void
233 purple_presence_set_status_active(PurplePresence *presence,
234 const gchar *status_id, gboolean active)
235 {
236 PurpleStatus *status;
237
238 g_return_if_fail(PURPLE_IS_PRESENCE(presence));
239 g_return_if_fail(status_id != NULL);
240
241 status = purple_presence_get_status(presence, status_id);
242
243 g_return_if_fail(PURPLE_IS_STATUS(status));
244 /* TODO: Should we do the following? */
245 /* g_return_if_fail(active == status->active); */
246
247 if (purple_status_is_exclusive(status))
248 {
249 if (!active)
250 {
251 purple_debug_warning("presence",
252 "Attempted to set a non-independent status "
253 "(%s) inactive. Only independent statuses "
254 "can be specifically marked inactive.",
255 status_id);
256 return;
257 }
258 }
259
260 purple_status_set_active(status, active);
261 }
262
263 void
264 purple_presence_switch_status(PurplePresence *presence, const gchar *status_id)
265 {
266 purple_presence_set_status_active(presence, status_id, TRUE);
267 }
268
269 void
270 purple_presence_set_idle(PurplePresence *presence, gboolean idle,
271 time_t idle_time)
272 {
273 PurplePresencePrivate *priv = NULL;
274 PurplePresenceClass *klass = NULL;
275 gboolean old_idle;
276 GObject *obj;
277
278 g_return_if_fail(PURPLE_IS_PRESENCE(presence));
279
280 priv = purple_presence_get_instance_private(presence);
281 klass = PURPLE_PRESENCE_GET_CLASS(presence);
282
283 if (priv->idle == idle && priv->idle_time == idle_time)
284 return;
285
286 old_idle = priv->idle;
287 priv->idle = idle;
288 priv->idle_time = (idle ? idle_time : 0);
289
290 obj = G_OBJECT(presence);
291 g_object_freeze_notify(obj);
292 g_object_notify_by_pspec(obj, properties[PROP_IDLE]);
293 g_object_notify_by_pspec(obj, properties[PROP_IDLE_TIME]);
294 g_object_thaw_notify(obj);
295
296 if (klass->update_idle)
297 klass->update_idle(presence, old_idle);
298 }
299
300 void
301 purple_presence_set_login_time(PurplePresence *presence, time_t login_time) {
302 PurplePresencePrivate *priv = NULL;
303
304 g_return_if_fail(PURPLE_IS_PRESENCE(presence));
305
306 priv = purple_presence_get_instance_private(presence);
307
308 if (priv->login_time == login_time)
309 return;
310
311 priv->login_time = login_time;
312
313 g_object_notify_by_pspec(G_OBJECT(presence),
314 properties[PROP_LOGIN_TIME]);
315 }
316
317 GList *
318 purple_presence_get_statuses(PurplePresence *presence) {
319 PurplePresenceClass *klass = NULL;
320
321 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
322
323 klass = PURPLE_PRESENCE_GET_CLASS(presence);
324 if(klass && klass->get_statuses) {
325 return klass->get_statuses(presence);
326 }
327
328 return NULL;
329 }
330
331 PurpleStatus *
332 purple_presence_get_status(PurplePresence *presence, const gchar *status_id) {
333 PurplePresencePrivate *priv = NULL;
334 PurpleStatus *status;
335 GList *l = NULL;
336
337 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
338 g_return_val_if_fail(status_id != NULL, NULL);
339
340 priv = purple_presence_get_instance_private(presence);
341
342 /* What's the purpose of this hash table? */
343 status = (PurpleStatus *)g_hash_table_lookup(priv->status_table,
344 status_id);
345
346 if (status == NULL) {
347 for (l = purple_presence_get_statuses(presence);
348 l != NULL && status == NULL; l = l->next)
349 {
350 PurpleStatus *temp_status = l->data;
351
352 if (purple_strequal(status_id, purple_status_get_id(temp_status)))
353 status = temp_status;
354 }
355
356 if (status != NULL)
357 g_hash_table_insert(priv->status_table,
358 g_strdup(purple_status_get_id(status)), status);
359 }
360
361 return status;
362 }
363
364 PurpleStatus *
365 purple_presence_get_active_status(PurplePresence *presence) {
366 PurplePresencePrivate *priv = NULL;
367
368 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
369
370 priv = purple_presence_get_instance_private(presence);
371
372 return priv->active_status;
373 }
374
375 gboolean
376 purple_presence_is_available(PurplePresence *presence) {
377 PurpleStatus *status;
378
379 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
380
381 status = purple_presence_get_active_status(presence);
382
383 return ((status != NULL && purple_status_is_available(status)) &&
384 !purple_presence_is_idle(presence));
385 }
386
387 gboolean
388 purple_presence_is_online(PurplePresence *presence) {
389 PurpleStatus *status;
390
391 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
392
393 if ((status = purple_presence_get_active_status(presence)) == NULL)
394 return FALSE;
395
396 return purple_status_is_online(status);
397 }
398
399 gboolean
400 purple_presence_is_status_active(PurplePresence *presence,
401 const gchar *status_id)
402 {
403 PurpleStatus *status;
404
405 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
406 g_return_val_if_fail(status_id != NULL, FALSE);
407
408 status = purple_presence_get_status(presence, status_id);
409
410 return (status != NULL && purple_status_is_active(status));
411 }
412
413 gboolean
414 purple_presence_is_status_primitive_active(PurplePresence *presence,
415 PurpleStatusPrimitive primitive)
416 {
417 GList *l;
418
419 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
420 g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE);
421
422 for (l = purple_presence_get_statuses(presence);
423 l != NULL; l = l->next)
424 {
425 PurpleStatus *temp_status = l->data;
426 PurpleStatusType *type = purple_status_get_status_type(temp_status);
427
428 if (purple_status_type_get_primitive(type) == primitive &&
429 purple_status_is_active(temp_status))
430 return TRUE;
431 }
432 return FALSE;
433 }
434
435 gboolean
436 purple_presence_is_idle(PurplePresence *presence) {
437 PurplePresencePrivate *priv = NULL;
438
439 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
440
441 priv = purple_presence_get_instance_private(presence);
442
443 return purple_presence_is_online(presence) && priv->idle;
444 }
445
446 time_t
447 purple_presence_get_idle_time(PurplePresence *presence) {
448 PurplePresencePrivate *priv = NULL;
449
450 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), 0);
451
452 priv = purple_presence_get_instance_private(presence);
453 return priv->idle_time;
454 }
455
456 time_t
457 purple_presence_get_login_time(PurplePresence *presence) {
458 PurplePresencePrivate *priv = NULL;
459
460 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), 0);
461
462 priv = purple_presence_get_instance_private(presence);
463 return purple_presence_is_online(presence) ? priv->login_time : 0;
464 }

mercurial