Mercurial > pidgin.yaz
annotate src/status.c @ 11279:ed5302df41b0
[gaim-migrate @ 13474]
Patch by Sadrul Habib Chowdhury to fix tab dragging. Many thanks also to
Cae for helping to track down the exact behavior, and for helping to test
this patch so that Sadrul could provide a version that actually fixes the
bug. :-)
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Tue, 16 Aug 2005 18:54:40 +0000 |
parents | 90be432e8385 |
children | 519dc2186438 |
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; | |
11249 | 72 time_t login_time; |
9949 | 73 |
74 GList *statuses; | |
75 GHashTable *status_table; | |
76 | |
77 GaimStatus *active_status; | |
6065 | 78 |
9949 | 79 union |
80 { | |
81 GaimAccount *account; | |
82 | |
83 struct | |
84 { | |
85 GaimConversation *conv; | |
86 char *user; | |
87 | |
88 } chat; | |
6065 | 89 |
9949 | 90 struct |
91 { | |
92 GaimAccount *account; | |
93 char *name; | |
94 size_t ref_count; | |
95 GList *buddies; | |
96 | |
97 } buddy; | |
98 | |
99 } u; | |
100 }; | |
101 | |
102 /** | |
103 * An active status. | |
104 */ | |
105 struct _GaimStatus | |
6065 | 106 { |
9949 | 107 GaimStatusType *type; |
108 GaimPresence *presence; | |
109 | |
110 const char *title; | |
6065 | 111 |
9949 | 112 gboolean active; |
6065 | 113 |
9949 | 114 GHashTable *attr_values; |
115 }; | |
6065 | 116 |
117 typedef struct | |
118 { | |
9949 | 119 GaimAccount *account; |
120 char *name; | |
121 } GaimStatusBuddyKey; | |
122 | |
123 static int primitive_scores[] = | |
124 { | |
125 0, /* unset */ | |
126 -500, /* offline */ | |
127 0, /* online */ | |
128 100, /* available */ | |
129 -75, /* unavailable */ | |
130 -50, /* hidden */ | |
131 -100, /* away */ | |
10860 | 132 -200, /* extended away */ |
9949 | 133 -10, /* idle, special case. */ |
134 -5 /* idle time, special case. */ | |
135 }; | |
136 | |
137 static GHashTable *buddy_presences = NULL; | |
138 | |
10860 | 139 #define SCORE_IDLE 8 |
140 #define SCORE_IDLE_TIME 9 | |
9949 | 141 |
142 /************************************************************************** | |
10419 | 143 * GaimStatusPrimitive API |
144 **************************************************************************/ | |
145 static struct GaimStatusPrimitiveMap | |
146 { | |
147 GaimStatusPrimitive type; | |
148 const char *id; | |
149 const char *name; | |
150 | |
151 } const status_primitive_map[] = | |
152 { | |
153 { GAIM_STATUS_UNSET, "unset", N_("Unset") }, | |
154 { GAIM_STATUS_OFFLINE, "offline", N_("Offline") }, | |
155 { GAIM_STATUS_ONLINE, "online", N_("Online") }, | |
156 { GAIM_STATUS_AVAILABLE, "available", N_("Available") }, | |
157 { GAIM_STATUS_UNAVAILABLE, "unavailable", N_("Unavailable") }, | |
158 { GAIM_STATUS_HIDDEN, "hidden", N_("Hidden") }, | |
159 { GAIM_STATUS_AWAY, "away", N_("Away") }, | |
160 { GAIM_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended Away") } | |
161 }; | |
162 | |
163 const char * | |
164 gaim_primitive_get_id_from_type(GaimStatusPrimitive type) | |
165 { | |
166 int i; | |
167 | |
168 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
169 { | |
170 if (type == status_primitive_map[i].type) | |
171 return status_primitive_map[i].id; | |
172 } | |
173 | |
174 return status_primitive_map[0].id; | |
175 } | |
176 | |
177 const char * | |
178 gaim_primitive_get_name_from_type(GaimStatusPrimitive type) | |
179 { | |
180 int i; | |
181 | |
182 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
183 { | |
184 if (type == status_primitive_map[i].type) | |
185 return status_primitive_map[i].name; | |
186 } | |
187 | |
188 return status_primitive_map[0].name; | |
189 } | |
190 | |
191 GaimStatusPrimitive | |
192 gaim_primitive_get_type_from_id(const char *id) | |
193 { | |
194 int i; | |
195 | |
196 g_return_val_if_fail(id != NULL, GAIM_STATUS_UNSET); | |
197 | |
198 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) | |
199 { | |
200 if (!strcmp(id, status_primitive_map[i].id)) | |
201 return status_primitive_map[i].type; | |
202 } | |
203 | |
204 return status_primitive_map[0].type; | |
205 } | |
206 | |
207 | |
208 /************************************************************************** | |
9949 | 209 * GaimStatusType API |
210 **************************************************************************/ | |
211 GaimStatusType * | |
212 gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id, | |
10009 | 213 const char *name, gboolean saveable, |
214 gboolean user_settable, gboolean independent) | |
9949 | 215 { |
216 GaimStatusType *status_type; | |
217 | |
218 g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL); | |
219 g_return_val_if_fail(id != NULL, NULL); | |
220 g_return_val_if_fail(name != NULL, NULL); | |
221 | |
222 status_type = g_new0(GaimStatusType, 1); | |
11187 | 223 GAIM_DBUS_REGISTER_POINTER(status_type, GaimStatusType); |
9949 | 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 | |
11187 | 299 GAIM_DBUS_UNREGISTER_POINTER(status_type); |
9949 | 300 g_free(status_type); |
301 } | |
302 | |
303 void | |
304 gaim_status_type_set_primary_attr(GaimStatusType *status_type, const char *id) | |
305 { | |
306 g_return_if_fail(status_type != NULL); | |
307 | |
308 if (status_type->primary_attr_id != NULL) | |
309 g_free(status_type->primary_attr_id); | |
310 | |
311 status_type->primary_attr_id = (id == NULL ? NULL : g_strdup(id)); | |
312 } | |
313 | |
314 void | |
10197 | 315 gaim_status_type_add_attr(GaimStatusType *status_type, const char *id, |
9949 | 316 const char *name, GaimValue *value) |
317 { | |
318 GaimStatusAttr *attr; | |
319 | |
320 g_return_if_fail(status_type != NULL); | |
321 g_return_if_fail(id != NULL); | |
322 g_return_if_fail(name != NULL); | |
323 g_return_if_fail(value != NULL); | |
324 | |
325 attr = gaim_status_attr_new(id, name, value); | |
326 | |
327 status_type->attrs = g_list_append(status_type->attrs, attr); | |
328 } | |
329 | |
330 void | |
331 gaim_status_type_add_attrs_vargs(GaimStatusType *status_type, va_list args) | |
332 { | |
333 const char *id, *name; | |
334 GaimValue *value; | |
335 | |
336 g_return_if_fail(status_type != NULL); | |
337 | |
338 while ((id = va_arg(args, const char *)) != NULL) | |
339 { | |
340 name = va_arg(args, const char *); | |
341 g_return_if_fail(name != NULL); | |
342 | |
343 value = va_arg(args, GaimValue *); | |
344 g_return_if_fail(value != NULL); | |
6065 | 345 |
9949 | 346 gaim_status_type_add_attr(status_type, id, name, value); |
347 } | |
348 } | |
349 | |
10010 | 350 void |
351 gaim_status_type_add_attrs(GaimStatusType *status_type, const char *id, | |
352 const char *name, GaimValue *value, ...) | |
353 { | |
354 va_list args; | |
355 | |
356 g_return_if_fail(status_type != NULL); | |
357 g_return_if_fail(id != NULL); | |
358 g_return_if_fail(name != NULL); | |
359 g_return_if_fail(value != NULL); | |
360 | |
361 /* Add the first attribute */ | |
362 gaim_status_type_add_attr(status_type, id, name, value); | |
363 | |
364 va_start(args, value); | |
365 gaim_status_type_add_attrs_vargs(status_type, args); | |
366 va_end(args); | |
367 } | |
368 | |
9949 | 369 GaimStatusPrimitive |
370 gaim_status_type_get_primitive(const GaimStatusType *status_type) | |
371 { | |
372 g_return_val_if_fail(status_type != NULL, GAIM_STATUS_UNSET); | |
373 | |
374 return status_type->primitive; | |
375 } | |
376 | |
377 const char * | |
378 gaim_status_type_get_id(const GaimStatusType *status_type) | |
379 { | |
380 g_return_val_if_fail(status_type != NULL, NULL); | |
381 | |
382 return status_type->id; | |
383 } | |
384 | |
385 const char * | |
386 gaim_status_type_get_name(const GaimStatusType *status_type) | |
387 { | |
388 g_return_val_if_fail(status_type != NULL, NULL); | |
389 | |
390 return status_type->name; | |
391 } | |
392 | |
393 gboolean | |
394 gaim_status_type_is_saveable(const GaimStatusType *status_type) | |
395 { | |
396 g_return_val_if_fail(status_type != NULL, FALSE); | |
397 | |
398 return status_type->saveable; | |
399 } | |
400 | |
401 gboolean | |
402 gaim_status_type_is_user_settable(const GaimStatusType *status_type) | |
403 { | |
404 g_return_val_if_fail(status_type != NULL, FALSE); | |
405 | |
406 return status_type->user_settable; | |
407 } | |
408 | |
409 gboolean | |
410 gaim_status_type_is_independent(const GaimStatusType *status_type) | |
411 { | |
412 g_return_val_if_fail(status_type != NULL, FALSE); | |
413 | |
414 return status_type->independent; | |
415 } | |
416 | |
417 gboolean | |
10067 | 418 gaim_status_type_is_exclusive(const GaimStatusType *status_type) |
419 { | |
420 g_return_val_if_fail(status_type != NULL, FALSE); | |
421 | |
422 return !status_type->independent; | |
423 } | |
424 | |
425 gboolean | |
9949 | 426 gaim_status_type_is_available(const GaimStatusType *status_type) |
427 { | |
428 GaimStatusPrimitive primitive; | |
429 | |
430 g_return_val_if_fail(status_type != NULL, FALSE); | |
431 | |
432 primitive = gaim_status_type_get_primitive(status_type); | |
433 | |
10500 | 434 /* Why does "hidden" mean the person is available? */ |
9949 | 435 return (primitive == GAIM_STATUS_AVAILABLE || |
436 primitive == GAIM_STATUS_HIDDEN); | |
437 } | |
438 | |
439 const char * | |
440 gaim_status_type_get_primary_attr(const GaimStatusType *status_type) | |
441 { | |
442 g_return_val_if_fail(status_type != NULL, NULL); | |
443 | |
444 return status_type->primary_attr_id; | |
445 } | |
446 | |
447 GaimStatusAttr * | |
448 gaim_status_type_get_attr(const GaimStatusType *status_type, const char *id) | |
449 { | |
450 GList *l; | |
451 | |
452 g_return_val_if_fail(status_type != NULL, NULL); | |
453 g_return_val_if_fail(id != NULL, NULL); | |
454 | |
455 for (l = status_type->attrs; l != NULL; l = l->next) | |
456 { | |
457 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
458 | |
459 if (!strcmp(gaim_status_attr_get_id(attr), id)) | |
460 return attr; | |
461 } | |
462 | |
463 return NULL; | |
464 } | |
465 | |
466 const GList * | |
467 gaim_status_type_get_attrs(const GaimStatusType *status_type) | |
468 { | |
469 g_return_val_if_fail(status_type != NULL, NULL); | |
470 | |
471 return status_type->attrs; | |
472 } | |
473 | |
10348 | 474 const GaimStatusType * |
475 gaim_status_type_find_with_id(GList *status_types, const char *id) | |
476 { | |
477 GaimStatusType *status_type; | |
478 | |
479 g_return_val_if_fail(id != NULL, NULL); | |
480 | |
481 while (status_types != NULL) | |
482 { | |
483 status_type = status_types->data; | |
484 | |
485 if (!strcmp(id, status_type->id)) | |
486 return status_type; | |
10895 | 487 |
488 status_types = status_types->next; | |
10348 | 489 } |
490 | |
491 return NULL; | |
492 } | |
493 | |
9949 | 494 |
495 /************************************************************************** | |
496 * GaimStatusAttr API | |
497 **************************************************************************/ | |
498 GaimStatusAttr * | |
499 gaim_status_attr_new(const char *id, const char *name, GaimValue *value_type) | |
500 { | |
501 GaimStatusAttr *attr; | |
502 | |
503 g_return_val_if_fail(id != NULL, NULL); | |
504 g_return_val_if_fail(name != NULL, NULL); | |
505 g_return_val_if_fail(value_type != NULL, NULL); | |
506 | |
507 attr = g_new0(GaimStatusAttr, 1); | |
11187 | 508 GAIM_DBUS_REGISTER_POINTER(attr, GaimStatusAttr); |
9949 | 509 |
510 attr->id = g_strdup(id); | |
511 attr->name = g_strdup(name); | |
512 attr->value_type = value_type; | |
513 | |
514 return attr; | |
515 } | |
516 | |
517 void | |
518 gaim_status_attr_destroy(GaimStatusAttr *attr) | |
519 { | |
520 g_return_if_fail(attr != NULL); | |
521 | |
522 g_free(attr->id); | |
523 g_free(attr->name); | |
524 | |
525 gaim_value_destroy(attr->value_type); | |
526 | |
11187 | 527 GAIM_DBUS_UNREGISTER_POINTER(attr); |
9949 | 528 g_free(attr); |
529 } | |
530 | |
531 const char * | |
532 gaim_status_attr_get_id(const GaimStatusAttr *attr) | |
533 { | |
534 g_return_val_if_fail(attr != NULL, NULL); | |
535 | |
536 return attr->id; | |
537 } | |
538 | |
539 const char * | |
540 gaim_status_attr_get_name(const GaimStatusAttr *attr) | |
541 { | |
542 g_return_val_if_fail(attr != NULL, NULL); | |
543 | |
544 return attr->name; | |
545 } | |
546 | |
547 GaimValue * | |
11249 | 548 gaim_status_attr_get_value(const GaimStatusAttr *attr) |
9949 | 549 { |
550 g_return_val_if_fail(attr != NULL, NULL); | |
551 | |
552 return attr->value_type; | |
553 } | |
554 | |
555 | |
556 /************************************************************************** | |
557 * GaimStatus API | |
558 **************************************************************************/ | |
559 GaimStatus * | |
560 gaim_status_new(GaimStatusType *status_type, GaimPresence *presence) | |
561 { | |
562 GaimStatus *status; | |
563 const GList *l; | |
564 | |
565 g_return_val_if_fail(status_type != NULL, NULL); | |
566 g_return_val_if_fail(presence != NULL, NULL); | |
567 | |
568 status = g_new0(GaimStatus, 1); | |
11187 | 569 GAIM_DBUS_REGISTER_POINTER(status, GaimStatus); |
9949 | 570 |
571 status->type = status_type; | |
572 status->presence = presence; | |
573 | |
574 status->attr_values = | |
575 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
576 (GDestroyNotify)gaim_value_destroy); | |
577 | |
578 for (l = gaim_status_type_get_attrs(status_type); l != NULL; l = l->next) | |
579 { | |
580 GaimStatusAttr *attr = (GaimStatusAttr *)l->data; | |
11249 | 581 GaimValue *value = gaim_status_attr_get_value(attr); |
9949 | 582 GaimValue *new_value = gaim_value_dup(value); |
583 | |
584 g_hash_table_insert(status->attr_values, | |
10197 | 585 g_strdup(gaim_status_attr_get_id(attr)), |
586 new_value); | |
9949 | 587 } |
588 | |
589 return status; | |
590 } | |
591 | |
10754 | 592 /* |
593 * TODO: If the GaimStatus is in a GaimPresence, then | |
594 * remove it from the GaimPresence? | |
595 */ | |
9949 | 596 void |
597 gaim_status_destroy(GaimStatus *status) | |
598 { | |
599 g_return_if_fail(status != NULL); | |
600 | |
10754 | 601 /* TODO: Don't do this is if the status is exclusive */ |
9949 | 602 gaim_status_set_active(status, FALSE); |
603 | |
604 g_hash_table_destroy(status->attr_values); | |
605 | |
11187 | 606 GAIM_DBUS_UNREGISTER_POINTER(status); |
9949 | 607 g_free(status); |
608 } | |
6065 | 609 |
610 static void | |
9949 | 611 notify_buddy_status_update(GaimBuddy *buddy, GaimPresence *presence, |
612 GaimStatus *old_status, GaimStatus *new_status) | |
613 { | |
614 GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); | |
615 | |
616 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
617 gaim_prefs_get_bool("/core/logging/log_away_state")) | |
618 { | |
619 time_t current_time = time(NULL); | |
620 const char *buddy_alias = gaim_buddy_get_alias(buddy); | |
621 char *tmp = NULL; | |
622 | |
623 if (!gaim_status_is_available(old_status) && | |
624 gaim_status_is_available(new_status)) | |
625 { | |
626 tmp = g_strdup_printf(_("%s came back"), buddy_alias); | |
627 } | |
628 else if (gaim_status_is_available(old_status) && | |
629 !gaim_status_is_available(new_status)) | |
630 { | |
631 tmp = g_strdup_printf(_("%s went away"), buddy_alias); | |
632 } | |
633 | |
634 if (tmp != NULL) | |
635 { | |
636 GaimLog *log = gaim_account_get_log(buddy->account); | |
637 | |
638 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, buddy_alias, | |
639 current_time, tmp); | |
640 g_free(tmp); | |
641 } | |
642 } | |
643 | |
10012 | 644 if (ops != NULL && ops->update != NULL) |
645 ops->update(gaim_get_blist(), (GaimBlistNode*)buddy); | |
9949 | 646 } |
647 | |
648 static void | |
649 notify_status_update(GaimPresence *presence, GaimStatus *old_status, | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
650 GaimStatus *new_status) |
6065 | 651 { |
9949 | 652 GaimPresenceContext context = gaim_presence_get_context(presence); |
653 | |
654 if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT) | |
655 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
656 GaimAccount *account = gaim_presence_get_account(presence); |
9949 | 657 GaimAccountUiOps *ops = gaim_accounts_get_ui_ops(); |
658 | |
10400 | 659 if (gaim_account_get_enabled(account, gaim_core_get_ui())) |
10447 | 660 gaim_prpl_change_account_status(account, old_status, new_status); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
661 |
9949 | 662 if (ops != NULL && ops->status_changed != NULL) |
663 { | |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
664 ops->status_changed(account, new_status); |
9949 | 665 } |
666 } | |
667 else if (context == GAIM_PRESENCE_CONTEXT_CONV) | |
668 { | |
669 #if 0 | |
670 GaimConversationUiOps *ops; | |
671 GaimConversation *conv; | |
672 | |
673 conv = gaim_status_get_conversation(new_status); | |
10348 | 674 /* |
675 * TODO: Probably need to do some of the following here? This is copied | |
676 * from some old status code that was removed. | |
677 * | |
678 * char *tmp = g_strdup_printf(_("%s logged in."), alias); | |
679 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
680 * g_free(tmp); | |
681 * | |
682 * char *tmp = g_strdup_printf(_("%s logged out."), alias); | |
683 * gaim_conversation_write(c, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
684 * g_free(tmp); | |
685 * | |
686 * char *tmp = g_strdup_printf(_("%s signed off"), alias); | |
687 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
688 * g_free(tmp); | |
689 * | |
690 * serv_got_typing_stopped(gc, name); | |
691 * | |
692 * gaim_conversation_update(c, GAIM_CONV_UPDATE_AWAY); | |
693 */ | |
9949 | 694 #endif |
695 } | |
696 else if (context == GAIM_PRESENCE_CONTEXT_BUDDY) | |
697 { | |
698 const GList *l; | |
699 | |
700 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
701 { | |
702 notify_buddy_status_update((GaimBuddy *)l->data, presence, | |
703 old_status, new_status); | |
704 } | |
10348 | 705 |
706 /* | |
707 * TODO: Maybe we should do this here? | |
708 * GaimLog *log = gaim_account_get_log(account); | |
709 * char *tmp = g_strdup_printf(_("%s signed on"), alias); | |
710 * gaim_log_write(log, GAIM_MESSAGE_SYSTEM, (alias ? alias : name), current_time, tmp); | |
711 * g_free(tmp); | |
712 */ | |
9949 | 713 } |
714 } | |
715 | |
10204 | 716 static void |
717 status_has_changed(GaimStatus *status) | |
9949 | 718 { |
719 GaimPresence *presence; | |
720 GaimStatus *old_status; | |
721 | |
722 presence = gaim_status_get_presence(status); | |
723 | |
10204 | 724 /* |
725 * If this status is exclusive, then we must be setting it to "active." | |
726 * Since we are setting it to active, we want to set the currently | |
727 * active status to "inactive." | |
728 */ | |
729 if (gaim_status_is_exclusive(status)) | |
9949 | 730 { |
10754 | 731 old_status = gaim_presence_get_active_status(presence); |
10760 | 732 if (old_status != NULL && (old_status != status)) |
10754 | 733 old_status->active = FALSE; |
734 presence->active_status = status; | |
9949 | 735 } |
10754 | 736 else |
737 old_status = NULL; | |
9949 | 738 |
10204 | 739 notify_status_update(presence, old_status, status); |
740 } | |
741 | |
742 void | |
743 gaim_status_set_active(GaimStatus *status, gboolean active) | |
744 { | |
10754 | 745 gaim_status_set_active_with_attrs(status, active, NULL); |
10204 | 746 } |
747 | |
11249 | 748 /* |
749 * This used to parse the va_list directly, but now it creates a GList | |
750 * and passes it to gaim_status_set_active_with_attrs_list(). That | |
751 * function was created because accounts.c needs to pass a GList of | |
752 * attributes to the status API. | |
753 */ | |
10204 | 754 void |
755 gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args) | |
756 { | |
11249 | 757 GList *attrs = NULL; |
758 const gchar *id; | |
759 gpointer data; | |
760 | |
761 if (args != NULL) | |
762 { | |
763 while ((id = va_arg(args, const char *)) != NULL) | |
764 { | |
765 attrs = g_list_append(attrs, (char *)id); | |
766 data = va_arg(args, void *); | |
767 attrs = g_list_append(attrs, data); | |
768 } | |
769 } | |
770 gaim_status_set_active_with_attrs_list(status, active, attrs); | |
771 g_list_free(attrs); | |
772 } | |
773 | |
774 void | |
775 gaim_status_set_active_with_attrs_list(GaimStatus *status, gboolean active, | |
776 const GList *attrs) | |
777 { | |
10204 | 778 gboolean changed = FALSE; |
779 const gchar *id; | |
780 | |
10714 | 781 g_return_if_fail(status != NULL); |
782 | |
10204 | 783 if (!active && gaim_status_is_exclusive(status)) |
784 { | |
785 gaim_debug_error("status", | |
786 "Cannot deactivate an exclusive status (%s).\n", | |
787 gaim_status_get_id(status)); | |
788 return; | |
789 } | |
790 | |
791 if (status->active != active) | |
10738 | 792 { |
10204 | 793 changed = TRUE; |
10738 | 794 } |
10204 | 795 |
9949 | 796 status->active = active; |
6065 | 797 |
10204 | 798 /* Set any attributes */ |
11249 | 799 while (attrs) |
10204 | 800 { |
801 GaimValue *value; | |
11249 | 802 |
803 id = attrs->data; | |
804 attrs = attrs->next; | |
10204 | 805 value = gaim_status_get_attr_value(status, id); |
10713 | 806 if (value == NULL) |
807 { | |
808 gaim_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " | |
10714 | 809 "not supported.\n", id, status->type->name); |
10713 | 810 /* Skip over the data and move on to the next attribute */ |
11249 | 811 attrs = attrs->next; |
10713 | 812 continue; |
813 } | |
814 | |
10204 | 815 if (value->type == GAIM_TYPE_STRING) |
816 { | |
11249 | 817 const gchar *string_data = attrs->data; |
818 attrs = attrs->next; | |
10204 | 819 if (((string_data == NULL) && (value->data.string_data == NULL)) || |
820 ((string_data != NULL) && (value->data.string_data != NULL) && | |
821 !strcmp(string_data, value->data.string_data))) | |
822 { | |
823 continue; | |
824 } | |
825 gaim_status_set_attr_string(status, id, string_data); | |
826 changed = TRUE; | |
827 } | |
828 else if (value->type == GAIM_TYPE_INT) | |
829 { | |
11249 | 830 int int_data = (int)attrs->data; |
831 attrs = attrs->next; | |
10204 | 832 if (int_data == value->data.int_data) |
833 continue; | |
834 gaim_status_set_attr_int(status, id, int_data); | |
835 changed = TRUE; | |
836 } | |
837 else if (value->type == GAIM_TYPE_BOOLEAN) | |
838 { | |
11249 | 839 gboolean boolean_data = (gboolean)attrs->data; |
840 attrs = attrs->next; | |
10204 | 841 if (boolean_data == value->data.boolean_data) |
842 continue; | |
843 gaim_status_set_attr_int(status, id, boolean_data); | |
844 changed = TRUE; | |
845 } | |
846 else | |
847 { | |
848 /* We don't know what the data is--skip over it */ | |
11249 | 849 attrs = attrs->next; |
10204 | 850 } |
851 } | |
852 | |
853 if (!changed) | |
854 return; | |
855 status_has_changed(status); | |
9949 | 856 } |
857 | |
858 void | |
859 gaim_status_set_attr_boolean(GaimStatus *status, const char *id, | |
860 gboolean value) | |
861 { | |
862 GaimStatusType *status_type; | |
863 GaimValue *attr_value; | |
864 | |
865 g_return_if_fail(status != NULL); | |
866 g_return_if_fail(id != NULL); | |
867 | |
868 status_type = gaim_status_get_type(status); | |
869 | |
10197 | 870 /* Make sure this attribute exists and is the correct type. */ |
871 attr_value = gaim_status_get_attr_value(status, id); | |
872 g_return_if_fail(attr_value != NULL); | |
9949 | 873 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN); |
874 | |
875 gaim_value_set_boolean(attr_value, value); | |
876 } | |
877 | |
878 void | |
879 gaim_status_set_attr_int(GaimStatus *status, const char *id, int value) | |
880 { | |
881 GaimStatusType *status_type; | |
882 GaimValue *attr_value; | |
883 | |
884 g_return_if_fail(status != NULL); | |
885 g_return_if_fail(id != NULL); | |
886 | |
887 status_type = gaim_status_get_type(status); | |
888 | |
10197 | 889 /* Make sure this attribute exists and is the correct type. */ |
890 attr_value = gaim_status_get_attr_value(status, id); | |
891 g_return_if_fail(attr_value != NULL); | |
9949 | 892 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT); |
893 | |
894 gaim_value_set_int(attr_value, value); | |
6065 | 895 } |
896 | |
9949 | 897 void |
898 gaim_status_set_attr_string(GaimStatus *status, const char *id, | |
899 const char *value) | |
900 { | |
901 GaimStatusType *status_type; | |
902 GaimValue *attr_value; | |
903 | |
904 g_return_if_fail(status != NULL); | |
905 g_return_if_fail(id != NULL); | |
906 | |
907 status_type = gaim_status_get_type(status); | |
908 | |
10197 | 909 /* Make sure this attribute exists and is the correct type. */ |
10196 | 910 attr_value = gaim_status_get_attr_value(status, id); |
10197 | 911 g_return_if_fail(attr_value != NULL); |
9949 | 912 g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING); |
913 | |
914 gaim_value_set_string(attr_value, value); | |
915 } | |
916 | |
917 GaimStatusType * | |
918 gaim_status_get_type(const GaimStatus *status) | |
919 { | |
920 g_return_val_if_fail(status != NULL, NULL); | |
921 | |
922 return status->type; | |
923 } | |
924 | |
925 GaimPresence * | |
926 gaim_status_get_presence(const GaimStatus *status) | |
6065 | 927 { |
9949 | 928 g_return_val_if_fail(status != NULL, NULL); |
929 | |
930 return status->presence; | |
931 } | |
932 | |
933 const char * | |
934 gaim_status_get_id(const GaimStatus *status) | |
935 { | |
936 g_return_val_if_fail(status != NULL, NULL); | |
937 | |
938 return gaim_status_type_get_id(gaim_status_get_type(status)); | |
939 } | |
940 | |
941 const char * | |
942 gaim_status_get_name(const GaimStatus *status) | |
943 { | |
944 g_return_val_if_fail(status != NULL, NULL); | |
945 | |
946 return gaim_status_type_get_name(gaim_status_get_type(status)); | |
947 } | |
948 | |
949 gboolean | |
950 gaim_status_is_independent(const GaimStatus *status) | |
951 { | |
952 g_return_val_if_fail(status != NULL, FALSE); | |
953 | |
954 return gaim_status_type_is_independent(gaim_status_get_type(status)); | |
955 } | |
956 | |
957 gboolean | |
10067 | 958 gaim_status_is_exclusive(const GaimStatus *status) |
959 { | |
960 g_return_val_if_fail(status != NULL, FALSE); | |
961 | |
962 return gaim_status_type_is_exclusive(gaim_status_get_type(status)); | |
963 } | |
964 | |
965 gboolean | |
9949 | 966 gaim_status_is_available(const GaimStatus *status) |
967 { | |
968 g_return_val_if_fail(status != NULL, FALSE); | |
969 | |
970 return gaim_status_type_is_available(gaim_status_get_type(status)); | |
971 } | |
6216 | 972 |
9949 | 973 gboolean |
974 gaim_status_is_active(const GaimStatus *status) | |
975 { | |
976 g_return_val_if_fail(status != NULL, FALSE); | |
977 | |
978 return status->active; | |
979 } | |
980 | |
10040
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
981 gboolean |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
982 gaim_status_is_online(const GaimStatus *status) |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
983 { |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
984 GaimStatusPrimitive primitive; |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
985 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
986 g_return_val_if_fail( status != NULL, FALSE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
987 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
988 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
989 |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
990 return (primitive != GAIM_STATUS_UNSET && |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
991 primitive != GAIM_STATUS_OFFLINE); |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
992 } |
81059dce3aed
[gaim-migrate @ 10999]
Luke Schierer <lschiere@pidgin.im>
parents:
10013
diff
changeset
|
993 |
9949 | 994 GaimValue * |
995 gaim_status_get_attr_value(const GaimStatus *status, const char *id) | |
996 { | |
997 GaimStatusType *status_type; | |
998 GaimStatusAttr *attr; | |
999 | |
1000 g_return_val_if_fail(status != NULL, NULL); | |
1001 g_return_val_if_fail(id != NULL, NULL); | |
1002 | |
1003 status_type = gaim_status_get_type(status); | |
1004 | |
1005 /* Make sure this attribute exists. */ | |
1006 attr = gaim_status_type_get_attr(status_type, id); | |
1007 g_return_val_if_fail(attr != NULL, NULL); | |
1008 | |
1009 return (GaimValue *)g_hash_table_lookup(status->attr_values, id); | |
1010 } | |
1011 | |
1012 gboolean | |
1013 gaim_status_get_attr_boolean(const GaimStatus *status, const char *id) | |
1014 { | |
1015 const GaimValue *value; | |
1016 | |
1017 g_return_val_if_fail(status != NULL, FALSE); | |
1018 g_return_val_if_fail(id != NULL, FALSE); | |
1019 | |
1020 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
1021 return FALSE; | |
1022 | |
10197 | 1023 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE); |
9949 | 1024 |
1025 return gaim_value_get_boolean(value); | |
1026 } | |
1027 | |
1028 int | |
1029 gaim_status_get_attr_int(const GaimStatus *status, const char *id) | |
1030 { | |
1031 const GaimValue *value; | |
1032 | |
10507 | 1033 g_return_val_if_fail(status != NULL, 0); |
1034 g_return_val_if_fail(id != NULL, 0); | |
9949 | 1035 |
1036 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10507 | 1037 return 0; |
9949 | 1038 |
1039 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0); | |
1040 | |
1041 return gaim_value_get_int(value); | |
1042 } | |
1043 | |
1044 const char * | |
1045 gaim_status_get_attr_string(const GaimStatus *status, const char *id) | |
1046 { | |
1047 const GaimValue *value; | |
1048 | |
10507 | 1049 g_return_val_if_fail(status != NULL, NULL); |
1050 g_return_val_if_fail(id != NULL, NULL); | |
9949 | 1051 |
1052 if ((value = gaim_status_get_attr_value(status, id)) == NULL) | |
10504 | 1053 return NULL; |
9949 | 1054 |
1055 g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL); | |
1056 | |
1057 return gaim_value_get_string(value); | |
1058 } | |
1059 | |
1060 gint | |
1061 gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2) | |
1062 { | |
1063 GaimStatusType *type1, *type2; | |
1064 int score1 = 0, score2 = 0; | |
6065 | 1065 |
9949 | 1066 if ((status1 == NULL && status2 == NULL) || |
1067 (status1 == status2)) | |
1068 { | |
1069 return 0; | |
1070 } | |
1071 else if (status1 == NULL) | |
1072 return 1; | |
1073 else if (status2 == NULL) | |
1074 return -1; | |
1075 | |
1076 type1 = gaim_status_get_type(status1); | |
1077 type2 = gaim_status_get_type(status2); | |
1078 | |
1079 if (gaim_status_is_active(status1)) | |
1080 score1 = primitive_scores[gaim_status_type_get_primitive(type1)]; | |
1081 | |
1082 if (gaim_status_is_active(status2)) | |
1083 score2 = primitive_scores[gaim_status_type_get_primitive(type2)]; | |
1084 | |
1085 if (score1 > score2) | |
1086 return -1; | |
1087 else if (score1 < score2) | |
1088 return 1; | |
1089 | |
1090 return 0; | |
1091 } | |
1092 | |
1093 | |
1094 /************************************************************************** | |
1095 * GaimPresence API | |
1096 **************************************************************************/ | |
1097 GaimPresence * | |
1098 gaim_presence_new(GaimPresenceContext context) | |
1099 { | |
1100 GaimPresence *presence; | |
1101 | |
1102 g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL); | |
1103 | |
1104 presence = g_new0(GaimPresence, 1); | |
11187 | 1105 GAIM_DBUS_REGISTER_POINTER(presence, GaimPresence); |
9949 | 1106 |
1107 presence->context = context; | |
1108 | |
1109 presence->status_table = | |
10009 | 1110 g_hash_table_new_full(g_str_hash, g_str_equal, |
1111 g_free, (GFreeFunc)gaim_status_destroy); | |
9949 | 1112 |
1113 return presence; | |
1114 } | |
1115 | |
1116 GaimPresence * | |
1117 gaim_presence_new_for_account(GaimAccount *account) | |
1118 { | |
10012 | 1119 GaimPresence *presence = NULL; |
9949 | 1120 g_return_val_if_fail(account != NULL, NULL); |
1121 | |
1122 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT); | |
1123 presence->u.account = account; | |
10006 | 1124 presence->statuses = gaim_prpl_get_statuses(account, presence); |
9949 | 1125 |
1126 return presence; | |
1127 } | |
1128 | |
1129 GaimPresence * | |
1130 gaim_presence_new_for_conv(GaimConversation *conv) | |
1131 { | |
1132 GaimPresence *presence; | |
1133 | |
1134 g_return_val_if_fail(conv != NULL, NULL); | |
1135 | |
1136 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV); | |
1137 presence->u.chat.conv = conv; | |
10006 | 1138 /* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */ |
9949 | 1139 |
1140 return presence; | |
1141 } | |
6216 | 1142 |
9949 | 1143 GaimPresence * |
1144 gaim_presence_new_for_buddy(GaimBuddy *buddy) | |
1145 { | |
1146 GaimPresence *presence; | |
1147 GaimStatusBuddyKey *key; | |
10006 | 1148 GaimAccount *account; |
9949 | 1149 |
1150 g_return_val_if_fail(buddy != NULL, NULL); | |
10012 | 1151 account = buddy->account; |
9949 | 1152 |
10006 | 1153 account = buddy->account; |
1154 | |
9949 | 1155 key = g_new0(GaimStatusBuddyKey, 1); |
1156 key->account = buddy->account; | |
1157 key->name = g_strdup(buddy->name); | |
10006 | 1158 |
1159 presence = g_hash_table_lookup(buddy_presences, key); | |
1160 if (presence == NULL) | |
9949 | 1161 { |
1162 presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY); | |
1163 | |
1164 presence->u.buddy.name = g_strdup(buddy->name); | |
1165 presence->u.buddy.account = buddy->account; | |
10006 | 1166 presence->statuses = gaim_prpl_get_statuses(buddy->account, presence); |
9949 | 1167 |
1168 g_hash_table_insert(buddy_presences, key, presence); | |
1169 } | |
1170 else | |
1171 { | |
1172 g_free(key->name); | |
1173 g_free(key); | |
1174 } | |
1175 | |
1176 presence->u.buddy.ref_count++; | |
1177 presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies, | |
1178 buddy); | |
1179 | |
1180 return presence; | |
1181 } | |
1182 | |
1183 void | |
1184 gaim_presence_destroy(GaimPresence *presence) | |
1185 { | |
1186 g_return_if_fail(presence != NULL); | |
6216 | 1187 |
9949 | 1188 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) |
1189 { | |
1190 GaimStatusBuddyKey key; | |
1191 | |
10077 | 1192 if(presence->u.buddy.ref_count != 0) |
1193 return; | |
9949 | 1194 |
1195 key.account = presence->u.buddy.account; | |
1196 key.name = presence->u.buddy.name; | |
1197 | |
1198 g_hash_table_remove(buddy_presences, &key); | |
1199 | |
1200 if (presence->u.buddy.name != NULL) | |
1201 g_free(presence->u.buddy.name); | |
1202 } | |
1203 else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV) | |
1204 { | |
1205 if (presence->u.chat.user != NULL) | |
1206 g_free(presence->u.chat.user); | |
1207 } | |
1208 | |
1209 if (presence->statuses != NULL) | |
1210 g_list_free(presence->statuses); | |
1211 | |
1212 g_hash_table_destroy(presence->status_table); | |
1213 | |
11187 | 1214 GAIM_DBUS_UNREGISTER_POINTER(presence); |
9949 | 1215 g_free(presence); |
1216 } | |
1217 | |
10580 | 1218 /* |
1219 * TODO: Maybe we should cal gaim_presence_destroy() after we | |
1220 * decrement the ref count? I don't see why we should | |
1221 * make other places do it manually when we can do it here. | |
1222 */ | |
9949 | 1223 void |
1224 gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy) | |
1225 { | |
1226 g_return_if_fail(presence != NULL); | |
1227 g_return_if_fail(buddy != NULL); | |
1228 g_return_if_fail(gaim_presence_get_context(presence) == | |
1229 GAIM_PRESENCE_CONTEXT_BUDDY); | |
1230 | |
1231 if (g_list_find(presence->u.buddy.buddies, buddy) != NULL) | |
1232 { | |
1233 presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies, | |
1234 buddy); | |
1235 presence->u.buddy.ref_count--; | |
1236 } | |
6065 | 1237 } |
1238 | |
9949 | 1239 void |
1240 gaim_presence_add_status(GaimPresence *presence, GaimStatus *status) | |
1241 { | |
1242 g_return_if_fail(presence != NULL); | |
1243 g_return_if_fail(status != NULL); | |
1244 | |
1245 presence->statuses = g_list_append(presence->statuses, status); | |
1246 | |
1247 g_hash_table_insert(presence->status_table, | |
1248 g_strdup(gaim_status_get_id(status)), status); | |
1249 } | |
1250 | |
1251 void | |
1252 gaim_presence_add_presence(GaimPresence *presence, const GList *source_list) | |
1253 { | |
1254 const GList *l; | |
1255 | |
1256 g_return_if_fail(presence != NULL); | |
1257 g_return_if_fail(source_list != NULL); | |
1258 | |
1259 for (l = source_list; l != NULL; l = l->next) | |
1260 gaim_presence_add_status(presence, (GaimStatus *)l->data); | |
1261 } | |
1262 | |
1263 void | |
1264 gaim_presence_set_status_active(GaimPresence *presence, const char *status_id, | |
1265 gboolean active) | |
1266 { | |
1267 GaimStatus *status; | |
1268 | |
1269 g_return_if_fail(presence != NULL); | |
1270 g_return_if_fail(status_id != NULL); | |
1271 | |
1272 status = gaim_presence_get_status(presence, status_id); | |
1273 | |
1274 g_return_if_fail(status != NULL); | |
10348 | 1275 /* TODO: Should we do the following? */ |
1276 /* g_return_if_fail(active == status->active); */ | |
9949 | 1277 |
10067 | 1278 if (gaim_status_is_exclusive(status)) |
9949 | 1279 { |
1280 if (!active) | |
1281 { | |
1282 gaim_debug_warning("status", | |
1283 "Attempted to set a non-independent status " | |
1284 "(%s) inactive. Only independent statuses " | |
1285 "can be specifically marked inactive.", | |
1286 status_id); | |
1287 return; | |
1288 } | |
1289 } | |
1290 | |
1291 gaim_status_set_active(status, active); | |
1292 } | |
1293 | |
1294 void | |
1295 gaim_presence_switch_status(GaimPresence *presence, const char *status_id) | |
1296 { | |
10754 | 1297 gaim_presence_set_status_active(presence, status_id, TRUE); |
9949 | 1298 } |
1299 | |
1300 static void | |
1301 update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence, | |
1302 time_t current_time, gboolean old_idle, gboolean idle) | |
1303 { | |
1304 GaimBlistUiOps *ops = gaim_get_blist()->ui_ops; | |
1305 | |
1306 if (!old_idle && idle) | |
1307 { | |
1308 gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle", buddy); | |
1309 | |
1310 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1311 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1312 { | |
1313 GaimLog *log = gaim_account_get_log(buddy->account); | |
1314 char *tmp = g_strdup_printf(_("%s became idle"), | |
1315 gaim_buddy_get_alias(buddy)); | |
1316 | |
1317 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1318 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1319 g_free(tmp); | |
1320 } | |
1321 } | |
1322 else if (old_idle && !idle) | |
1323 { | |
1324 gaim_signal_emit(gaim_blist_get_handle(), "buddy-unidle", buddy); | |
1325 | |
1326 if (gaim_prefs_get_bool("/core/logging/log_system") && | |
1327 gaim_prefs_get_bool("/core/logging/log_idle_state")) | |
1328 { | |
1329 GaimLog *log = gaim_account_get_log(buddy->account); | |
1330 char *tmp = g_strdup_printf(_("%s became unidle"), | |
1331 gaim_buddy_get_alias(buddy)); | |
1332 | |
1333 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
1334 gaim_buddy_get_alias(buddy), current_time, tmp); | |
1335 g_free(tmp); | |
1336 } | |
1337 } | |
1338 | |
10378 | 1339 gaim_contact_invalidate_priority_buddy(gaim_buddy_get_contact(buddy)); |
9949 | 1340 |
1341 if (ops != NULL && ops->update != NULL) | |
1342 ops->update(gaim_get_blist(), (GaimBlistNode *)buddy); | |
1343 } | |
1344 | |
1345 void | |
1346 gaim_presence_set_idle(GaimPresence *presence, gboolean idle, time_t idle_time) | |
1347 { | |
1348 gboolean old_idle; | |
1349 | |
1350 g_return_if_fail(presence != NULL); | |
1351 | |
1352 if (presence->idle == idle && presence->idle_time == idle_time) | |
1353 return; | |
1354 | |
1355 old_idle = presence->idle; | |
1356 presence->idle = idle; | |
1357 presence->idle_time = (idle ? idle_time : 0); | |
1358 | |
1359 if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY) | |
1360 { | |
1361 const GList *l; | |
1362 time_t current_time = time(NULL); | |
1363 | |
1364 for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next) | |
1365 { | |
1366 update_buddy_idle((GaimBuddy *)l->data, presence, current_time, | |
1367 old_idle, idle); | |
1368 } | |
1369 } | |
1370 } | |
1371 | |
1372 void | |
10006 | 1373 gaim_presence_set_login_time(GaimPresence *presence, time_t login_time) |
1374 { | |
1375 g_return_if_fail(presence != NULL); | |
1376 | |
1377 if (presence->login_time == login_time) | |
1378 return; | |
1379 | |
1380 presence->login_time = login_time; | |
1381 } | |
1382 | |
9949 | 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 |
10567 | 1558 time_t |
1559 gaim_presence_get_login_time(const GaimPresence *presence) | |
1560 { | |
1561 g_return_val_if_fail(presence != NULL, 0); | |
1562 | |
1563 return presence->login_time; | |
1564 } | |
1565 | |
9949 | 1566 gint |
1567 gaim_presence_compare(const GaimPresence *presence1, | |
1568 const GaimPresence *presence2) | |
6065 | 1569 { |
9949 | 1570 gboolean idle1, idle2; |
10860 | 1571 time_t idle_time_1, idle_time_2; |
9949 | 1572 int score1 = 0, score2 = 0; |
1573 const GList *l; | |
6065 | 1574 |
9949 | 1575 if ((presence1 == NULL && presence2 == NULL) || (presence1 == presence2)) |
1576 return 0; | |
1577 else if (presence1 == NULL) | |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1578 return 1; |
9949 | 1579 else if (presence2 == NULL) |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1580 return -1; |
6065 | 1581 |
9949 | 1582 /* Compute the score of the first set of statuses. */ |
1583 for (l = gaim_presence_get_statuses(presence1); l != NULL; l = l->next) | |
1584 { | |
1585 GaimStatus *status = (GaimStatus *)l->data; | |
1586 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1587 |
9949 | 1588 if (gaim_status_is_active(status)) |
1589 score1 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1590 } |
1591 | |
9949 | 1592 /* Compute the score of the second set of statuses. */ |
10151
d83e6f2125b1
[gaim-migrate @ 11228]
Christian Hammond <chipx86@chipx86.com>
parents:
10087
diff
changeset
|
1593 for (l = gaim_presence_get_statuses(presence2); l != NULL; l = l->next) |
9949 | 1594 { |
1595 GaimStatus *status = (GaimStatus *)l->data; | |
1596 GaimStatusType *type = gaim_status_get_type(status); | |
6065 | 1597 |
9949 | 1598 if (gaim_status_is_active(status)) |
1599 score2 += primitive_scores[gaim_status_type_get_primitive(type)]; | |
6065 | 1600 } |
1601 | |
9949 | 1602 idle1 = gaim_presence_is_idle(presence1); |
1603 idle2 = gaim_presence_is_idle(presence2); | |
6065 | 1604 |
9949 | 1605 if (idle1) |
1606 score1 += primitive_scores[SCORE_IDLE]; | |
6065 | 1607 |
9949 | 1608 if (idle2) |
1609 score2 += primitive_scores[SCORE_IDLE]; | |
6065 | 1610 |
10860 | 1611 idle_time_1 = time(NULL) - gaim_presence_get_idle_time(presence1); |
1612 idle_time_2 = time(NULL) - gaim_presence_get_idle_time(presence2); | |
6065 | 1613 |
9949 | 1614 if (idle_time_1 > idle_time_2) |
1615 score1 += primitive_scores[SCORE_IDLE_TIME]; | |
1616 else if (idle_time_1 < idle_time_2) | |
1617 score2 += primitive_scores[SCORE_IDLE_TIME]; | |
6065 | 1618 |
9949 | 1619 if (score1 < score2) |
1620 return 1; | |
1621 else if (score1 > score2) | |
1622 return -1; | |
1623 | |
1624 return 0; | |
1625 } | |
1626 | |
6065 | 1627 |
9949 | 1628 /************************************************************************** |
1629 * Status subsystem | |
1630 **************************************************************************/ | |
1631 static void | |
1632 score_pref_changed_cb(const char *name, GaimPrefType type, gpointer value, | |
1633 gpointer data) | |
1634 { | |
1635 int index = GPOINTER_TO_INT(data); | |
6065 | 1636 |
9949 | 1637 primitive_scores[index] = GPOINTER_TO_INT(value); |
6065 | 1638 } |
1639 | |
10519 | 1640 static guint |
10006 | 1641 gaim_buddy_presences_hash(gconstpointer key) |
1642 { | |
10012 | 1643 const GaimStatusBuddyKey *me = key; |
1644 guint ret; | |
1645 char *str; | |
1646 | |
1647 str = g_strdup_printf("%p%s", me->account, me->name); | |
1648 ret = g_str_hash(str); | |
1649 g_free(str); | |
1650 | |
1651 return ret; | |
10006 | 1652 } |
1653 | |
10519 | 1654 static gboolean |
10006 | 1655 gaim_buddy_presences_equal(gconstpointer a, gconstpointer b) |
1656 { | |
1657 GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a; | |
1658 GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b; | |
1659 | |
10012 | 1660 if(key_a->account == key_b->account && |
1661 !strcmp(key_a->name, key_b->name)) | |
10006 | 1662 return TRUE; |
1663 else | |
1664 return FALSE; | |
1665 } | |
1666 | |
10519 | 1667 static void |
1668 gaim_buddy_presences_key_free(gpointer a) | |
1669 { | |
1670 GaimStatusBuddyKey *key = (GaimStatusBuddyKey *)a; | |
1671 g_free(key->name); | |
1672 g_free(key); | |
1673 } | |
1674 | |
10087 | 1675 void * |
10418 | 1676 gaim_status_get_handle(void) { |
10087 | 1677 static int handle; |
1678 | |
1679 return &handle; | |
1680 } | |
1681 | |
9949 | 1682 void |
10418 | 1683 gaim_status_init(void) |
6065 | 1684 { |
10418 | 1685 void *handle = gaim_status_get_handle; |
10087 | 1686 |
9949 | 1687 gaim_prefs_add_none("/core/status"); |
1688 gaim_prefs_add_none("/core/status/scores"); | |
6065 | 1689 |
9949 | 1690 gaim_prefs_add_int("/core/status/scores/offline", |
1691 primitive_scores[GAIM_STATUS_OFFLINE]); | |
1692 gaim_prefs_add_int("/core/status/scores/available", | |
1693 primitive_scores[GAIM_STATUS_AVAILABLE]); | |
1694 gaim_prefs_add_int("/core/status/scores/hidden", | |
1695 primitive_scores[GAIM_STATUS_HIDDEN]); | |
1696 gaim_prefs_add_int("/core/status/scores/away", | |
1697 primitive_scores[GAIM_STATUS_AWAY]); | |
1698 gaim_prefs_add_int("/core/status/scores/extended_away", | |
1699 primitive_scores[GAIM_STATUS_EXTENDED_AWAY]); | |
1700 gaim_prefs_add_int("/core/status/scores/idle", | |
1701 primitive_scores[SCORE_IDLE]); | |
6065 | 1702 |
10087 | 1703 gaim_prefs_connect_callback(handle, "/core/status/scores/offline", |
9949 | 1704 score_pref_changed_cb, |
1705 GINT_TO_POINTER(GAIM_STATUS_OFFLINE)); | |
10087 | 1706 gaim_prefs_connect_callback(handle, "/core/status/scores/available", |
9949 | 1707 score_pref_changed_cb, |
1708 GINT_TO_POINTER(GAIM_STATUS_AVAILABLE)); | |
10087 | 1709 gaim_prefs_connect_callback(handle, "/core/status/scores/hidden", |
9949 | 1710 score_pref_changed_cb, |
1711 GINT_TO_POINTER(GAIM_STATUS_HIDDEN)); | |
10087 | 1712 gaim_prefs_connect_callback(handle, "/core/status/scores/away", |
9949 | 1713 score_pref_changed_cb, |
1714 GINT_TO_POINTER(GAIM_STATUS_AWAY)); | |
10087 | 1715 gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away", |
9949 | 1716 score_pref_changed_cb, |
1717 GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY)); | |
10087 | 1718 gaim_prefs_connect_callback(handle, "/core/status/scores/idle", |
9949 | 1719 score_pref_changed_cb, |
1720 GINT_TO_POINTER(SCORE_IDLE)); | |
10006 | 1721 |
10519 | 1722 buddy_presences = g_hash_table_new_full(gaim_buddy_presences_hash, |
1723 gaim_buddy_presences_equal, | |
1724 gaim_buddy_presences_key_free, NULL); | |
9949 | 1725 } |
6065 | 1726 |
9949 | 1727 void |
10418 | 1728 gaim_status_uninit(void) |
9949 | 1729 { |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1730 if (buddy_presences != NULL) |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1731 { |
10077 | 1732 g_hash_table_destroy(buddy_presences); |
10176
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1733 |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1734 buddy_presences = NULL; |
0109f3a518d2
[gaim-migrate @ 11291]
Christian Hammond <chipx86@chipx86.com>
parents:
10153
diff
changeset
|
1735 } |
9949 | 1736 } |