Mercurial > pidgin
annotate src/status.c @ 11243:a511b77a368b
[gaim-migrate @ 13408]
sf patch #1246384, from shiyee
"This patch globally defines
spacings and boreders according to the Gnome Human
Interfaces Guidelines, and uses those defines where
appropriate. No visual changes are made, but the the
intention is that the defines should help promote
uniformness."
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Fri, 12 Aug 2005 23:53:28 +0000 |
parents | 744c0708d11f |
children | b4b1be482b4e |
rev | line source |
---|---|
9944 | 1 /** |
10067 | 2 * @file status.c Status API |
9944 | 3 * @ingroup core |
4 * | |
6065 | 5 * gaim |
6 * | |
8046 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
9944 | 10 * |
6065 | 11 * This program is free software; you can redistribute it and/or modify |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
9949 | 25 #include "internal.h" |
6065 | 26 |
9949 | 27 #include "blist.h" |
10400 | 28 #include "core.h" |
11187 | 29 #include "dbus-maybe.h" |
9949 | 30 #include "debug.h" |
10337 | 31 #include "notify.h" |
9949 | 32 #include "prefs.h" |
6065 | 33 #include "status.h" |
34 | |
9949 | 35 /** |
36 * A type of status. | |
37 */ | |
38 struct _GaimStatusType | |
39 { | |
40 GaimStatusPrimitive primitive; | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
41 |
9949 | 42 char *id; |
43 char *name; | |
44 char *primary_attr_id; | |
45 | |
46 gboolean saveable; | |
47 gboolean user_settable; | |
48 gboolean independent; | |
49 | |
50 GList *attrs; | |
51 }; | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
52 |
9949 | 53 /** |
54 * A status attribute. | |
55 */ | |
56 struct _GaimStatusAttr | |
57 { | |
58 char *id; | |
59 char *name; | |
60 GaimValue *value_type; | |
61 }; | |
6065 | 62 |
9949 | 63 /** |
64 * A list of statuses. | |
65 */ | |
66 struct _GaimPresence | |
67 { | |
68 GaimPresenceContext context; | |
69 | |
70 gboolean idle; | |
71 time_t idle_time; | |
10006 | 72 time_t login_time; |
9949 | 73 |
74 unsigned int warning_level; | |
6065 | 75 |
9949 | 76 GList *statuses; |
77 GHashTable *status_table; | |
78 | |
79 GaimStatus *active_status; | |
6065 | 80 |
9949 | 81 union |
82 { | |
83 GaimAccount *account; | |
84 | |
85 struct | |
86 { | |
87 GaimConversation *conv; | |
88 char *user; | |
89 | |
90 } chat; | |
6065 | 91 |
9949 | 92 struct |
93 { | |
94 GaimAccount *account; | |
95 char *name; | |
96 size_t ref_count; | |
97 GList *buddies; | |
98 | |
99 } buddy; | |
100 | |
101 } u; | |
102 }; | |
103 | |
104 /** | |
105 * An active status. | |
106 */ | |
107 struct _GaimStatus | |
6065 | 108 { |
9949 | 109 GaimStatusType *type; |
110 GaimPresence *presence; | |
111 | |
112 const char *title; | |
6065 | 113 |
9949 | 114 gboolean active; |
6065 | 115 |
9949 | 116 GHashTable *attr_values; |
117 }; | |
6065 | 118 |
119 typedef struct | |
120 { | |
9949 | 121 GaimAccount *account; |
122 char *name; | |
123 } GaimStatusBuddyKey; | |
124 | |
125 static int primitive_scores[] = | |
126 { | |
127 0, /* unset */ | |
128 -500, /* offline */ | |
129 0, /* online */ | |
130 100, /* available */ | |
131 -75, /* unavailable */ | |
132 -50, /* hidden */ | |
133 -100, /* away */ | |
10860 | 134 -200, /* extended away */ |
9949 | 135 -10, /* idle, special case. */ |
136 -5 /* idle time, special case. */ | |
137 }; | |
138 | |
139 static GHashTable *buddy_presences = NULL; | |
140 | |
10860 | 141 #define SCORE_IDLE 8 |
142 #define SCORE_IDLE_TIME 9 | |
9949 | 143 |
144 /************************************************************************** | |
10419 | 145 * GaimStatusPrimitive API |
146 **************************************************************************/ | |
147 static struct GaimStatusPrimitiveMap | |
148 { | |
149 GaimStatusPrimitive type; | |
150 const char *id; | |
151 const char *name; | |
152 | |
153 } const status_primitive_map[] = | |
154 { | |
155 { GAIM_STATUS_UNSET, "unset", N_("Unset") }, | |
156 { GAIM_STATUS_OFFLINE, "offline", N_("Offline") }, | |
157 { GAIM_STATUS_ONLINE, "online", N_("Online") }, | |
158 { GAIM_STATUS_AVAILABLE, "available", N_("Available") }, | |
159 { GAIM_STATUS_UNAVAILABLE, "unavailable", N_("Unavailable") }, | |
160 { GAIM_STATUS_HIDDEN, "hidden", N_("Hidden") }, | |
161 { GAIM_STATUS_AWAY, "away", N_("Away") }, | |
162 { GAIM_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended Away") } | |
163 }; | |
164 | |
165 const char * | |
166 gaim_primitive_get_id_from_type(GaimStatusPrimitive type) | |
167 { | |
168 int i; | |
169 | |
170 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
171 { | |
172 if (type == status_primitive_map[i].type) | |
173 return status_primitive_map[i].id; | |
174 } | |
175 | |
176 return status_primitive_map[0].id; | |
177 } | |
178 | |
179 const char * | |
180 gaim_primitive_get_name_from_type(GaimStatusPrimitive type) | |
181 { | |
182 int i; | |
183 | |
184 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
185 { | |
186 if (type == status_primitive_map[i].type) | |
187 return status_primitive_map[i].name; | |
188 } | |
189 | |
190 return status_primitive_map[0].name; | |
191 } | |
192 | |
193 GaimStatusPrimitive | |
194 gaim_primitive_get_type_from_id(const char *id) | |
195 { | |
196 int i; | |
197 | |
198 g_return_val_if_fail(id != NULL, GAIM_STATUS_UNSET); | |
199 | |
200 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
201 { | |
202 if (!strcmp(id, status_primitive_map[i].id)) | |
203 return status_primitive_map[i].type; | |
204 } | |
205 | |
206 return status_primitive_map[0].type; | |
207 } | |
208 | |
209 | |
210 /************************************************************************** | |
9949 | 211 * GaimStatusType API |
212 **************************************************************************/ | |
213 GaimStatusType * | |
214 gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id, | |
10009 | 215 const char *name, gboolean saveable, |
216 gboolean user_settable, gboolean independent) | |
9949 | 217 { |
218 GaimStatusType *status_type; | |
219 | |
220 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
221 g_return_val_if_fail(id != NULL, NULL); | |
222 g_return_val_if_fail(name != NULL, NULL); | |
223 | |
224 status_type = g_new0(GaimStatusType, 1); | |
11187 | 225 GAIM_DBUS_REGISTER_POINTER(status_type, GaimStatusType); |
9949 | 226 |
227 status_type->primitive = primitive; | |
228 status_type->id = g_strdup(id); | |
229 status_type->name = g_strdup(name); | |
230 status_type->saveable = saveable; | |
231 status_type->user_settable = user_settable; | |
232 status_type->independent = independent; | |
233 | |
234 return status_type; | |
235 } | |
236 | |
237 GaimStatusType * | |
238 gaim_status_type_new(GaimStatusPrimitive primitive, const char *id, | |
10009 | 239 const char *name, gboolean user_settable) |
9949 | 240 { |
241 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
242 g_return_val_if_fail(id != NULL, NULL); | |
243 g_return_val_if_fail(name != NULL, NULL); | |
244 | |
245 return gaim_status_type_new_full(primitive, id, name, FALSE, | |
246 user_settable, FALSE); | |
247 } | |
248 | |
249 GaimStatusType * | |
250 gaim_status_type_new_with_attrs(GaimStatusPrimitive primitive, | |
251 const char *id, const char *name, | |
252 gboolean saveable, gboolean user_settable, | |
253 gboolean independent, const char *attr_id, | |
254 const char *attr_name, GaimValue *attr_value, | |
255 ...) | |
256 { | |
257 GaimStatusType *status_type; | |
258 va_list args; | |
259 | |
260 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
261 g_return_val_if_fail(id != NULL, NULL); | |
262 g_return_val_if_fail(name != NULL, NULL); | |
10012 | 263 g_return_val_if_fail(attr_id != NULL, NULL); |
9949 | 264 g_return_val_if_fail(attr_name != NULL, NULL); |
265 g_return_val_if_fail(attr_value != NULL, NULL); | |
266 | |
267 status_type = gaim_status_type_new_full(primitive, id, name, saveable, | |
268 user_settable, independent); | |
269 | |
10010 | 270 /* Add the first attribute */ |
9949 | 271 gaim_status_type_add_attr(status_type, attr_id, attr_name, attr_value); |
272 | |
273 va_start(args, attr_value); | |
274 gaim_status_type_add_attrs_vargs(status_type, args); | |
275 va_end(args); | |
276 | |
277 return status_type; | |
278 } | |
279 | |
280 void | |
281 gaim_status_type_destroy(GaimStatusType *status_type) | |
282 { | |
283 GList *l; | |
284 | |
285 g_return_if_fail(status_type != NULL); | |
286 | |
287 g_free(status_type->id); | |
288 g_free(status_type->name); | |
289 | |
290 if (status_type->primary_attr_id != NULL) | |
291 g_free(status_type->primary_attr_id); | |
292 | |
293 if (status_type->attrs != NULL) | |
294 { | |
295 for (l = status_type->attrs; l != NULL; l = l->next) | |
296 gaim_status_attr_destroy((GaimStatusAttr *)l->data); | |
297 | |
298 g_list_free(status_type->attrs); | |
299 } | |
300 | |
11187 | 301 GAIM_DBUS_UNREGISTER_POINTER(status_type); |
9949 | 302 g_free(status_type); |
303 } | |
304 | |
305 void | |
306 gaim_status_type_set_primary_attr(GaimStatusType *status_type, const char *id) | |
307 { | |
308 g_return_if_fail(status_type != NULL); | |
309 | |
310 if (status_type->primary_attr_id != NULL) | |
311 g_free(status_type->primary_attr_id); | |
312 | |
313 status_type->primary_attr_id = (id == NULL ? NULL : g_strdup(id)); | |
314 } | |
315 | |
316 void | |
10197 | 317 gaim_status_type_add_attr(GaimStatusType *status_type, const char *id, |
9949 | 318 const char *name, GaimValue *value) |
319 { | |
320 GaimStatusAttr *attr; | |
321 | |
322 g_return_if_fail(status_type != NULL); | |
323 g_return_if_fail(id != NULL); | |
324 g_return_if_fail(name != NULL); | |
325 g_return_if_fail(value != NULL); | |
326 | |
327 attr = gaim_status_attr_new(id, name, value); | |
328 | |
329 status_type->attrs = g_list_append(status_type->attrs, attr); | |
330 } | |
331 | |
332 void | |
333 gaim_status_type_add_attrs_vargs(GaimStatusType *status_type, va_list args) | |
334 { | |
335 const char *id, *name; | |
336 GaimValue *value; | |
337 | |
338 g_return_if_fail(status_type != NULL); | |
339 | |
340 while ((id = va_arg(args, const char *)) != NULL) | |
341 { | |
342 name = va_arg(args, const char *); | |
343 g_return_if_fail(name != NULL); | |
344 | |
345 value = va_arg(args, GaimValue *); | |
346 g_return_if_fail(value != NULL); | |
6065 | 347 |
9949 | 348 gaim_status_type_add_attr(status_type, id, name, value); |
349 } | |
350 } | |
351 | |
10010 | 352 void |
353 gaim_status_type_add_attrs(GaimStatusType *status_type, const char *id, | |
354 const char *name, GaimValue *value, ...) | |
355 { | |
356 va_list args; | |
357 | |
358 g_return_if_fail(status_type != NULL); | |
359 g_return_if_fail(id != NULL); | |
360 g_return_if_fail(name != NULL); | |
361 g_return_if_fail(value != NULL); | |
362 | |
363 /* Add the first attribute */ | |
364 gaim_status_type_add_attr(status_type, id, name, value); | |
365 | |
366 va_start(args, value); | |
367 gaim_status_type_add_attrs_vargs(status_type, args); | |
368 va_end(args); | |
369 } | |
370 | |
9949 | 371 GaimStatusPrimitive |
372 gaim_status_type_get_primitive(const GaimStatusType *status_type) | |
373 { | |
374 g_return_val_if_fail(status_type != NULL, GAIM_STATUS_UNSET); | |
375 | |
376 return status_type->primitive; | |
377 } | |
378 | |
379 const char * | |
380 gaim_status_type_get_id(const GaimStatusType *status_type) | |
381 { | |
382 g_return_val_if_fail(status_type != NULL, NULL); | |
383 | |
384 return status_type->id; | |
385 } | |
386 | |
387 const char * | |
388 gaim_status_type_get_name(const GaimStatusType *status_type) | |
389 { | |
390 g_return_val_if_fail(status_type != NULL, NULL); | |
391 | |
392 return status_type->name; | |
393 } | |
394 | |
395 gboolean | |
396 gaim_status_type_is_saveable(const GaimStatusType *status_type) | |
397 { | |
398 g_return_val_if_fail(status_type != NULL, FALSE); | |
399 | |
400 return status_type->saveable; | |
401 } | |
402 | |
403 gboolean | |
404 gaim_status_type_is_user_settable(const GaimStatusType *status_type) | |
405 { | |
406 g_return_val_if_fail(status_type != NULL, FALSE); | |
407 | |
408 return status_type->user_settable; | |
409 } | |
410 | |
411 gboolean | |
412 gaim_status_type_is_independent(const GaimStatusType *status_type) | |
413 { | |
414 g_return_val_if_fail(status_type != NULL, FALSE); | |
415 | |
416 return status_type->independent; | |
417 } | |
418 | |
419 gboolean | |
10067 | 420 gaim_status_type_is_exclusive(const GaimStatusType *status_type) |
421 { | |
422 g_return_val_if_fail(status_type != NULL, FALSE); | |
423 | |
424 return !status_type->independent; | |
425 } | |
426 | |
427 gboolean | |
9949 | 428 gaim_status_type_is_available(const GaimStatusType *status_type) |
429 { | |
430 GaimStatusPrimitive primitive; | |
431 | |
432 g_return_val_if_fail(status_type != NULL, FALSE); | |
433 | |
434 primitive = gaim_status_type_get_primitive(status_type); | |
435 | |
10500 | 436 /* Why does "hidden" mean the person is available? */ |
9949 | 437 return (primitive == GAIM_STATUS_AVAILABLE || |
438 primitive == GAIM_STATUS_HIDDEN); | |
439 } | |
440 | |
441 const char * | |
442 gaim_status_type_get_primary_attr(const GaimStatusType *status_type) | |
443 { | |
444 g_return_val_if_fail(status_type != NULL, NULL); | |
445 | |
446 return status_type->primary_attr_id; | |
447 } | |
448 | |
449 GaimStatusAttr * | |
450 gaim_status_type_get_attr(const GaimStatusType *status_type, const char *id) | |
451 { | |
452 GList *l; | |
453 | |
454 g_return_val_if_fail(status_type != NULL, NULL); | |
455 g_return_val_if_fail(id != NULL, NULL); | |
456 | |
457 for (l = status_type->attrs; l != NULL; l = l->next) | |
458 { | |
459 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
460 | |
461 if (!strcmp(gaim_status_attr_get_id(attr), id)) | |
462 return attr; | |
463 } | |
464 | |
465 return NULL; | |
466 } | |
467 | |
468 const GList * | |
469 gaim_status_type_get_attrs(const GaimStatusType *status_type) | |
470 { | |
471 g_return_val_if_fail(status_type != NULL, NULL); | |
472 | |
473 return status_type->attrs; | |
474 } | |
475 | |
10348 | 476 const GaimStatusType * |
477 gaim_status_type_find_with_id(GList *status_types, const char *id) | |
478 { | |
479 GaimStatusType *status_type; | |
480 | |
481 g_return_val_if_fail(id != NULL, NULL); | |
482 | |
483 while (status_types != NULL) | |
484 { | |
485 status_type = status_types->data; | |
486 | |
487 if (!strcmp(id, status_type->id)) | |
488 return status_type; | |
10895 | 489 |
490 status_types = status_types->next; | |
10348 | 491 } |
492 | |
493 return NULL; | |
494 } | |
495 | |
9949 | 496 |
497 /************************************************************************** | |
498 * GaimStatusAttr API | |
499 **************************************************************************/ | |
500 GaimStatusAttr * | |
501 gaim_status_attr_new(const char *id, const char *name, GaimValue *value_type) | |
502 { | |
503 GaimStatusAttr *attr; | |
504 | |
505 g_return_val_if_fail(id != NULL, NULL); | |
506 g_return_val_if_fail(name != NULL, NULL); | |
507 g_return_val_if_fail(value_type != NULL, NULL); | |
508 | |
509 attr = g_new0(GaimStatusAttr, 1); | |
11187 | 510 GAIM_DBUS_REGISTER_POINTER(attr, GaimStatusAttr); |
9949 | 511 |
512 attr->id = g_strdup(id); | |
513 attr->name = g_strdup(name); | |
514 attr->value_type = value_type; | |
515 | |
516 return attr; | |
517 } | |
518 | |
519 void | |
520 gaim_status_attr_destroy(GaimStatusAttr *attr) | |
521 { | |
522 g_return_if_fail(attr != NULL); | |
523 | |
524 g_free(attr->id); | |
525 g_free(attr->name); | |
526 | |
527 gaim_value_destroy(attr->value_type); | |
528 | |
11187 | 529 GAIM_DBUS_UNREGISTER_POINTER(attr); |
9949 | 530 g_free(attr); |
531 } | |
532 | |
533 const char * | |
534 gaim_status_attr_get_id(const GaimStatusAttr *attr) | |
535 { | |
536 g_return_val_if_fail(attr != NULL, NULL); | |
537 | |
538 return attr->id; | |
539 } | |
540 | |
541 const char * | |
542 gaim_status_attr_get_name(const GaimStatusAttr *attr) | |
543 { | |
544 g_return_val_if_fail(attr != NULL, NULL); | |
545 | |
546 return attr->name; | |
547 } | |
548 | |
549 GaimValue * | |
550 gaim_status_attr_get_value_type(const GaimStatusAttr *attr) | |
551 { | |
552 g_return_val_if_fail(attr != NULL, NULL); | |
553 | |
554 return attr->value_type; | |
555 } | |
556 | |
557 | |
558 /************************************************************************** | |
559 * GaimStatus API | |
560 **************************************************************************/ | |
561 GaimStatus * | |
562 gaim_status_new(GaimStatusType *status_type, GaimPresence *presence) | |
563 { | |
564 GaimStatus *status; | |
565 const GList *l; | |
566 | |
567 g_return_val_if_fail(status_type != NULL, NULL); | |
568 g_return_val_if_fail(presence != NULL, NULL); | |
569 | |
570 status = g_new0(GaimStatus, 1); | |
11187 | 571 GAIM_DBUS_REGISTER_POINTER(status, GaimStatus); |
9949 | 572 |
573 status->type = status_type; | |
574 status->presence = presence; | |
575 | |
576 status->attr_values = | |
577 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
578 (GDestroyNotify)gaim_value_destroy); | |
579 | |
580 for (l = gaim_status_type_get_attrs(status_type); l != NULL; l = l->next) | |
581 { | |
582 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
583 GaimValue *value = gaim_status_attr_get_value_type(attr); | |
584 GaimValue *new_value = gaim_value_dup(value); | |
585 | |
586 g_hash_table_insert(status->attr_values, | |
10197 | 587 g_strdup(gaim_status_attr_get_id(attr)), |
588 new_value); | |
9949 | 589 } |
590 | |
591 return status; | |
592 } | |
593 | |
10754 | 594 /* |
595 * TODO: If the GaimStatus is in a GaimPresence, then | |
596 * remove it from the GaimPresence? | |
597 */ | |
9949 | 598 void |
599 gaim_status_destroy(GaimStatus *status) | |
600 { | |
601 g_return_if_fail(status != NULL); | |
602 | |
10754 | 603 /* TODO: Don't do this is if the status is exclusive */ |
9949 | 604 gaim_status_set_active(status, FALSE); |
605 | |
606 g_hash_table_destroy(status->attr_values); | |
607 | |
11187 | 608 GAIM_DBUS_UNREGISTER_POINTER(status); |
9949 | 609 g_free(status); |
610 } | |
6065 | 611 |
612 static void | |
9949 | 613 notify_buddy_status_update(GaimBuddy *buddy, GaimPresence *presence, |
614 GaimStatus *old_status, GaimStatus *new_status) | |
615 { | |
616 GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); | |
617 | |
618 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
619 gaim_prefs_get_bool("/core/logging/log_away_state")) | |
620 { | |
621 time_t current_time = time(NULL); | |
622 const char *buddy_alias = gaim_buddy_get_alias(buddy); | |
623 char *tmp = NULL; | |
624 | |
625 if (!gaim_status_is_available(old_status) && | |
626 gaim_status_is_available(new_status)) | |
627 { | |
628 tmp = g_strdup_printf(_("%s came back"), buddy_alias); | |
629 } | |
630 else if (gaim_status_is_available(old_status) && | |
631 !gaim_status_is_available(new_status)) | |
632 { | |
633 tmp = g_strdup_printf(_("%s went away"), buddy_alias); | |
634 } | |
635 | |
636 if (tmp != NULL) | |
637 { | |
638 GaimLog *log = gaim_account_get_log(buddy->account); | |
639 | |
640 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, buddy_alias, | |
641 current_time, tmp); | |
642 g_free(tmp); | |
643 } | |
644 } | |
645 | |
10012 | 646 if (ops != NULL && ops->update != NULL) |
647 ops->update(gaim_get_blist(), (GaimBlistNode*)buddy); | |
9949 | 648 } |
649 | |
650 static void | |
651 notify_status_update(GaimPresence *presence, GaimStatus *old_status, | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
652 GaimStatus *new_status) |
6065 | 653 { |
9949 | 654 GaimPresenceContext context = gaim_presence_get_context(presence); |
655 | |
656 if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT) | |
657 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
658 GaimAccount *account = gaim_presence_get_account(presence); |
9949 | 659 GaimAccountUiOps *ops = gaim_accounts_get_ui_ops(); |
660 | |
10400 | 661 if (gaim_account_get_enabled(account, gaim_core_get_ui())) |
10447 | 662 gaim_prpl_change_account_status(account, old_status, new_status); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
663 |
9949 | 664 if (ops != NULL && ops->status_changed != NULL) |
665 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
666 ops->status_changed(account, new_status); |
9949 | 667 } |
668 } | |
669 else if (context == GAIM_PRESENCE_CONTEXT_CONV) | |
670 { | |
671 #if 0 | |
672 GaimConversationUiOps *ops; | |
673 GaimConversation *conv; | |
674 | |
675 conv = gaim_status_get_conversation(new_status); | |
10348 | 676 /* |
677 * TODO: Probably need to do some of the following here? This is copied | |
678 * from some old status code that was removed. | |
679 * | |
680 * char *tmp = g_strdup_printf(_("%s logged in."), alias); | |
681 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
682 * g_free(tmp); | |
683 * | |
684 * char *tmp = g_strdup_printf(_("%s logged out."), alias); | |
685 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
686 * g_free(tmp); | |
687 * | |
688 * char *tmp = g_strdup_printf(_("%s signed off"), alias); | |
689 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
690 * g_free(tmp); | |
691 * | |
692 * serv_got_typing_stopped(gc, name); | |
693 * | |
694 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY); | |
695 */ | |
9949 | 696 #endif |
697 } | |
698 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY) | |
699 { | |
700 const GList *l; | |
701 | |
702 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
703 { | |
704 notify_buddy_status_update((GaimBuddy *)l->data, presence, | |
705 old_status, new_status); | |
706 } | |
10348 | 707 |
708 /* | |
709 * TODO: Maybe we should do this here? | |
710 * GaimLog *log = gaim_account_get_log(account); | |
711 * char *tmp = g_strdup_printf(_("%s signed on"), alias); | |
712 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
713 * g_free(tmp); | |
714 */ | |
9949 | 715 } |
716 } | |
717 | |
10204 | 718 static void |
719 status_has_changed(GaimStatus *status) | |
9949 | 720 { |
721 GaimPresence *presence; | |
722 GaimStatus *old_status; | |
723 | |
724 presence = gaim_status_get_presence(status); | |
725 | |
10204 | 726 /* |
727 * If this status is exclusive, then we must be setting it to "active." | |
728 * Since we are setting it to active, we want to set the currently | |
729 * active status to "inactive." | |
730 */ | |
731 if (gaim_status_is_exclusive(status)) | |
9949 | 732 { |
10754 | 733 old_status = gaim_presence_get_active_status(presence); |
10760 | 734 if (old_status != NULL && (old_status != status)) |
10754 | 735 old_status->active = FALSE; |
736 presence->active_status = status; | |
9949 | 737 } |
10754 | 738 else |
739 old_status = NULL; | |
9949 | 740 |
10204 | 741 notify_status_update(presence, old_status, status); |
742 } | |
743 | |
744 void | |
745 gaim_status_set_active(GaimStatus *status, gboolean active) | |
746 { | |
10754 | 747 gaim_status_set_active_with_attrs(status, active, NULL); |
10204 | 748 } |
749 | |
750 void | |
751 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args) | |
752 { | |
753 gboolean changed = FALSE; | |
754 const gchar *id; | |
755 | |
10714 | 756 g_return_if_fail(status != NULL); |
757 | |
10204 | 758 if (!active && gaim_status_is_exclusive(status)) |
759 { | |
760 gaim_debug_error("status", | |
761 "Cannot deactivate an exclusive status (%s).\n", | |
762 gaim_status_get_id(status)); | |
763 return; | |
764 } | |
765 | |
766 if (status->active != active) | |
10738 | 767 { |
10204 | 768 changed = TRUE; |
10738 | 769 } |
10204 | 770 |
9949 | 771 status->active = active; |
6065 | 772 |
10204 | 773 /* Set any attributes */ |
10754 | 774 if (args != NULL) |
10204 | 775 while ((id = va_arg(args, const char *)) != NULL) |
776 { | |
777 GaimValue *value; | |
778 value = gaim_status_get_attr_value(status, id); | |
10713 | 779 if (value == NULL) |
780 { | |
781 gaim_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " | |
10714 | 782 "not supported.\n", id, status->type->name); |
10713 | 783 /* Skip over the data and move on to the next attribute */ |
784 va_arg(args, void *); | |
785 continue; | |
786 } | |
787 | |
10204 | 788 if (value->type == GAIM_TYPE_STRING) |
789 { | |
790 const gchar *string_data = va_arg(args, const char *); | |
791 if (((string_data == NULL) && (value->data.string_data == NULL)) || | |
792 ((string_data != NULL) && (value->data.string_data != NULL) && | |
793 !strcmp(string_data, value->data.string_data))) | |
794 { | |
795 continue; | |
796 } | |
797 gaim_status_set_attr_string(status, id, string_data); | |
798 changed = TRUE; | |
799 } | |
800 else if (value->type == GAIM_TYPE_INT) | |
801 { | |
802 int int_data = va_arg(args, int); | |
803 if (int_data == value->data.int_data) | |
804 continue; | |
805 gaim_status_set_attr_int(status, id, int_data); | |
806 changed = TRUE; | |
807 } | |
808 else if (value->type == GAIM_TYPE_BOOLEAN) | |
809 { | |
810 gboolean boolean_data = va_arg(args, gboolean); | |
811 if (boolean_data == value->data.boolean_data) | |
812 continue; | |
813 gaim_status_set_attr_int(status, id, boolean_data); | |
814 changed = TRUE; | |
815 } | |
816 else | |
817 { | |
818 /* We don't know what the data is--skip over it */ | |
819 va_arg(args, void *); | |
820 } | |
821 } | |
822 | |
823 if (!changed) | |
824 return; | |
825 | |
826 status_has_changed(status); | |
9949 | 827 } |
828 | |
829 void | |
830 gaim_status_set_attr_boolean(GaimStatus *status, const char *id, | |
831 gboolean value) | |
832 { | |
833 GaimStatusType *status_type; | |
834 GaimValue *attr_value; | |
835 | |
836 g_return_if_fail(status != NULL); | |
837 g_return_if_fail(id != NULL); | |
838 | |
839 status_type = gaim_status_get_type(status); | |
840 | |
10197 | 841 /* Make sure this attribute exists and is the correct type. */ |
842 attr_value = gaim_status_get_attr_value(status, id); | |
843 g_return_if_fail(attr_value != NULL); | |
9949 | 844 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN); |
845 | |
846 gaim_value_set_boolean(attr_value, value); | |
847 } | |
848 | |
849 void | |
850 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value) | |
851 { | |
852 GaimStatusType *status_type; | |
853 GaimValue *attr_value; | |
854 | |
855 g_return_if_fail(status != NULL); | |
856 g_return_if_fail(id != NULL); | |
857 | |
858 status_type = gaim_status_get_type(status); | |
859 | |
10197 | 860 /* Make sure this attribute exists and is the correct type. */ |
861 attr_value = gaim_status_get_attr_value(status, id); | |
862 g_return_if_fail(attr_value != NULL); | |
9949 | 863 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT); |
864 | |
865 gaim_value_set_int(attr_value, value); | |
6065 | 866 } |
867 | |
9949 | 868 void |
869 gaim_status_set_attr_string(GaimStatus *status, const char *id, | |
870 const char *value) | |
871 { | |
872 GaimStatusType *status_type; | |
873 GaimValue *attr_value; | |
874 | |
875 g_return_if_fail(status != NULL); | |
876 g_return_if_fail(id != NULL); | |
877 | |
878 status_type = gaim_status_get_type(status); | |
879 | |
10197 | 880 /* Make sure this attribute exists and is the correct type. */ |
10196 | 881 attr_value = gaim_status_get_attr_value(status, id); |
10197 | 882 g_return_if_fail(attr_value != NULL); |
9949 | 883 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING); |
884 | |
885 gaim_value_set_string(attr_value, value); | |
886 } | |
887 | |
888 GaimStatusType * | |
889 gaim_status_get_type(const GaimStatus *status) | |
890 { | |
891 g_return_val_if_fail(status != NULL, NULL); | |
892 | |
893 return status->type; | |
894 } | |
895 | |
896 GaimPresence * | |
897 gaim_status_get_presence(const GaimStatus *status) | |
6065 | 898 { |
9949 | 899 g_return_val_if_fail(status != NULL, NULL); |
900 | |
901 return status->presence; | |
902 } | |
903 | |
904 const char * | |
905 gaim_status_get_id(const GaimStatus *status) | |
906 { | |
907 g_return_val_if_fail(status != NULL, NULL); | |
908 | |
909 return gaim_status_type_get_id(gaim_status_get_type(status)); | |
910 } | |
911 | |
912 const char * | |
913 gaim_status_get_name(const GaimStatus *status) | |
914 { | |
915 g_return_val_if_fail(status != NULL, NULL); | |
916 | |
917 return gaim_status_type_get_name(gaim_status_get_type(status)); | |
918 } | |
919 | |
920 gboolean | |
921 gaim_status_is_independent(const GaimStatus *status) | |
922 { | |
923 g_return_val_if_fail(status != NULL, FALSE); | |
924 | |
925 return gaim_status_type_is_independent(gaim_status_get_type(status)); | |
926 } | |
927 | |
928 gboolean | |
10067 | 929 gaim_status_is_exclusive(const GaimStatus *status) |
930 { | |
931 g_return_val_if_fail(status != NULL, FALSE); | |
932 | |
933 return gaim_status_type_is_exclusive(gaim_status_get_type(status)); | |
934 } | |
935 | |
936 gboolean | |
9949 | 937 gaim_status_is_available(const GaimStatus *status) |
938 { | |
939 g_return_val_if_fail(status != NULL, FALSE); | |
940 | |
941 return gaim_status_type_is_available(gaim_status_get_type(status)); | |
942 } | |
6216 | 943 |
9949 | 944 gboolean |
945 gaim_status_is_active(const GaimStatus *status) | |
946 { | |
947 g_return_val_if_fail(status != NULL, FALSE); | |
948 | |
949 return status->active; | |
950 } | |
951 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
952 gboolean |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
953 gaim_status_is_online(const GaimStatus *status) |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
954 { |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
955 GaimStatusPrimitive primitive; |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
956 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
957 g_return_val_if_fail( status != NULL, FALSE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
958 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
959 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
960 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
961 return (primitive != GAIM_STATUS_UNSET && |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
962 primitive != GAIM_STATUS_OFFLINE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
963 } |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
964 |
9949 | 965 GaimValue * |
966 gaim_status_get_attr_value(const GaimStatus *status, const char *id) | |
967 { | |
968 GaimStatusType *status_type; | |
969 GaimStatusAttr *attr; | |
970 | |
971 g_return_val_if_fail(status != NULL, NULL); | |
972 g_return_val_if_fail(id != NULL, NULL); | |
973 | |
974 status_type = gaim_status_get_type(status); | |
975 | |
976 /* Make sure this attribute exists. */ | |
977 attr = gaim_status_type_get_attr(status_type, id); | |
978 g_return_val_if_fail(attr != NULL, NULL); | |
979 | |
980 return (GaimValue *)g_hash_table_lookup(status->attr_values, id); | |
981 } | |
982 | |
983 gboolean | |
984 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id) | |
985 { | |
986 const GaimValue *value; | |
987 | |
988 g_return_val_if_fail(status != NULL, FALSE); | |
989 g_return_val_if_fail(id != NULL, FALSE); | |
990 | |
991 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
992 return FALSE; | |
993 | |
10197 | 994 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE); |
9949 | 995 |
996 return gaim_value_get_boolean(value); | |
997 } | |
998 | |
999 int | |
1000 gaim_status_get_attr_int(const GaimStatus *status, const char *id) | |
1001 { | |
1002 const GaimValue *value; | |
1003 | |
10507 | 1004 g_return_val_if_fail(status != NULL, 0); |
1005 g_return_val_if_fail(id != NULL, 0); | |
9949 | 1006 |
1007 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10507 | 1008 return 0; |
9949 | 1009 |
1010 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0); | |
1011 | |
1012 return gaim_value_get_int(value); | |
1013 } | |
1014 | |
1015 const char * | |
1016 gaim_status_get_attr_string(const GaimStatus *status, const char *id) | |
1017 { | |
1018 const GaimValue *value; | |
1019 | |
10507 | 1020 g_return_val_if_fail(status != NULL, NULL); |
1021 g_return_val_if_fail(id != NULL, NULL); | |
9949 | 1022 |
1023 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10504 | 1024 return NULL; |
9949 | 1025 |
1026 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL); | |
1027 | |
1028 return gaim_value_get_string(value); | |
1029 } | |
1030 | |
1031 gint | |
1032 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2) | |
1033 { | |
1034 GaimStatusType *type1, *type2; | |
1035 int score1 = 0, score2 = 0; | |
6065 | 1036 |
9949 | 1037 if ((status1 == NULL && status2 == NULL) || |
1038 (status1 == status2)) | |
1039 { | |
1040 return 0; | |
1041 } | |
1042 else if (status1 == NULL) | |
1043 return 1; | |
1044 else if (status2 == NULL) | |
1045 return -1; | |
1046 | |
1047 type1 = gaim_status_get_type(status1); | |
1048 type2 = gaim_status_get_type(status2); | |
1049 | |
1050 if (gaim_status_is_active(status1)) | |
1051 score1 = primitive_scores[gaim_status_type_get_primitive(type1)]; | |
1052 | |
1053 if (gaim_status_is_active(status2)) | |
1054 score2 = primitive_scores[gaim_status_type_get_primitive(type2)]; | |
1055 | |
1056 if (score1 > score2) | |
1057 return -1; | |
1058 else if (score1 < score2) | |
1059 return 1; | |
1060 | |
1061 return 0; | |
1062 } | |
1063 | |
1064 | |
1065 /************************************************************************** | |
1066 * GaimPresence API | |
1067 **************************************************************************/ | |
1068 GaimPresence * | |
1069 gaim_presence_new(GaimPresenceContext context) | |
1070 { | |
1071 GaimPresence *presence; | |
1072 | |
1073 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL); | |
1074 | |
1075 presence = g_new0(GaimPresence, 1); | |
11187 | 1076 GAIM_DBUS_REGISTER_POINTER(presence, GaimPresence); |
9949 | 1077 |
1078 presence->context = context; | |
1079 | |
1080 presence->status_table = | |
10009 | 1081 g_hash_table_new_full(g_str_hash, g_str_equal, |
1082 g_free, (GFreeFunc)gaim_status_destroy); | |
9949 | 1083 |
1084 return presence; | |
1085 } | |
1086 | |
1087 GaimPresence * | |
1088 gaim_presence_new_for_account(GaimAccount *account) | |
1089 { | |
10012 | 1090 GaimPresence *presence = NULL; |
9949 | 1091 g_return_val_if_fail(account != NULL, NULL); |
1092 | |
1093 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT); | |
1094 presence->u.account = account; | |
10006 | 1095 presence->statuses = gaim_prpl_get_statuses(account, presence); |
9949 | 1096 |
1097 return presence; | |
1098 } | |
1099 | |
1100 GaimPresence * | |
1101 gaim_presence_new_for_conv(GaimConversation *conv) | |
1102 { | |
1103 GaimPresence *presence; | |
1104 | |
1105 g_return_val_if_fail(conv != NULL, NULL); | |
1106 | |
1107 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV); | |
1108 presence->u.chat.conv = conv; | |
10006 | 1109 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */ |
9949 | 1110 |
1111 return presence; | |
1112 } | |
6216 | 1113 |
9949 | 1114 GaimPresence * |
1115 gaim_presence_new_for_buddy(GaimBuddy *buddy) | |
1116 { | |
1117 GaimPresence *presence; | |
1118 GaimStatusBuddyKey *key; | |
10006 | 1119 GaimAccount *account; |
9949 | 1120 |
1121 g_return_val_if_fail(buddy != NULL, NULL); | |
10012 | 1122 account = buddy->account; |
9949 | 1123 |
10006 | 1124 account = buddy->account; |
1125 | |
9949 | 1126 key = g_new0(GaimStatusBuddyKey, 1); |
1127 key->account = buddy->account; | |
1128 key->name = g_strdup(buddy->name); | |
10006 | 1129 |
1130 presence = g_hash_table_lookup(buddy_presences, key); | |
1131 if (presence == NULL) | |
9949 | 1132 { |
1133 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY); | |
1134 | |
1135 presence->u.buddy.name = g_strdup(buddy->name); | |
1136 presence->u.buddy.account = buddy->account; | |
10006 | 1137 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence); |
9949 | 1138 |
1139 g_hash_table_insert(buddy_presences, key, presence); | |
1140 } | |
1141 else | |
1142 { | |
1143 g_free(key->name); | |
1144 g_free(key); | |
1145 } | |
1146 | |
1147 presence->u.buddy.ref_count++; | |
1148 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies, | |
1149 buddy); | |
1150 | |
1151 return presence; | |
1152 } | |
1153 | |
1154 void | |
1155 gaim_presence_destroy(GaimPresence *presence) | |
1156 { | |
1157 g_return_if_fail(presence != NULL); | |
6216 | 1158 |
9949 | 1159 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) |
1160 { | |
1161 GaimStatusBuddyKey key; | |
1162 | |
10077 | 1163 if(presence->u.buddy.ref_count != 0) |
1164 return; | |
9949 | 1165 |
1166 key.account = presence->u.buddy.account; | |
1167 key.name = presence->u.buddy.name; | |
1168 | |
1169 g_hash_table_remove(buddy_presences, &key); | |
1170 | |
1171 if (presence->u.buddy.name != NULL) | |
1172 g_free(presence->u.buddy.name); | |
1173 } | |
1174 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV) | |
1175 { | |
1176 if (presence->u.chat.user != NULL) | |
1177 g_free(presence->u.chat.user); | |
1178 } | |
1179 | |
1180 if (presence->statuses != NULL) | |
1181 g_list_free(presence->statuses); | |
1182 | |
1183 g_hash_table_destroy(presence->status_table); | |
1184 | |
11187 | 1185 GAIM_DBUS_UNREGISTER_POINTER(presence); |
9949 | 1186 g_free(presence); |
1187 } | |
1188 | |
10580 | 1189 /* |
1190 * TODO: Maybe we should cal gaim_presence_destroy() after we | |
1191 * decrement the ref count? I don't see why we should | |
1192 * make other places do it manually when we can do it here. | |
1193 */ | |
9949 | 1194 void |
1195 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy) | |
1196 { | |
1197 g_return_if_fail(presence != NULL); | |
1198 g_return_if_fail(buddy != NULL); | |
1199 g_return_if_fail(gaim_presence_get_context(presence) == | |
1200 GAIM_PRESENCE_CONTEXT_BUDDY); | |
1201 | |
1202 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL) | |
1203 { | |
1204 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies, | |
1205 buddy); | |
1206 presence->u.buddy.ref_count--; | |
1207 } | |
6065 | 1208 } |
1209 | |
9949 | 1210 void |
1211 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status) | |
1212 { | |
1213 g_return_if_fail(presence != NULL); | |
1214 g_return_if_fail(status != NULL); | |
1215 | |
1216 presence->statuses = g_list_append(presence->statuses, status); | |
1217 | |
1218 g_hash_table_insert(presence->status_table, | |
1219 g_strdup(gaim_status_get_id(status)), status); | |
1220 } | |
1221 | |
1222 void | |
1223 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list) | |
1224 { | |
1225 const GList *l; | |
1226 | |
1227 g_return_if_fail(presence != NULL); | |
1228 g_return_if_fail(source_list != NULL); | |
1229 | |
1230 for (l = source_list; l != NULL; l = l->next) | |
1231 gaim_presence_add_status(presence, (GaimStatus *)l->data); | |
1232 } | |
1233 | |
1234 void | |
1235 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id, | |
1236 gboolean active) | |
1237 { | |
1238 GaimStatus *status; | |
1239 | |
1240 g_return_if_fail(presence != NULL); | |
1241 g_return_if_fail(status_id != NULL); | |
1242 | |
1243 status = gaim_presence_get_status(presence, status_id); | |
1244 | |
1245 g_return_if_fail(status != NULL); | |
10348 | 1246 /* TODO: Should we do the following? */ |
1247 /* g_return_if_fail(active == status->active); */ | |
9949 | 1248 |
10067 | 1249 if (gaim_status_is_exclusive(status)) |
9949 | 1250 { |
1251 if (!active) | |
1252 { | |
1253 gaim_debug_warning("status", | |
1254 "Attempted to set a non-independent status " | |
1255 "(%s) inactive. Only independent statuses " | |
1256 "can be specifically marked inactive.", | |
1257 status_id); | |
1258 return; | |
1259 } | |
1260 } | |
1261 | |
1262 gaim_status_set_active(status, active); | |
1263 } | |
1264 | |
1265 void | |
1266 gaim_presence_switch_status(GaimPresence *presence, const char *status_id) | |
1267 { | |
10754 | 1268 gaim_presence_set_status_active(presence, status_id, TRUE); |
9949 | 1269 } |
1270 | |
1271 static void | |
1272 update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence, | |
1273 time_t current_time, gboolean old_idle, gboolean idle) | |
1274 { | |
1275 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1276 | |
1277 if (!old_idle && idle) | |
1278 { | |
1279 gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle", buddy); | |
1280 | |
1281 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1282 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1283 { | |
1284 GaimLog *log = gaim_account_get_log(buddy->account); | |
1285 char *tmp = g_strdup_printf(_("%s became idle"), | |
1286 gaim_buddy_get_alias(buddy)); | |
1287 | |
1288 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1289 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1290 g_free(tmp); | |
1291 } | |
1292 } | |
1293 else if (old_idle && !idle) | |
1294 { | |
1295 gaim_signal_emit(gaim_blist_get_handle(), "buddy-unidle", buddy); | |
1296 | |
1297 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1298 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1299 { | |
1300 GaimLog *log = gaim_account_get_log(buddy->account); | |
1301 char *tmp = g_strdup_printf(_("%s became unidle"), | |
1302 gaim_buddy_get_alias(buddy)); | |
1303 | |
1304 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1305 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1306 g_free(tmp); | |
1307 } | |
1308 } | |
1309 | |
10378 | 1310 gaim_contact_invalidate_priority_buddy(gaim_buddy_get_contact(buddy)); |
9949 | 1311 |
1312 if (ops != NULL && ops->update != NULL) | |
1313 ops->update(gaim_get_blist(), (GaimBlistNode *)buddy); | |
1314 } | |
1315 | |
1316 void | |
1317 gaim_presence_set_idle(GaimPresence *presence, gboolean idle, time_t idle_time) | |
1318 { | |
1319 gboolean old_idle; | |
1320 | |
1321 g_return_if_fail(presence != NULL); | |
1322 | |
1323 if (presence->idle == idle && presence->idle_time == idle_time) | |
1324 return; | |
1325 | |
1326 old_idle = presence->idle; | |
1327 presence->idle = idle; | |
1328 presence->idle_time = (idle ? idle_time : 0); | |
1329 | |
1330 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1331 { | |
1332 const GList *l; | |
1333 time_t current_time = time(NULL); | |
1334 | |
1335 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
1336 { | |
1337 update_buddy_idle((GaimBuddy *)l->data, presence, current_time, | |
1338 old_idle, idle); | |
1339 } | |
1340 } | |
1341 } | |
1342 | |
1343 void | |
10006 | 1344 gaim_presence_set_login_time(GaimPresence *presence, time_t login_time) |
1345 { | |
1346 g_return_if_fail(presence != NULL); | |
1347 | |
1348 if (presence->login_time == login_time) | |
1349 return; | |
1350 | |
1351 presence->login_time = login_time; | |
1352 } | |
1353 | |
1354 void | |
9949 | 1355 gaim_presence_set_warning_level(GaimPresence *presence, unsigned int level) |
6065 | 1356 { |
9949 | 1357 g_return_if_fail(presence != NULL); |
1358 g_return_if_fail(level <= 100); | |
1359 | |
1360 if (presence->warning_level == level) | |
1361 return; | |
1362 | |
1363 presence->warning_level = level; | |
1364 | |
1365 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1366 { | |
1367 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1368 | |
1369 if (ops != NULL && ops->update != NULL) | |
1370 { | |
1371 const GList *l; | |
1372 | |
1373 for (l = gaim_presence_get_buddies(presence); | |
1374 l != NULL; | |
1375 l = l->next) | |
1376 { | |
1377 ops->update(gaim_get_blist(), (GaimBlistNode *)l->data); | |
1378 } | |
1379 } | |
1380 } | |
1381 } | |
1382 | |
1383 GaimPresenceContext | |
1384 gaim_presence_get_context(const GaimPresence *presence) | |
1385 { | |
1386 g_return_val_if_fail(presence != NULL, GAIM_PRESENCE_CONTEXT_UNSET); | |
1387 | |
1388 return presence->context; | |
1389 } | |
1390 | |
1391 GaimAccount * | |
1392 gaim_presence_get_account(const GaimPresence *presence) | |
1393 { | |
1394 GaimPresenceContext context; | |
1395 | |
1396 g_return_val_if_fail(presence != NULL, NULL); | |
1397 | |
1398 context = gaim_presence_get_context(presence); | |
1399 | |
1400 g_return_val_if_fail(context == GAIM_PRESENCE_CONTEXT_ACCOUNT || | |
1401 context == GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1402 | |
1403 return presence->u.account; | |
1404 } | |
1405 | |
1406 GaimConversation * | |
1407 gaim_presence_get_conversation(const GaimPresence *presence) | |
1408 { | |
1409 g_return_val_if_fail(presence != NULL, NULL); | |
1410 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1411 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1412 | |
1413 return presence->u.chat.conv; | |
1414 } | |
1415 | |
1416 const char * | |
1417 gaim_presence_get_chat_user(const GaimPresence *presence) | |
1418 { | |
1419 g_return_val_if_fail(presence != NULL, NULL); | |
1420 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1421 GAIM_PRESENCE_CONTEXT_CONV, NULL); | |
1422 | |
1423 return presence->u.chat.user; | |
1424 } | |
1425 | |
1426 const GList * | |
1427 gaim_presence_get_buddies(const GaimPresence *presence) | |
1428 { | |
1429 g_return_val_if_fail(presence != NULL, NULL); | |
1430 g_return_val_if_fail(gaim_presence_get_context(presence) == | |
1431 GAIM_PRESENCE_CONTEXT_BUDDY, NULL); | |
1432 | |
1433 return presence->u.buddy.buddies; | |
1434 } | |
1435 | |
1436 const GList * | |
1437 gaim_presence_get_statuses(const GaimPresence *presence) | |
1438 { | |
1439 g_return_val_if_fail(presence != NULL, NULL); | |
1440 | |
1441 return presence->statuses; | |
1442 } | |
1443 | |
1444 GaimStatus * | |
1445 gaim_presence_get_status(const GaimPresence *presence, const char *status_id) | |
1446 { | |
1447 GaimStatus *status; | |
10006 | 1448 const GList *l = NULL; |
9949 | 1449 |
1450 g_return_val_if_fail(presence != NULL, NULL); | |
1451 g_return_val_if_fail(status_id != NULL, NULL); | |
1452 | |
10006 | 1453 /* What's the purpose of this hash table? */ |
10012 | 1454 status = (GaimStatus *)g_hash_table_lookup(presence->status_table, |
10006 | 1455 status_id); |
10012 | 1456 |
10006 | 1457 if (status == NULL) { |
10012 | 1458 for (l = gaim_presence_get_statuses(presence); |
10006 | 1459 l != NULL && status == NULL; l = l->next) |
1460 { | |
1461 GaimStatus *temp_status = l->data; | |
10012 | 1462 |
10006 | 1463 if (!strcmp(status_id, gaim_status_get_id(temp_status))) |
1464 status = temp_status; | |
1465 } | |
1466 | |
1467 if (status != NULL) | |
1468 g_hash_table_insert(presence->status_table, | |
1469 g_strdup(gaim_status_get_id(status)), status); | |
10012 | 1470 } |
9949 | 1471 |
1472 return status; | |
1473 } | |
1474 | |
1475 GaimStatus * | |
1476 gaim_presence_get_active_status(const GaimPresence *presence) | |
1477 { | |
1478 g_return_val_if_fail(presence != NULL, NULL); | |
1479 | |
1480 return presence->active_status; | |
1481 } | |
1482 | |
1483 gboolean | |
1484 gaim_presence_is_available(const GaimPresence *presence) | |
1485 { | |
1486 GaimStatus *status; | |
1487 | |
1488 g_return_val_if_fail(presence != NULL, FALSE); | |
1489 | |
1490 status = gaim_presence_get_active_status(presence); | |
1491 | |
1492 return ((status != NULL && gaim_status_is_available(status)) && | |
1493 !gaim_presence_is_idle(presence)); | |
1494 } | |
1495 | |
1496 gboolean | |
1497 gaim_presence_is_online(const GaimPresence *presence) | |
1498 { | |
1499 GaimStatus *status; | |
1500 | |
1501 g_return_val_if_fail(presence != NULL, FALSE); | |
1502 | |
1503 if ((status = gaim_presence_get_active_status(presence)) == NULL) | |
1504 return FALSE; | |
1505 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
1506 return gaim_status_is_online(status); |
9949 | 1507 } |
1508 | |
1509 gboolean | |
1510 gaim_presence_is_status_active(const GaimPresence *presence, | |
1511 const char *status_id) | |
1512 { | |
1513 GaimStatus *status; | |
1514 | |
1515 g_return_val_if_fail(presence != NULL, FALSE); | |
1516 g_return_val_if_fail(status_id != NULL, FALSE); | |
1517 | |
1518 status = gaim_presence_get_status(presence, status_id); | |
1519 | |
1520 return (status != NULL && gaim_status_is_active(status)); | |
1521 } | |
1522 | |
1523 gboolean | |
1524 gaim_presence_is_status_primitive_active(const GaimPresence *presence, | |
1525 GaimStatusPrimitive primitive) | |
1526 { | |
1527 GaimStatus *status; | |
1528 GaimStatusType *status_type; | |
1529 | |
1530 g_return_val_if_fail(presence != NULL, FALSE); | |
1531 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, FALSE); | |
1532 | |
1533 status = gaim_presence_get_active_status(presence); | |
1534 status_type = gaim_status_get_type(status); | |
1535 | |
1536 if (gaim_status_type_get_primitive(status_type) == primitive) | |
1537 return TRUE; | |
6065 | 1538 |
1539 return FALSE; | |
1540 } | |
1541 | |
9949 | 1542 gboolean |
1543 gaim_presence_is_idle(const GaimPresence *presence) | |
6065 | 1544 { |
9949 | 1545 g_return_val_if_fail(presence != NULL, FALSE); |
1546 | |
1547 return presence->idle; | |
6065 | 1548 } |
1549 | |
9949 | 1550 time_t |
1551 gaim_presence_get_idle_time(const GaimPresence *presence) | |
6065 | 1552 { |
9949 | 1553 g_return_val_if_fail(presence != NULL, 0); |
6065 | 1554 |
9949 | 1555 return presence->idle_time; |
1556 } | |
6065 | 1557 |
9949 | 1558 unsigned int |
1559 gaim_presence_get_warning_level(const GaimPresence *presence) | |
1560 { | |
1561 g_return_val_if_fail(presence != NULL, 0); | |
6216 | 1562 |
9949 | 1563 return presence->warning_level; |
6065 | 1564 } |
1565 | |
10567 | 1566 time_t |
1567 gaim_presence_get_login_time(const GaimPresence *presence) | |
1568 { | |
1569 g_return_val_if_fail(presence != NULL, 0); | |
1570 | |
1571 return presence->login_time; | |
1572 } | |
1573 | |
9949 | 1574 gint |
1575 gaim_presence_compare(const GaimPresence *presence1, | |
1576 const GaimPresence *presence2) | |
6065 | 1577 { |
9949 | 1578 gboolean idle1, idle2; |
10860 | 1579 time_t idle_time_1, idle_time_2; |
9949 | 1580 int score1 = 0, score2 = 0; |
1581 const GList *l; | |
6065 | 1582 |
9949 | 1583 if ((presence1 == NULL && presence2 == NULL) || (presence1 == presence2)) |
1584 return 0; | |
1585 else if (presence1 == NULL) | |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1586 return 1; |
9949 | 1587 else if (presence2 == NULL) |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1588 return -1; |
6065 | 1589 |
9949 | 1590 /* Compute the score of the first set of statuses. */ |
1591 for (l = gaim_presence_get_statuses(presence1); l != NULL; l = l->next) | |
1592 { | |
1593 GaimStatus *status = (GaimStatus *)l->data; | |
1594 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1595 |
9949 | 1596 if (gaim_status_is_active(status)) |
1597 score1 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1598 } |
1599 | |
9949 | 1600 /* Compute the score of the second set of statuses. */ |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1601 for (l = gaim_presence_get_statuses(presence2); l != NULL; l = l->next) |
9949 | 1602 { |
1603 GaimStatus *status = (GaimStatus *)l->data; | |
1604 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1605 |
9949 | 1606 if (gaim_status_is_active(status)) |
1607 score2 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1608 } |
1609 | |
9949 | 1610 idle1 = gaim_presence_is_idle(presence1); |
1611 idle2 = gaim_presence_is_idle(presence2); | |
6065 | 1612 |
9949 | 1613 if (idle1) |
1614 score1 += primitive_scores[SCORE_IDLE]; | |
6065 | 1615 |
9949 | 1616 if (idle2) |
1617 score2 += primitive_scores[SCORE_IDLE]; | |
6065 | 1618 |
10860 | 1619 idle_time_1 = time(NULL) - gaim_presence_get_idle_time(presence1); |
1620 idle_time_2 = time(NULL) - gaim_presence_get_idle_time(presence2); | |
6065 | 1621 |
9949 | 1622 if (idle_time_1 > idle_time_2) |
1623 score1 += primitive_scores[SCORE_IDLE_TIME]; | |
1624 else if (idle_time_1 < idle_time_2) | |
1625 score2 += primitive_scores[SCORE_IDLE_TIME]; | |
6065 | 1626 |
9949 | 1627 if (score1 < score2) |
1628 return 1; | |
1629 else if (score1 > score2) | |
1630 return -1; | |
1631 | |
1632 return 0; | |
1633 } | |
1634 | |
6065 | 1635 |
9949 | 1636 /************************************************************************** |
1637 * Status subsystem | |
1638 **************************************************************************/ | |
1639 static void | |
1640 score_pref_changed_cb(const char *name, GaimPrefType type, gpointer value, | |
1641 gpointer data) | |
1642 { | |
1643 int index = GPOINTER_TO_INT(data); | |
6065 | 1644 |
9949 | 1645 primitive_scores[index] = GPOINTER_TO_INT(value); |
6065 | 1646 } |
1647 | |
10519 | 1648 static guint |
10006 | 1649 gaim_buddy_presences_hash(gconstpointer key) |
1650 { | |
10012 | 1651 const GaimStatusBuddyKey *me = key; |
1652 guint ret; | |
1653 char *str; | |
1654 | |
1655 str = g_strdup_printf("%p%s", me->account, me->name); | |
1656 ret = g_str_hash(str); | |
1657 g_free(str); | |
1658 | |
1659 return ret; | |
10006 | 1660 } |
1661 | |
10519 | 1662 static gboolean |
10006 | 1663 gaim_buddy_presences_equal(gconstpointer a, gconstpointer b) |
1664 { | |
1665 GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a; | |
1666 GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b; | |
1667 | |
10012 | 1668 if(key_a->account == key_b->account && |
1669 !strcmp(key_a->name, key_b->name)) | |
10006 | 1670 return TRUE; |
1671 else | |
1672 return FALSE; | |
1673 } | |
1674 | |
10519 | 1675 static void |
1676 gaim_buddy_presences_key_free(gpointer a) | |
1677 { | |
1678 GaimStatusBuddyKey *key = (GaimStatusBuddyKey *)a; | |
1679 g_free(key->name); | |
1680 g_free(key); | |
1681 } | |
1682 | |
10087 | 1683 void * |
10418 | 1684 gaim_status_get_handle(void) { |
10087 | 1685 static int handle; |
1686 | |
1687 return &handle; | |
1688 } | |
1689 | |
9949 | 1690 void |
10418 | 1691 gaim_status_init(void) |
6065 | 1692 { |
10418 | 1693 void *handle = gaim_status_get_handle; |
10087 | 1694 |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10895
diff
changeset
|
1695 gaim_debug_register_category("status"); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10895
diff
changeset
|
1696 |
9949 | 1697 gaim_prefs_add_none("/core/status"); |
1698 gaim_prefs_add_none("/core/status/scores"); | |
6065 | 1699 |
9949 | 1700 gaim_prefs_add_int("/core/status/scores/offline", |
1701 primitive_scores[GAIM_STATUS_OFFLINE]); | |
1702 gaim_prefs_add_int("/core/status/scores/available", | |
1703 primitive_scores[GAIM_STATUS_AVAILABLE]); | |
1704 gaim_prefs_add_int("/core/status/scores/hidden", | |
1705 primitive_scores[GAIM_STATUS_HIDDEN]); | |
1706 gaim_prefs_add_int("/core/status/scores/away", | |
1707 primitive_scores[GAIM_STATUS_AWAY]); | |
1708 gaim_prefs_add_int("/core/status/scores/extended_away", | |
1709 primitive_scores[GAIM_STATUS_EXTENDED_AWAY]); | |
1710 gaim_prefs_add_int("/core/status/scores/idle", | |
1711 primitive_scores[SCORE_IDLE]); | |
6065 | 1712 |
10087 | 1713 gaim_prefs_connect_callback(handle, "/core/status/scores/offline", |
9949 | 1714 score_pref_changed_cb, |
1715 GINT_TO_POINTER(GAIM_STATUS_OFFLINE)); | |
10087 | 1716 gaim_prefs_connect_callback(handle, "/core/status/scores/available", |
9949 | 1717 score_pref_changed_cb, |
1718 GINT_TO_POINTER(GAIM_STATUS_AVAILABLE)); | |
10087 | 1719 gaim_prefs_connect_callback(handle, "/core/status/scores/hidden", |
9949 | 1720 score_pref_changed_cb, |
1721 GINT_TO_POINTER(GAIM_STATUS_HIDDEN)); | |
10087 | 1722 gaim_prefs_connect_callback(handle, "/core/status/scores/away", |
9949 | 1723 score_pref_changed_cb, |
1724 GINT_TO_POINTER(GAIM_STATUS_AWAY)); | |
10087 | 1725 gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away", |
9949 | 1726 score_pref_changed_cb, |
1727 GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY)); | |
10087 | 1728 gaim_prefs_connect_callback(handle, "/core/status/scores/idle", |
9949 | 1729 score_pref_changed_cb, |
1730 GINT_TO_POINTER(SCORE_IDLE)); | |
10006 | 1731 |
10519 | 1732 buddy_presences = g_hash_table_new_full(gaim_buddy_presences_hash, |
1733 gaim_buddy_presences_equal, | |
1734 gaim_buddy_presences_key_free, NULL); | |
9949 | 1735 } |
6065 | 1736 |
9949 | 1737 void |
10418 | 1738 gaim_status_uninit(void) |
9949 | 1739 { |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1740 if (buddy_presences != NULL) |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1741 { |
10077 | 1742 g_hash_table_destroy(buddy_presences); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1743 |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1744 buddy_presences = NULL; |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1745 } |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10895
diff
changeset
|
1746 |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10895
diff
changeset
|
1747 gaim_debug_unregister_category("status"); |
9949 | 1748 } |