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