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