pidgin/pidgin

Parents c0ea70247280
Children 222423055d93
Move PurpleAccountPresence and PurpleBuddyPresence to their own files

split purpleaccountpresence and purplebuddypresence out to their own files. Going to clean up the `update_idle` methods and convert them from `time_t` to `GDateTime` in another PR, so I didn't do anything aside from the bare minimum in them right now.

Testing Done:
ran and verified logins still work.

Reviewed at https://reviews.imfreedom.org/r/122/
--- a/doc/reference/libpurple/libpurple-docs.xml Wed Sep 16 02:04:11 2020 -0500
+++ b/doc/reference/libpurple/libpurple-docs.xml Mon Sep 21 20:15:51 2020 -0500
@@ -65,7 +65,9 @@
<xi:include href="xml/proxy.xml" />
<xi:include href="xml/purple-gio.xml" />
<xi:include href="xml/purpleaccountoption.xml" />
+ <xi:include href="xml/purpleaccountpresence.xml" />
<xi:include href="xml/purpleaccountusersplit.xml" />
+ <xi:include href="xml/purplebuddypresence.xml" />
<xi:include href="xml/purplechatuser.xml" />
<xi:include href="xml/purpleimconversation.xml" />
<xi:include href="xml/purplekeyvaluepair.xml" />
--- a/libpurple/account.c Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/account.c Mon Sep 21 20:15:51 2020 -0500
@@ -30,6 +30,7 @@
#include "notify.h"
#include "pounce.h"
#include "prefs.h"
+#include "purpleaccountpresence.h"
#include "purpleprivate.h"
#include "request.h"
#include "server.h"
--- a/libpurple/buddy.c Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/buddy.c Mon Sep 21 20:15:51 2020 -0500
@@ -21,6 +21,7 @@
*
*/
#include "internal.h"
+#include "purplebuddypresence.h"
#include "util.h"
typedef struct _PurpleBuddyPrivate PurpleBuddyPrivate;
--- a/libpurple/contact.c Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/contact.c Mon Sep 21 20:15:51 2020 -0500
@@ -23,6 +23,7 @@
#include "contact.h"
#include "internal.h" /* TODO: this needs to die */
+#include "purplebuddypresence.h"
#include "purpleprivate.h"
#include "util.h"
--- a/libpurple/meson.build Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/meson.build Mon Sep 21 20:15:51 2020 -0500
@@ -49,7 +49,9 @@
'protocols.c',
'purple-gio.c',
'purpleaccountoption.c',
+ 'purpleaccountpresence.c',
'purpleaccountusersplit.c',
+ 'purplebuddypresence.c',
'purplechatuser.c',
'purpleimconversation.c',
'purpleattachment.c',
@@ -131,7 +133,9 @@
'protocols.h',
'purple-gio.h',
'purpleaccountoption.h',
+ 'purpleaccountpresence.h',
'purpleaccountusersplit.h',
+ 'purplebuddypresence.h',
'purplechatuser.h',
'purpleimconversation.h',
'purpleattachment.h',
--- a/libpurple/presence.c Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/presence.c Mon Sep 21 20:15:51 2020 -0500
@@ -26,112 +26,212 @@
#include "presence.h"
#include "purpleprivate.h"
-/**************************************************************************
- * PurplePresence
- **************************************************************************/
-
-/** Private data for a presence */
-typedef struct
-{
+typedef struct {
gboolean idle;
time_t idle_time;
time_t login_time;
- GList *statuses;
GHashTable *status_table;
PurpleStatus *active_status;
} PurplePresencePrivate;
-/* Presence property enums */
-enum
-{
- PRES_PROP_0,
- PRES_PROP_IDLE,
- PRES_PROP_IDLE_TIME,
- PRES_PROP_LOGIN_TIME,
- PRES_PROP_STATUSES,
- PRES_PROP_ACTIVE_STATUS,
- PRES_PROP_LAST
+enum {
+ PROP_0,
+ PROP_IDLE,
+ PROP_IDLE_TIME,
+ PROP_LOGIN_TIME,
+ PROP_ACTIVE_STATUS,
+ N_PROPERTIES
};
-
-static GParamSpec *properties[PRES_PROP_LAST];
+static GParamSpec *properties[N_PROPERTIES];
G_DEFINE_TYPE_WITH_PRIVATE(PurplePresence, purple_presence, G_TYPE_OBJECT)
-/**************************************************************************
- * PurpleAccountPresence
- **************************************************************************/
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_presence_set_active_status(PurplePresence *presence,
+ PurpleStatus *status)
+{
+ PurplePresencePrivate *priv = NULL;
+
+ priv = purple_presence_get_instance_private(presence);
-/**
- * PurpleAccountPresence:
- *
- * A presence for an account
- */
-struct _PurpleAccountPresence
-{
- PurplePresence parent;
-};
+ if(g_set_object(&priv->active_status, status)) {
+ g_object_notify_by_pspec(G_OBJECT(presence),
+ properties[PROP_ACTIVE_STATUS]);
+ }
+}
-/** Private data for an account presence */
-typedef struct
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+purple_presence_set_property(GObject *obj, guint param_id, const GValue *value,
+ GParamSpec *pspec)
{
- PurpleAccount *account;
-} PurpleAccountPresencePrivate;
+ PurplePresence *presence = PURPLE_PRESENCE(obj);
-/* Account presence property enums */
-enum
+ switch (param_id) {
+ case PROP_IDLE:
+ purple_presence_set_idle(presence, g_value_get_boolean(value), 0);
+ break;
+ case PROP_IDLE_TIME:
+#if SIZEOF_TIME_T == 4
+ purple_presence_set_idle(presence, TRUE, g_value_get_int(value));
+#elif SIZEOF_TIME_T == 8
+ purple_presence_set_idle(presence, TRUE, g_value_get_int64(value));
+#else
+#error Unknown size of time_t
+#endif
+ break;
+ case PROP_LOGIN_TIME:
+#if SIZEOF_TIME_T == 4
+ purple_presence_set_login_time(presence, g_value_get_int(value));
+#elif SIZEOF_TIME_T == 8
+ purple_presence_set_login_time(presence, g_value_get_int64(value));
+#else
+#error Unknown size of time_t
+#endif
+ break;
+ case PROP_ACTIVE_STATUS:
+ purple_presence_set_active_status(presence,
+ g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+/* Get method for GObject properties */
+static void
+purple_presence_get_property(GObject *obj, guint param_id, GValue *value,
+ GParamSpec *pspec)
{
- ACPRES_PROP_0,
- ACPRES_PROP_ACCOUNT,
- ACPRES_PROP_LAST
-};
-
-static GParamSpec *ap_properties[ACPRES_PROP_LAST];
-
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleAccountPresence, purple_account_presence,
- PURPLE_TYPE_PRESENCE)
-
-/**************************************************************************
- * PurpleBuddyPresence
- **************************************************************************/
+ PurplePresence *presence = PURPLE_PRESENCE(obj);
-/**
- * PurpleBuddyPresence:
- *
- * A presence for a buddy
- */
-struct _PurpleBuddyPresence
+ switch (param_id) {
+ case PROP_IDLE:
+ g_value_set_boolean(value, purple_presence_is_idle(presence));
+ break;
+ case PROP_IDLE_TIME:
+#if SIZEOF_TIME_T == 4
+ g_value_set_int(value, purple_presence_get_idle_time(presence));
+#elif SIZEOF_TIME_T == 8
+ g_value_set_int64(value, purple_presence_get_idle_time(presence));
+#else
+#error Unknown size of time_t
+#endif
+ break;
+ case PROP_LOGIN_TIME:
+#if SIZEOF_TIME_T == 4
+ g_value_set_int(value, purple_presence_get_login_time(presence));
+#elif SIZEOF_TIME_T == 8
+ g_value_set_int64(value, purple_presence_get_login_time(presence));
+#else
+#error Unknown size of time_t
+#endif
+ break;
+ case PROP_ACTIVE_STATUS:
+ g_value_set_object(value, purple_presence_get_active_status(presence));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_presence_init(PurplePresence *presence) {
+ PurplePresencePrivate *priv = NULL;
+
+ priv = purple_presence_get_instance_private(presence);
+
+ priv->status_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ NULL);
+}
+
+static void
+purple_presence_finalize(GObject *obj)
{
- PurplePresence parent;
-};
+ PurplePresencePrivate *priv = NULL;
+
+ priv = purple_presence_get_instance_private(PURPLE_PRESENCE(obj));
+
+ g_hash_table_destroy(priv->status_table);
+ g_clear_object(&priv->active_status);
-/** Private data for a buddy presence */
-typedef struct
+ G_OBJECT_CLASS(purple_presence_parent_class)->finalize(obj);
+}
+
+/* Class initializer function */
+static void purple_presence_class_init(PurplePresenceClass *klass)
{
- PurpleBuddy *buddy;
-} PurpleBuddyPresencePrivate;
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-/* Buddy presence property enums */
-enum
-{
- BUDPRES_PROP_0,
- BUDPRES_PROP_BUDDY,
- BUDPRES_PROP_LAST
-};
+ obj_class->get_property = purple_presence_get_property;
+ obj_class->set_property = purple_presence_set_property;
+ obj_class->finalize = purple_presence_finalize;
+
+ properties[PROP_IDLE] = g_param_spec_boolean("idle", "Idle",
+ "Whether the presence is in idle state.", FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-static GParamSpec *bp_properties[BUDPRES_PROP_LAST];
+ properties[PROP_IDLE_TIME] =
+#if SIZEOF_TIME_T == 4
+ g_param_spec_int
+#elif SIZEOF_TIME_T == 8
+ g_param_spec_int64
+#else
+#error Unknown size of time_t
+#endif
+ ("idle-time", "Idle time",
+ "The idle time of the presence",
+#if SIZEOF_TIME_T == 4
+ G_MININT, G_MAXINT, 0,
+#elif SIZEOF_TIME_T == 8
+ G_MININT64, G_MAXINT64, 0,
+#else
+#error Unknown size of time_t
+#endif
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleBuddyPresence, purple_buddy_presence,
- PURPLE_TYPE_PRESENCE)
+ properties[PROP_LOGIN_TIME] =
+#if SIZEOF_TIME_T == 4
+ g_param_spec_int
+#elif SIZEOF_TIME_T == 8
+ g_param_spec_int64
+#else
+#error Unknown size of time_t
+#endif
+ ("login-time", "Login time",
+ "The login time of the presence.",
+#if SIZEOF_TIME_T == 4
+ G_MININT, G_MAXINT, 0,
+#elif SIZEOF_TIME_T == 8
+ G_MININT64, G_MAXINT64, 0,
+#else
+#error Unknown size of time_t
+#endif
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-/**************************************************************************
-* PurplePresence API
-**************************************************************************/
+ properties[PROP_ACTIVE_STATUS] = g_param_spec_object("active-status",
+ "Active status",
+ "The active status for the presence.", PURPLE_TYPE_STATUS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
void
-purple_presence_set_status_active(PurplePresence *presence, const char *status_id,
- gboolean active)
+purple_presence_set_status_active(PurplePresence *presence,
+ const gchar *status_id, gboolean active)
{
PurpleStatus *status;
@@ -161,13 +261,14 @@
}
void
-purple_presence_switch_status(PurplePresence *presence, const char *status_id)
+purple_presence_switch_status(PurplePresence *presence, const gchar *status_id)
{
purple_presence_set_status_active(presence, status_id, TRUE);
}
void
-purple_presence_set_idle(PurplePresence *presence, gboolean idle, time_t idle_time)
+purple_presence_set_idle(PurplePresence *presence, gboolean idle,
+ time_t idle_time)
{
PurplePresencePrivate *priv = NULL;
PurplePresenceClass *klass = NULL;
@@ -188,8 +289,8 @@
obj = G_OBJECT(presence);
g_object_freeze_notify(obj);
- g_object_notify_by_pspec(obj, properties[PRES_PROP_IDLE]);
- g_object_notify_by_pspec(obj, properties[PRES_PROP_IDLE_TIME]);
+ g_object_notify_by_pspec(obj, properties[PROP_IDLE]);
+ g_object_notify_by_pspec(obj, properties[PROP_IDLE_TIME]);
g_object_thaw_notify(obj);
if (klass->update_idle)
@@ -197,8 +298,7 @@
}
void
-purple_presence_set_login_time(PurplePresence *presence, time_t login_time)
-{
+purple_presence_set_login_time(PurplePresence *presence, time_t login_time) {
PurplePresencePrivate *priv = NULL;
g_return_if_fail(PURPLE_IS_PRESENCE(presence));
@@ -211,23 +311,25 @@
priv->login_time = login_time;
g_object_notify_by_pspec(G_OBJECT(presence),
- properties[PRES_PROP_LOGIN_TIME]);
+ properties[PROP_LOGIN_TIME]);
}
GList *
-purple_presence_get_statuses(PurplePresence *presence)
-{
- PurplePresencePrivate *priv = NULL;
+purple_presence_get_statuses(PurplePresence *presence) {
+ PurplePresenceClass *klass = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
- priv = purple_presence_get_instance_private(presence);
- return priv->statuses;
+ klass = PURPLE_PRESENCE_GET_CLASS(presence);
+ if(klass && klass->get_statuses) {
+ return klass->get_statuses(presence);
+ }
+
+ return NULL;
}
PurpleStatus *
-purple_presence_get_status(PurplePresence *presence, const char *status_id)
-{
+purple_presence_get_status(PurplePresence *presence, const gchar *status_id) {
PurplePresencePrivate *priv = NULL;
PurpleStatus *status;
GList *l = NULL;
@@ -260,19 +362,18 @@
}
PurpleStatus *
-purple_presence_get_active_status(PurplePresence *presence)
-{
+purple_presence_get_active_status(PurplePresence *presence) {
PurplePresencePrivate *priv = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL);
priv = purple_presence_get_instance_private(presence);
+
return priv->active_status;
}
gboolean
-purple_presence_is_available(PurplePresence *presence)
-{
+purple_presence_is_available(PurplePresence *presence) {
PurpleStatus *status;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
@@ -284,8 +385,7 @@
}
gboolean
-purple_presence_is_online(PurplePresence *presence)
-{
+purple_presence_is_online(PurplePresence *presence) {
PurpleStatus *status;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
@@ -298,7 +398,7 @@
gboolean
purple_presence_is_status_active(PurplePresence *presence,
- const char *status_id)
+ const gchar *status_id)
{
PurpleStatus *status;
@@ -312,7 +412,7 @@
gboolean
purple_presence_is_status_primitive_active(PurplePresence *presence,
- PurpleStatusPrimitive primitive)
+ PurpleStatusPrimitive primitive)
{
GList *l;
@@ -333,19 +433,18 @@
}
gboolean
-purple_presence_is_idle(PurplePresence *presence)
-{
+purple_presence_is_idle(PurplePresence *presence) {
PurplePresencePrivate *priv = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), FALSE);
priv = purple_presence_get_instance_private(presence);
+
return purple_presence_is_online(presence) && priv->idle;
}
time_t
-purple_presence_get_idle_time(PurplePresence *presence)
-{
+purple_presence_get_idle_time(PurplePresence *presence) {
PurplePresencePrivate *priv = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), 0);
@@ -355,8 +454,7 @@
}
time_t
-purple_presence_get_login_time(PurplePresence *presence)
-{
+purple_presence_get_login_time(PurplePresence *presence) {
PurplePresencePrivate *priv = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), 0);
@@ -364,594 +462,3 @@
priv = purple_presence_get_instance_private(presence);
return purple_presence_is_online(presence) ? priv->login_time : 0;
}
-
-/**************************************************************************
- * GObject code for PurplePresence
- **************************************************************************/
-
-/* Set method for GObject properties */
-static void
-purple_presence_set_property(GObject *obj, guint param_id, const GValue *value,
- GParamSpec *pspec)
-{
- PurplePresence *presence = PURPLE_PRESENCE(obj);
- PurplePresencePrivate *priv = purple_presence_get_instance_private(presence);
-
- switch (param_id) {
- case PRES_PROP_IDLE:
- purple_presence_set_idle(presence, g_value_get_boolean(value), 0);
- break;
- case PRES_PROP_IDLE_TIME:
-#if SIZEOF_TIME_T == 4
- purple_presence_set_idle(presence, TRUE, g_value_get_int(value));
-#elif SIZEOF_TIME_T == 8
- purple_presence_set_idle(presence, TRUE, g_value_get_int64(value));
-#else
-#error Unknown size of time_t
-#endif
- break;
- case PRES_PROP_LOGIN_TIME:
-#if SIZEOF_TIME_T == 4
- purple_presence_set_login_time(presence, g_value_get_int(value));
-#elif SIZEOF_TIME_T == 8
- purple_presence_set_login_time(presence, g_value_get_int64(value));
-#else
-#error Unknown size of time_t
-#endif
- break;
- case PRES_PROP_ACTIVE_STATUS:
- priv->active_status = g_value_get_object(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* Get method for GObject properties */
-static void
-purple_presence_get_property(GObject *obj, guint param_id, GValue *value,
- GParamSpec *pspec)
-{
- PurplePresence *presence = PURPLE_PRESENCE(obj);
-
- switch (param_id) {
- case PRES_PROP_IDLE:
- g_value_set_boolean(value, purple_presence_is_idle(presence));
- break;
- case PRES_PROP_IDLE_TIME:
-#if SIZEOF_TIME_T == 4
- g_value_set_int(value, purple_presence_get_idle_time(presence));
-#elif SIZEOF_TIME_T == 8
- g_value_set_int64(value, purple_presence_get_idle_time(presence));
-#else
-#error Unknown size of time_t
-#endif
- break;
- case PRES_PROP_LOGIN_TIME:
-#if SIZEOF_TIME_T == 4
- g_value_set_int(value, purple_presence_get_login_time(presence));
-#elif SIZEOF_TIME_T == 8
- g_value_set_int64(value, purple_presence_get_login_time(presence));
-#else
-#error Unknown size of time_t
-#endif
- break;
- case PRES_PROP_STATUSES:
- g_value_set_pointer(value, purple_presence_get_statuses(presence));
- break;
- case PRES_PROP_ACTIVE_STATUS:
- g_value_set_object(value, purple_presence_get_active_status(presence));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* GObject initialization function */
-static void
-purple_presence_init(PurplePresence *presence)
-{
- PurplePresencePrivate *priv = purple_presence_get_instance_private(presence);
- priv->status_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-}
-
-/* GObject dispose function */
-static void
-purple_presence_dispose(GObject *object)
-{
- PurplePresencePrivate *priv =
- purple_presence_get_instance_private(PURPLE_PRESENCE(object));
-
- if (priv->statuses) {
- g_list_free_full(priv->statuses, g_object_unref);
- priv->statuses = NULL;
- }
-
- G_OBJECT_CLASS(purple_presence_parent_class)->dispose(object);
-}
-
-/* GObject finalize function */
-static void
-purple_presence_finalize(GObject *object)
-{
- PurplePresencePrivate *priv =
- purple_presence_get_instance_private(PURPLE_PRESENCE(object));
-
- g_hash_table_destroy(priv->status_table);
-
- G_OBJECT_CLASS(purple_presence_parent_class)->finalize(object);
-}
-
-/* Class initializer function */
-static void purple_presence_class_init(PurplePresenceClass *klass)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
- obj_class->dispose = purple_presence_dispose;
- obj_class->finalize = purple_presence_finalize;
-
- /* Setup properties */
- obj_class->get_property = purple_presence_get_property;
- obj_class->set_property = purple_presence_set_property;
-
- properties[PRES_PROP_IDLE] = g_param_spec_boolean("idle", "Idle",
- "Whether the presence is in idle state.", FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- properties[PRES_PROP_IDLE_TIME] =
-#if SIZEOF_TIME_T == 4
- g_param_spec_int
-#elif SIZEOF_TIME_T == 8
- g_param_spec_int64
-#else
-#error Unknown size of time_t
-#endif
- ("idle-time", "Idle time",
- "The idle time of the presence",
-#if SIZEOF_TIME_T == 4
- G_MININT, G_MAXINT, 0,
-#elif SIZEOF_TIME_T == 8
- G_MININT64, G_MAXINT64, 0,
-#else
-#error Unknown size of time_t
-#endif
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- properties[PRES_PROP_LOGIN_TIME] =
-#if SIZEOF_TIME_T == 4
- g_param_spec_int
-#elif SIZEOF_TIME_T == 8
- g_param_spec_int64
-#else
-#error Unknown size of time_t
-#endif
- ("login-time", "Login time",
- "The login time of the presence.",
-#if SIZEOF_TIME_T == 4
- G_MININT, G_MAXINT, 0,
-#elif SIZEOF_TIME_T == 8
- G_MININT64, G_MAXINT64, 0,
-#else
-#error Unknown size of time_t
-#endif
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- properties[PRES_PROP_STATUSES] = g_param_spec_pointer("statuses",
- "Statuses",
- "The list of statuses in the presence.",
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- properties[PRES_PROP_ACTIVE_STATUS] = g_param_spec_object("active-status",
- "Active status",
- "The active status for the presence.", PURPLE_TYPE_STATUS,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(obj_class, PRES_PROP_LAST, properties);
-}
-
-/**************************************************************************
-* PurpleAccountPresence API
-**************************************************************************/
-static void
-purple_account_presence_update_idle(PurplePresence *presence, gboolean old_idle)
-{
- PurpleAccount *account;
- PurpleConnection *gc = NULL;
- PurpleProtocol *protocol = NULL;
- gboolean idle = purple_presence_is_idle(presence);
- time_t idle_time = purple_presence_get_idle_time(presence);
- time_t current_time = time(NULL);
-
- account = purple_account_presence_get_account(PURPLE_ACCOUNT_PRESENCE(presence));
-
- if (purple_prefs_get_bool("/purple/logging/log_system"))
- {
- PurpleLog *log = purple_account_get_log(account, FALSE);
-
- if (log != NULL)
- {
- char *msg, *tmp;
- GDateTime *dt;
-
- if (idle) {
- tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account));
- dt = g_date_time_new_from_unix_local(idle_time);
- } else {
- tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account));
- dt = g_date_time_new_now_utc();
- }
-
- msg = g_markup_escape_text(tmp, -1);
- g_free(tmp);
- purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
- purple_account_get_username(account),
- dt, msg);
- g_date_time_unref(dt);
- g_free(msg);
- }
- }
-
- gc = purple_account_get_connection(account);
-
- if(PURPLE_CONNECTION_IS_CONNECTED(gc))
- protocol = purple_connection_get_protocol(gc);
-
- if (protocol)
- purple_protocol_server_iface_set_idle(protocol, gc, (idle ? (current_time - idle_time) : 0));
-}
-
-PurpleAccount *
-purple_account_presence_get_account(PurpleAccountPresence *presence)
-{
- PurpleAccountPresencePrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_ACCOUNT_PRESENCE(presence), NULL);
-
- priv = purple_account_presence_get_instance_private(presence);
- return priv->account;
-}
-
-static int
-purple_buddy_presence_compute_score(PurpleBuddyPresence *buddy_presence)
-{
- GList *l;
- int score = 0;
- PurplePresence *presence = PURPLE_PRESENCE(buddy_presence);
- PurpleBuddy *b = purple_buddy_presence_get_buddy(buddy_presence);
- int *primitive_scores = _purple_statuses_get_primitive_scores();
- int offline_score = purple_prefs_get_int("/purple/status/scores/offline_msg");
- int idle_score = purple_prefs_get_int("/purple/status/scores/idle");
-
- for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
- PurpleStatus *status = (PurpleStatus *)l->data;
- PurpleStatusType *type = purple_status_get_status_type(status);
-
- if (purple_status_is_active(status)) {
- score += primitive_scores[purple_status_type_get_primitive(type)];
- if (!purple_status_is_online(status)) {
- if (b && purple_account_supports_offline_message(purple_buddy_get_account(b), b))
- score += offline_score;
- }
- }
- }
- score += purple_account_get_int(purple_buddy_get_account(b), "score", 0);
- if (purple_presence_is_idle(presence))
- score += idle_score;
- return score;
-}
-
-gint
-purple_buddy_presence_compare(PurpleBuddyPresence *buddy_presence1,
- PurpleBuddyPresence *buddy_presence2)
-{
- PurplePresence *presence1 = PURPLE_PRESENCE(buddy_presence1);
- PurplePresence *presence2 = PURPLE_PRESENCE(buddy_presence2);
- time_t idle_time_1, idle_time_2;
- int score1 = 0, score2 = 0;
- int idle_time_score = purple_prefs_get_int("/purple/status/scores/idle_time");
-
- if (presence1 == presence2)
- return 0;
- else if (presence1 == NULL)
- return 1;
- else if (presence2 == NULL)
- return -1;
-
- if (purple_presence_is_online(presence1) &&
- !purple_presence_is_online(presence2))
- return -1;
- else if (purple_presence_is_online(presence2) &&
- !purple_presence_is_online(presence1))
- return 1;
-
- /* Compute the score of the first set of statuses. */
- score1 = purple_buddy_presence_compute_score(buddy_presence1);
-
- /* Compute the score of the second set of statuses. */
- score2 = purple_buddy_presence_compute_score(buddy_presence2);
-
- idle_time_1 = time(NULL) - purple_presence_get_idle_time(presence1);
- idle_time_2 = time(NULL) - purple_presence_get_idle_time(presence2);
-
- if (idle_time_1 > idle_time_2)
- score1 += idle_time_score;
- else if (idle_time_1 < idle_time_2)
- score2 += idle_time_score;
-
- if (score1 < score2)
- return 1;
- else if (score1 > score2)
- return -1;
-
- return 0;
-}
-
-/**************************************************************************
- * GObject code for PurpleAccountPresence
- **************************************************************************/
-
-/* Set method for GObject properties */
-static void
-purple_account_presence_set_property(GObject *obj, guint param_id, const GValue *value,
- GParamSpec *pspec)
-{
- PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(obj);
- PurpleAccountPresencePrivate *priv =
- purple_account_presence_get_instance_private(account_presence);
-
- switch (param_id) {
- case ACPRES_PROP_ACCOUNT:
- priv->account = g_value_get_object(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* Get method for GObject properties */
-static void
-purple_account_presence_get_property(GObject *obj, guint param_id, GValue *value,
- GParamSpec *pspec)
-{
- PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(obj);
-
- switch (param_id) {
- case ACPRES_PROP_ACCOUNT:
- g_value_set_object(value,
- purple_account_presence_get_account(account_presence));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* Called when done constructing */
-static void
-purple_account_presence_constructed(GObject *object)
-{
- PurplePresence *presence = PURPLE_PRESENCE(object);
- PurplePresencePrivate *parent_priv = purple_presence_get_instance_private(presence);
- PurpleAccountPresencePrivate *account_priv =
- purple_account_presence_get_instance_private(PURPLE_ACCOUNT_PRESENCE(presence));
-
- G_OBJECT_CLASS(purple_account_presence_parent_class)->constructed(object);
-
- parent_priv->statuses = purple_protocol_get_statuses(account_priv->account, presence);
-}
-
-/* Class initializer function */
-static void purple_account_presence_class_init(PurpleAccountPresenceClass *klass)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
- PURPLE_PRESENCE_CLASS(klass)->update_idle = purple_account_presence_update_idle;
-
- obj_class->constructed = purple_account_presence_constructed;
-
- /* Setup properties */
- obj_class->get_property = purple_account_presence_get_property;
- obj_class->set_property = purple_account_presence_set_property;
-
- ap_properties[ACPRES_PROP_ACCOUNT] = g_param_spec_object("account",
- "Account",
- "The account that this presence is of.", PURPLE_TYPE_ACCOUNT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(obj_class, ACPRES_PROP_LAST,
- ap_properties);
-}
-
-static void
-purple_account_presence_init(PurpleAccountPresence *presence)
-{
-}
-
-PurpleAccountPresence *
-purple_account_presence_new(PurpleAccount *account)
-{
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
-
- return g_object_new(PURPLE_TYPE_ACCOUNT_PRESENCE,
- "account", account,
- NULL);
-}
-
-/**************************************************************************
-* PurpleBuddyPresence API
-**************************************************************************/
-static void
-purple_buddy_presence_update_idle(PurplePresence *presence, gboolean old_idle)
-{
- PurpleBuddy *buddy = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(presence));
- GDateTime *current_time = g_date_time_new_now_utc();
- PurpleAccount *account = purple_buddy_get_account(buddy);
- gboolean idle = purple_presence_is_idle(presence);
-
- if (!old_idle && idle)
- {
- if (purple_prefs_get_bool("/purple/logging/log_system"))
- {
- PurpleLog *log = purple_account_get_log(account, FALSE);
-
- if (log != NULL)
- {
- char *tmp, *tmp2;
- tmp = g_strdup_printf(_("%s became idle"),
- purple_buddy_get_alias(buddy));
- tmp2 = g_markup_escape_text(tmp, -1);
- g_free(tmp);
-
- purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
- purple_buddy_get_alias(buddy),
- current_time, tmp2);
- g_free(tmp2);
- }
- }
- }
- else if (old_idle && !idle)
- {
- if (purple_prefs_get_bool("/purple/logging/log_system"))
- {
- PurpleLog *log = purple_account_get_log(account, FALSE);
-
- if (log != NULL)
- {
- char *tmp, *tmp2;
- tmp = g_strdup_printf(_("%s became unidle"),
- purple_buddy_get_alias(buddy));
- tmp2 = g_markup_escape_text(tmp, -1);
- g_free(tmp);
-
- purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
- purple_buddy_get_alias(buddy),
- current_time, tmp2);
- g_free(tmp2);
- }
- }
- }
-
- if (old_idle != idle)
- purple_signal_emit(purple_blist_get_handle(), "buddy-idle-changed", buddy,
- old_idle, idle);
-
- purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
-
- /* Should this be done here? It'd perhaps make more sense to
- * connect to buddy-[un]idle signals and update from there
- */
-
- purple_blist_update_node(purple_blist_get_default(),
- PURPLE_BLIST_NODE(buddy));
-
- g_date_time_unref(current_time);
-}
-
-PurpleBuddy *
-purple_buddy_presence_get_buddy(PurpleBuddyPresence *presence)
-{
- PurpleBuddyPresencePrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_BUDDY_PRESENCE(presence), NULL);
-
- priv = purple_buddy_presence_get_instance_private(presence);
- return priv->buddy;
-}
-
-/**************************************************************************
- * GObject code for PurpleBuddyPresence
- **************************************************************************/
-
-/* Set method for GObject properties */
-static void
-purple_buddy_presence_set_property(GObject *obj, guint param_id, const GValue *value,
- GParamSpec *pspec)
-{
- PurpleBuddyPresence *buddy_presence = PURPLE_BUDDY_PRESENCE(obj);
- PurpleBuddyPresencePrivate *priv =
- purple_buddy_presence_get_instance_private(buddy_presence);
-
- switch (param_id) {
- case BUDPRES_PROP_BUDDY:
- priv->buddy = g_value_get_object(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* Get method for GObject properties */
-static void
-purple_buddy_presence_get_property(GObject *obj, guint param_id, GValue *value,
- GParamSpec *pspec)
-{
- PurpleBuddyPresence *buddy_presence = PURPLE_BUDDY_PRESENCE(obj);
-
- switch (param_id) {
- case BUDPRES_PROP_BUDDY:
- g_value_set_object(value,
- purple_buddy_presence_get_buddy(buddy_presence));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-/* Called when done constructing */
-static void
-purple_buddy_presence_constructed(GObject *object)
-{
- PurplePresence *presence = PURPLE_PRESENCE(object);
- PurplePresencePrivate *parent_priv = purple_presence_get_instance_private(presence);
- PurpleBuddyPresencePrivate *buddy_priv =
- purple_buddy_presence_get_instance_private(PURPLE_BUDDY_PRESENCE(presence));
- PurpleAccount *account;
-
- G_OBJECT_CLASS(purple_buddy_presence_parent_class)->constructed(object);
-
- account = purple_buddy_get_account(buddy_priv->buddy);
- parent_priv->statuses = purple_protocol_get_statuses(account, presence);
-}
-
-/* Class initializer function */
-static void purple_buddy_presence_class_init(PurpleBuddyPresenceClass *klass)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
- PURPLE_PRESENCE_CLASS(klass)->update_idle = purple_buddy_presence_update_idle;
-
- obj_class->constructed = purple_buddy_presence_constructed;
-
- /* Setup properties */
- obj_class->get_property = purple_buddy_presence_get_property;
- obj_class->set_property = purple_buddy_presence_set_property;
-
- bp_properties[BUDPRES_PROP_BUDDY] = g_param_spec_object("buddy", "Buddy",
- "The buddy that this presence is of.", PURPLE_TYPE_BUDDY,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(obj_class, BUDPRES_PROP_LAST,
- bp_properties);
-}
-
-static void
-purple_buddy_presence_init(PurpleBuddyPresence *presence)
-{
-}
-
-PurpleBuddyPresence *
-purple_buddy_presence_new(PurpleBuddy *buddy)
-{
- g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL);
-
- return g_object_new(PURPLE_TYPE_BUDDY_PRESENCE,
- "buddy", buddy,
- NULL);
-}
--- a/libpurple/presence.h Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/presence.h Mon Sep 21 20:15:51 2020 -0500
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
@@ -26,6 +25,7 @@
#ifndef PURPLE_PRESENCE_H
#define PURPLE_PRESENCE_H
+
/**
* SECTION:presence
* @section_id: libpurple-presence
@@ -52,9 +52,9 @@
* Note: When a presence is destroyed with the last g_object_unref(), all
* statuses added to this list will be destroyed along with the presence.
*/
+
typedef struct _PurplePresence PurplePresence;
-#include "account.h"
#include "buddylist.h"
#include "status.h"
@@ -66,23 +66,19 @@
* Base class for all #PurplePresence's
*/
struct _PurplePresenceClass {
- GObjectClass parent_class;
+ /*< private >*/
+ GObjectClass parent;
+ /*< public >*/
void (*update_idle)(PurplePresence *presence, gboolean old_idle);
+ GList *(*get_statuses)(PurplePresence *presence);
/*< private >*/
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
+ gpointer reserved[4];
};
G_BEGIN_DECLS
-/**************************************************************************/
-/* PurplePresence API */
-/**************************************************************************/
-
/**
* PURPLE_TYPE_PRESENCE:
*
@@ -95,14 +91,14 @@
*
* Returns: The #GType for the #PurplePresence object.
*/
-G_DECLARE_DERIVABLE_TYPE(PurplePresence, purple_presence, PURPLE,
- PRESENCE, GObject)
+G_DECLARE_DERIVABLE_TYPE(PurplePresence, purple_presence, PURPLE, PRESENCE,
+ GObject)
/**
* purple_presence_set_status_active:
- * @presence: The presence.
+ * @presence: The presence.
* @status_id: The ID of the status.
- * @active: The active state.
+ * @active: The active state.
*
* Sets the active state of a status in a presence.
*
@@ -110,8 +106,7 @@
* be set active, so if you wish to disable a status, set another
* non-independent status to active, or use purple_presence_switch_status().
*/
-void purple_presence_set_status_active(PurplePresence *presence,
- const char *status_id, gboolean active);
+void purple_presence_set_status_active(PurplePresence *presence, const gchar *status_id, gboolean active);
/**
* purple_presence_switch_status:
@@ -123,8 +118,7 @@
* This is similar to purple_presence_set_status_active(), except it won't
* activate independent statuses.
*/
-void purple_presence_switch_status(PurplePresence *presence,
- const char *status_id);
+void purple_presence_switch_status(PurplePresence *presence, const gchar *status_id);
/**
* purple_presence_set_idle:
@@ -137,8 +131,7 @@
*
* Sets the idle state and time on a presence.
*/
-void purple_presence_set_idle(PurplePresence *presence, gboolean idle,
- time_t idle_time);
+void purple_presence_set_idle(PurplePresence *presence, gboolean idle, time_t idle_time);
/**
* purple_presence_set_login_time:
@@ -168,8 +161,7 @@
*
* Returns: (transfer none): The status if found, or %NULL.
*/
-PurpleStatus *purple_presence_get_status(PurplePresence *presence,
- const char *status_id);
+PurpleStatus *purple_presence_get_status(PurplePresence *presence, const gchar *status_id);
/**
* purple_presence_get_active_status:
@@ -214,8 +206,7 @@
*
* Returns: TRUE if the status is active, or FALSE.
*/
-gboolean purple_presence_is_status_active(PurplePresence *presence,
- const char *status_id);
+gboolean purple_presence_is_status_active(PurplePresence *presence, const gchar *status_id);
/**
* purple_presence_is_status_primitive_active:
@@ -229,8 +220,7 @@
*
* Returns: TRUE if the status is active, or FALSE.
*/
-gboolean purple_presence_is_status_primitive_active(
- PurplePresence *presence, PurpleStatusPrimitive primitive);
+gboolean purple_presence_is_status_primitive_active(PurplePresence *presence, PurpleStatusPrimitive primitive);
/**
* purple_presence_is_idle:
@@ -264,102 +254,6 @@
*/
time_t purple_presence_get_login_time(PurplePresence *presence);
-/**************************************************************************/
-/* PurpleAccountPresence API */
-/**************************************************************************/
-
-/**
- * PURPLE_TYPE_ACCOUNT_PRESENCE:
- *
- * The standard _get_type macro for #PurpleAccountPresence.
- */
-#define PURPLE_TYPE_ACCOUNT_PRESENCE (purple_account_presence_get_type())
-
-/**
- * purple_account_presence_get_type:
- *
- * Returns: The #GType for the #PurpleAccountPresence object.
- */
-G_DECLARE_FINAL_TYPE(PurpleAccountPresence, purple_account_presence,
- PURPLE, ACCOUNT_PRESENCE, PurplePresence)
-
-/**
- * purple_account_presence_new:
- * @account: The account to associate with the presence.
- *
- * Creates a presence for an account.
- *
- * Returns: The new presence.
- *
- * Since: 3.0.0
- */
-PurpleAccountPresence *purple_account_presence_new(PurpleAccount *account);
-
-/**
- * purple_account_presence_get_account:
- * @presence: The presence.
- *
- * Returns an account presence's account.
- *
- * Returns: (transfer none): The presence's account.
- */
-PurpleAccount *purple_account_presence_get_account(PurpleAccountPresence *presence);
-
-/**************************************************************************/
-/* PurpleBuddyPresence API */
-/**************************************************************************/
-
-/**
- * PURPLE_TYPE_BUDDY_PRESENCE:
- *
- * The standard _get_type macro for #PurpleBuddyPresence.
- */
-#define PURPLE_TYPE_BUDDY_PRESENCE (purple_buddy_presence_get_type())
-
-/**
- * purple_buddy_presence_get_type:
- *
- * Returns: The #GType for the #PurpleBuddyPresence object.
- */
-G_DECLARE_FINAL_TYPE(PurpleBuddyPresence, purple_buddy_presence, PURPLE,
- BUDDY_PRESENCE, PurplePresence)
-
-/**
- * purple_buddy_presence_new:
- * @buddy: The buddy to associate with the presence.
- *
- * Creates a presence for a buddy.
- *
- * Returns: The new presence.
- *
- * Since: 3.0.0
- */
-PurpleBuddyPresence *purple_buddy_presence_new(PurpleBuddy *buddy);
-
-/**
- * purple_buddy_presence_get_buddy:
- * @presence: The presence.
- *
- * Returns the buddy presence's buddy.
- *
- * Returns: (transfer none): The presence's buddy.
- */
-PurpleBuddy *purple_buddy_presence_get_buddy(PurpleBuddyPresence *presence);
-
-/**
- * purple_buddy_presence_compare:
- * @buddy_presence1: The first presence.
- * @buddy_presence2: The second presence.
- *
- * Compares two buddy presences for availability.
- *
- * Returns: -1 if @buddy_presence1 is more available than @buddy_presence2.
- * 0 if @buddy_presence1 is equal to @buddy_presence2.
- * 1 if @buddy_presence1 is less available than @buddy_presence2.
- */
-gint purple_buddy_presence_compare(PurpleBuddyPresence *buddy_presence1,
- PurpleBuddyPresence *buddy_presence2);
-
G_END_DECLS
#endif /* PURPLE_PRESENCE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleaccountpresence.c Mon Sep 21 20:15:51 2020 -0500
@@ -0,0 +1,201 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "purpleaccountpresence.h"
+
+struct _PurpleAccountPresence {
+ PurplePresence parent;
+
+ PurpleAccount *account;
+};
+
+enum {
+ PROP_0,
+ PROP_ACCOUNT,
+ N_PROPERTIES
+};
+static GParamSpec *properties[N_PROPERTIES];
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_account_presence_set_account(PurpleAccountPresence *presence,
+ PurpleAccount *account)
+{
+ if(g_set_object(&presence->account, account)) {
+ g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_ACCOUNT]);
+ }
+}
+
+/******************************************************************************
+ * PurplePresence Implementation
+ *****************************************************************************/
+static void
+purple_account_presence_update_idle(PurplePresence *presence, gboolean old_idle)
+{
+ PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(presence);
+ PurpleConnection *gc = NULL;
+ PurpleProtocol *protocol = NULL;
+ gboolean idle = purple_presence_is_idle(presence);
+ time_t idle_time = purple_presence_get_idle_time(presence);
+ time_t current_time = time(NULL);
+
+ if(purple_prefs_get_bool("/purple/logging/log_system")) {
+ PurpleLog *log = purple_account_get_log(account_presence->account,
+ FALSE);
+
+ if(log != NULL) {
+ gchar *msg, *tmp;
+ GDateTime *dt;
+
+ if(idle) {
+ tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account_presence->account));
+ dt = g_date_time_new_from_unix_local(idle_time);
+ } else {
+ tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account_presence->account));
+ dt = g_date_time_new_now_utc();
+ }
+
+ msg = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
+ purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
+ purple_account_get_username(account_presence->account),
+ dt, msg);
+ g_date_time_unref(dt);
+ g_free(msg);
+ }
+ }
+
+ gc = purple_account_get_connection(account_presence->account);
+
+ if(PURPLE_CONNECTION_IS_CONNECTED(gc)) {
+ protocol = purple_connection_get_protocol(gc);
+ }
+
+ if(protocol) {
+ purple_protocol_server_iface_set_idle(protocol, gc, (idle ? (current_time - idle_time) : 0));
+ }
+}
+
+static GList *
+purple_account_presence_get_statuses(PurplePresence *presence) {
+ PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(presence);
+
+ return purple_protocol_get_statuses(account_presence->account, presence);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PurpleAccountPresence, purple_account_presence,
+ PURPLE_TYPE_PRESENCE)
+
+static void
+purple_account_presence_set_property(GObject *obj, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PurpleAccountPresence *presence = PURPLE_ACCOUNT_PRESENCE(obj);
+
+ switch (param_id) {
+ case PROP_ACCOUNT:
+ purple_account_presence_set_account(presence,
+ g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_account_presence_get_property(GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PurpleAccountPresence *presence = PURPLE_ACCOUNT_PRESENCE(obj);
+
+ switch (param_id) {
+ case PROP_ACCOUNT:
+ g_value_set_object(value,
+ purple_account_presence_get_account(presence));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_account_presence_finalize(GObject *obj) {
+ PurpleAccountPresence *presence = PURPLE_ACCOUNT_PRESENCE(obj);
+
+ g_clear_object(&presence->account);
+
+ G_OBJECT_CLASS(purple_account_presence_parent_class)->finalize(obj);
+}
+
+static void
+purple_account_presence_init(PurpleAccountPresence *presence) {
+}
+
+static void
+purple_account_presence_class_init(PurpleAccountPresenceClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+ PurplePresenceClass *presence_class = PURPLE_PRESENCE_CLASS(klass);
+
+ obj_class->get_property = purple_account_presence_get_property;
+ obj_class->set_property = purple_account_presence_set_property;
+ obj_class->finalize = purple_account_presence_finalize;
+
+ presence_class->update_idle = purple_account_presence_update_idle;
+ presence_class->get_statuses = purple_account_presence_get_statuses;
+
+ properties[PROP_ACCOUNT] = g_param_spec_object(
+ "account", "Account",
+ "The account for this presence.",
+ PURPLE_TYPE_ACCOUNT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+PurpleAccountPresence *
+purple_account_presence_new(PurpleAccount *account) {
+ g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
+
+ return g_object_new(
+ PURPLE_TYPE_ACCOUNT_PRESENCE,
+ "account", account,
+ NULL);
+}
+
+PurpleAccount *
+purple_account_presence_get_account(PurpleAccountPresence *presence)
+{
+ g_return_val_if_fail(PURPLE_IS_ACCOUNT_PRESENCE(presence), NULL);
+
+ return presence->account;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleaccountpresence.h Mon Sep 21 20:15:51 2020 -0500
@@ -0,0 +1,83 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_ACCOUNT_PRESENCE_H
+#define PURPLE_ACCOUNT_PRESENCE_H
+
+/**
+ * SECTION:purpleaccountpresence
+ * @section_id: libpurple-purpleaccountpresence
+ * @title: Account Presence API
+ *
+ * A #PurpleAccountPresence represent the #PurplePresence for a specific
+ * #PurpleAccount.
+ */
+
+#include "account.h"
+#include "presence.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PurpleAccountPresence:
+ *
+ * A presence for an account
+ */
+
+/**
+ * PURPLE_TYPE_ACCOUNT_PRESENCE:
+ *
+ * The standard _get_type macro for #PurpleAccountPresence.
+ */
+#define PURPLE_TYPE_ACCOUNT_PRESENCE (purple_account_presence_get_type())
+
+/**
+ * purple_account_presence_get_type:
+ *
+ * Returns: The #GType for the #PurpleAccountPresence object.
+ */
+G_DECLARE_FINAL_TYPE(PurpleAccountPresence, purple_account_presence, PURPLE,
+ ACCOUNT_PRESENCE, PurplePresence)
+
+/**
+ * purple_account_presence_new:
+ * @account: The account to associate with the presence.
+ *
+ * Creates a presence for an account.
+ *
+ * Returns: The new presence.
+ *
+ * Since: 3.0.0
+ */
+PurpleAccountPresence *purple_account_presence_new(PurpleAccount *account);
+
+/**
+ * purple_account_presence_get_account:
+ * @presence: The presence.
+ *
+ * Returns an account presence's account.
+ *
+ * Returns: (transfer none): The presence's account.
+ */
+PurpleAccount *purple_account_presence_get_account(PurpleAccountPresence *presence);
+
+G_END_DECLS
+
+#endif /* PURPLE_ACCOUNT_PRESENCE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purplebuddypresence.c Mon Sep 21 20:15:51 2020 -0500
@@ -0,0 +1,300 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "purplebuddypresence.h"
+
+#include "purpleprivate.h"
+
+struct _PurpleBuddyPresence {
+ PurplePresence parent;
+
+ PurpleBuddy *buddy;
+};
+
+enum {
+ PROP_0,
+ PROP_BUDDY,
+ N_PROPERTIES
+};
+static GParamSpec *properties[N_PROPERTIES];
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_buddy_presence_set_buddy(PurpleBuddyPresence *presence,
+ PurpleBuddy *buddy)
+{
+ if(g_set_object(&presence->buddy, buddy)) {
+ g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_BUDDY]);
+ }
+}
+
+static int
+purple_buddy_presence_compute_score(PurpleBuddyPresence *buddy_presence)
+{
+ GList *l;
+ int score = 0;
+ PurplePresence *presence = PURPLE_PRESENCE(buddy_presence);
+ PurpleBuddy *b = purple_buddy_presence_get_buddy(buddy_presence);
+ int *primitive_scores = _purple_statuses_get_primitive_scores();
+ int offline_score = purple_prefs_get_int("/purple/status/scores/offline_msg");
+ int idle_score = purple_prefs_get_int("/purple/status/scores/idle");
+
+ for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
+ PurpleStatus *status = (PurpleStatus *)l->data;
+ PurpleStatusType *type = purple_status_get_status_type(status);
+
+ if (purple_status_is_active(status)) {
+ score += primitive_scores[purple_status_type_get_primitive(type)];
+ if (!purple_status_is_online(status)) {
+ if (b && purple_account_supports_offline_message(purple_buddy_get_account(b), b))
+ score += offline_score;
+ }
+ }
+ }
+ score += purple_account_get_int(purple_buddy_get_account(b), "score", 0);
+ if (purple_presence_is_idle(presence))
+ score += idle_score;
+ return score;
+}
+
+gint
+purple_buddy_presence_compare(PurpleBuddyPresence *buddy_presence1,
+ PurpleBuddyPresence *buddy_presence2)
+{
+ PurplePresence *presence1 = PURPLE_PRESENCE(buddy_presence1);
+ PurplePresence *presence2 = PURPLE_PRESENCE(buddy_presence2);
+ time_t idle_time_1, idle_time_2;
+ int score1 = 0, score2 = 0;
+ int idle_time_score = purple_prefs_get_int("/purple/status/scores/idle_time");
+
+ if (presence1 == presence2)
+ return 0;
+ else if (presence1 == NULL)
+ return 1;
+ else if (presence2 == NULL)
+ return -1;
+
+ if (purple_presence_is_online(presence1) &&
+ !purple_presence_is_online(presence2))
+ return -1;
+ else if (purple_presence_is_online(presence2) &&
+ !purple_presence_is_online(presence1))
+ return 1;
+
+ /* Compute the score of the first set of statuses. */
+ score1 = purple_buddy_presence_compute_score(buddy_presence1);
+
+ /* Compute the score of the second set of statuses. */
+ score2 = purple_buddy_presence_compute_score(buddy_presence2);
+
+ idle_time_1 = time(NULL) - purple_presence_get_idle_time(presence1);
+ idle_time_2 = time(NULL) - purple_presence_get_idle_time(presence2);
+
+ if (idle_time_1 > idle_time_2)
+ score1 += idle_time_score;
+ else if (idle_time_1 < idle_time_2)
+ score2 += idle_time_score;
+
+ if (score1 < score2)
+ return 1;
+ else if (score1 > score2)
+ return -1;
+
+ return 0;
+}
+
+/******************************************************************************
+ * PurplePresence Implementation
+ *****************************************************************************/
+static void
+purple_buddy_presence_update_idle(PurplePresence *presence, gboolean old_idle)
+{
+ PurpleBuddy *buddy = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(presence));
+ GDateTime *current_time = g_date_time_new_now_utc();
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ gboolean idle = purple_presence_is_idle(presence);
+
+ if (!old_idle && idle)
+ {
+ if (purple_prefs_get_bool("/purple/logging/log_system"))
+ {
+ PurpleLog *log = purple_account_get_log(account, FALSE);
+
+ if (log != NULL)
+ {
+ char *tmp, *tmp2;
+ tmp = g_strdup_printf(_("%s became idle"),
+ purple_buddy_get_alias(buddy));
+ tmp2 = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
+
+ purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
+ purple_buddy_get_alias(buddy),
+ current_time, tmp2);
+ g_free(tmp2);
+ }
+ }
+ }
+ else if (old_idle && !idle)
+ {
+ if (purple_prefs_get_bool("/purple/logging/log_system"))
+ {
+ PurpleLog *log = purple_account_get_log(account, FALSE);
+
+ if (log != NULL)
+ {
+ char *tmp, *tmp2;
+ tmp = g_strdup_printf(_("%s became unidle"),
+ purple_buddy_get_alias(buddy));
+ tmp2 = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
+
+ purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
+ purple_buddy_get_alias(buddy),
+ current_time, tmp2);
+ g_free(tmp2);
+ }
+ }
+ }
+
+ if (old_idle != idle)
+ purple_signal_emit(purple_blist_get_handle(), "buddy-idle-changed", buddy,
+ old_idle, idle);
+
+ purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
+
+ /* Should this be done here? It'd perhaps make more sense to
+ * connect to buddy-[un]idle signals and update from there
+ */
+
+ purple_blist_update_node(purple_blist_get_default(),
+ PURPLE_BLIST_NODE(buddy));
+
+ g_date_time_unref(current_time);
+}
+
+static GList *
+purple_buddy_presence_get_statuses(PurplePresence *presence) {
+ PurpleAccount *account = NULL;
+ PurpleBuddyPresence *buddy_presence = NULL;
+
+ buddy_presence = PURPLE_BUDDY_PRESENCE(presence);
+ account = purple_buddy_get_account(buddy_presence->buddy);
+
+ return purple_protocol_get_statuses(account, presence);
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PurpleBuddyPresence, purple_buddy_presence, PURPLE_TYPE_PRESENCE)
+
+static void
+purple_buddy_presence_set_property(GObject *obj, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PurpleBuddyPresence *presence = PURPLE_BUDDY_PRESENCE(obj);
+
+ switch(param_id) {
+ case PROP_BUDDY:
+ purple_buddy_presence_set_buddy(presence,
+ g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_buddy_presence_get_property(GObject *obj, guint param_id, GValue *value,
+ GParamSpec *pspec)
+{
+ PurpleBuddyPresence *presence = PURPLE_BUDDY_PRESENCE(obj);
+
+ switch(param_id) {
+ case PROP_BUDDY:
+ g_value_set_object(value,
+ purple_buddy_presence_get_buddy(presence));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_buddy_presence_finalize(GObject *obj) {
+ PurpleBuddyPresence *presence = PURPLE_BUDDY_PRESENCE(obj);
+
+ g_clear_object(&presence->buddy);
+
+ G_OBJECT_CLASS(purple_buddy_presence_parent_class)->finalize(obj);
+}
+
+static void
+purple_buddy_presence_init(PurpleBuddyPresence *presence) {
+}
+
+static void
+purple_buddy_presence_class_init(PurpleBuddyPresenceClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+ PurplePresenceClass *presence_class = PURPLE_PRESENCE_CLASS(klass);
+
+ obj_class->get_property = purple_buddy_presence_get_property;
+ obj_class->set_property = purple_buddy_presence_set_property;
+ obj_class->finalize = purple_buddy_presence_finalize;
+
+ presence_class->update_idle = purple_buddy_presence_update_idle;
+ presence_class->get_statuses = purple_buddy_presence_get_statuses;
+
+ properties[PROP_BUDDY] = g_param_spec_object(
+ "buddy", "Buddy",
+ "The buddy for this presence.",
+ PURPLE_TYPE_BUDDY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+PurpleBuddyPresence *
+purple_buddy_presence_new(PurpleBuddy *buddy) {
+ g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL);
+
+ return g_object_new(
+ PURPLE_TYPE_BUDDY_PRESENCE,
+ "buddy", buddy,
+ NULL);
+}
+
+PurpleBuddy *
+purple_buddy_presence_get_buddy(PurpleBuddyPresence *presence) {
+ g_return_val_if_fail(PURPLE_IS_BUDDY_PRESENCE(presence), NULL);
+
+ return presence->buddy;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purplebuddypresence.h Mon Sep 21 20:15:51 2020 -0500
@@ -0,0 +1,97 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef PURPLE_BUDDY_PRESENCE_H
+#define PURPLE_BUDDY_PRESENCE_H
+
+/**
+ * SECTION:purplebuddypresence
+ * @section_id: libpurple-purplebuddypresence
+ * @title: Buddy Presence API
+ *
+ * A #PurpleBuddyPresence represent the #PurplePresence for a specific
+ * #PurpleBuddy.
+ */
+
+#include "buddylist.h"
+#include "presence.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PurpleBuddyPresence:
+ *
+ * A presence for a buddy
+ */
+
+/**
+ * PURPLE_TYPE_BUDDY_PRESENCE:
+ *
+ * The standard _get_type macro for #PurpleBuddyPresence.
+ */
+#define PURPLE_TYPE_BUDDY_PRESENCE (purple_buddy_presence_get_type())
+
+/**
+ * purple_buddy_presence_get_type:
+ *
+ * Returns: The #GType for the #PurpleBuddyPresence object.
+ */
+G_DECLARE_FINAL_TYPE(PurpleBuddyPresence, purple_buddy_presence, PURPLE,
+ BUDDY_PRESENCE, PurplePresence)
+
+/**
+ * purple_buddy_presence_new:
+ * @buddy: The buddy to associate with the presence.
+ *
+ * Creates a presence for a buddy.
+ *
+ * Returns: The new presence.
+ *
+ * Since: 3.0.0
+ */
+PurpleBuddyPresence *purple_buddy_presence_new(PurpleBuddy *buddy);
+
+/**
+ * purple_buddy_presence_get_buddy:
+ * @presence: The presence.
+ *
+ * Returns the buddy presence's buddy.
+ *
+ * Returns: (transfer none): The presence's buddy.
+ */
+PurpleBuddy *purple_buddy_presence_get_buddy(PurpleBuddyPresence *presence);
+
+/**
+ * purple_buddy_presence_compare:
+ * @buddy_presence1: The first presence.
+ * @buddy_presence2: The second presence.
+ *
+ * Compares two buddy presences for availability.
+ *
+ * Returns: -1 if @buddy_presence1 is more available than @buddy_presence2.
+ * 0 if @buddy_presence1 is equal to @buddy_presence2.
+ * 1 if @buddy_presence1 is less available than @buddy_presence2.
+ */
+gint purple_buddy_presence_compare(PurpleBuddyPresence *buddy_presence1,
+ PurpleBuddyPresence *buddy_presence2);
+
+G_END_DECLS
+
+#endif /* PURPLE_BUDDY_PRESENCE_H */
--- a/libpurple/status.c Wed Sep 16 02:04:11 2020 -0500
+++ b/libpurple/status.c Mon Sep 21 20:15:51 2020 -0500
@@ -29,6 +29,8 @@
#include "debug.h"
#include "notify.h"
#include "prefs.h"
+#include "purpleaccountpresence.h"
+#include "purplebuddypresence.h"
#include "status.h"
typedef struct _PurpleStatusPrivate PurpleStatusPrivate;
--- a/po/POTFILES.in Wed Sep 16 02:04:11 2020 -0500
+++ b/po/POTFILES.in Mon Sep 21 20:15:51 2020 -0500
@@ -266,7 +266,9 @@
libpurple/protocols/zephyr/ZWait4Not.c
libpurple/proxy.c
libpurple/purple-gio.c
+libpurple/purpleaccountpresence.c
libpurple/purpleattachment.c
+libpurple/purplebuddypresence.c
libpurple/purplechatuser.c
libpurple/purpleimconversation.c
libpurple/purpleprotocolim.c