--- a/libpurple/conversationtypes.c Mon Aug 10 19:59:56 2020 -0500
+++ b/libpurple/conversationtypes.c Thu Aug 13 18:29:17 2020 -0500
@@ -28,37 +28,6 @@
#include "purpleprivate.h"
-#define SEND_TYPED_TIMEOUT_SECONDS 5
-/**************************************************************************/
-/* PurpleIMConversation */
-/**************************************************************************/
- * Data specific to Instant Messages.
- PurpleIMTypingState typing_state; /* The current typing state. */
- guint typing_timeout; /* The typing timer handle. */
- time_t type_again; /* The type again time. */
- guint send_typed_timeout; /* The type again timer handle. */
- PurpleBuddyIcon *icon; /* The buddy icon. */
-} PurpleIMConversationPrivate;
-static GParamSpec *im_properties[IM_PROP_LAST];
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleIMConversation, purple_im_conversation,
- PURPLE_TYPE_CONVERSATION);
/**************************************************************************/
/* PurpleChatConversation */
/**************************************************************************/
@@ -149,434 +118,6 @@
/**************************************************************************
- **************************************************************************/
-reset_typing_cb(gpointer data)
- PurpleIMConversation *im = (PurpleIMConversation *)data;
- purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING);
- purple_im_conversation_stop_typing_timeout(im);
-send_typed_cb(gpointer data)
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(data);
- g_return_val_if_fail(im != NULL, FALSE);
- gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im));
- name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
- if (gc != NULL && name != NULL) {
- /* We set this to 1 so that PURPLE_IM_TYPING will be sent
- * if the Purple user types anything else.
- purple_im_conversation_set_type_again(im, 1);
- purple_serv_send_typing(gc, name, PURPLE_IM_TYPED);
- purple_debug(PURPLE_DEBUG_MISC, "conversationtypes", "typed...\n");
-purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- if (priv->icon != icon)
- purple_buddy_icon_unref(priv->icon);
- priv->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon));
- g_object_notify_by_pspec(G_OBJECT(im), im_properties[IM_PROP_ICON]);
- purple_conversation_update(PURPLE_CONVERSATION(im),
- PURPLE_CONVERSATION_UPDATE_ICON);
-purple_im_conversation_get_icon(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), NULL);
- priv = purple_im_conversation_get_instance_private(im);
-purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMTypingState state)
- PurpleIMConversationPrivate *priv = NULL;
- PurpleAccount *account;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
- account = purple_conversation_get_account(PURPLE_CONVERSATION(im));
- if (priv->typing_state != state)
- priv->typing_state = state;
- g_object_notify_by_pspec(G_OBJECT(im),
- im_properties[IM_PROP_TYPING_STATE]);
- purple_signal_emit(purple_conversations_get_handle(),
- "buddy-typing", account, name);
- purple_signal_emit(purple_conversations_get_handle(),
- "buddy-typed", account, name);
- case PURPLE_IM_NOT_TYPING:
- purple_signal_emit(purple_conversations_get_handle(),
- "buddy-typing-stopped", account, name);
- purple_im_conversation_update_typing(im);
-purple_im_conversation_get_typing_state(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0);
- priv = purple_im_conversation_get_instance_private(im);
- return priv->typing_state;
-purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- if (priv->typing_timeout > 0)
- purple_im_conversation_stop_typing_timeout(im);
- priv->typing_timeout = g_timeout_add_seconds(timeout, reset_typing_cb, im);
-purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- if (priv->typing_timeout == 0)
- g_source_remove(priv->typing_timeout);
- priv->typing_timeout = 0;
-purple_im_conversation_get_typing_timeout(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0);
- priv = purple_im_conversation_get_instance_private(im);
- return priv->typing_timeout;
-purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- priv->type_again = time(NULL) + val;
-purple_im_conversation_get_type_again(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0);
- priv = purple_im_conversation_get_instance_private(im);
- return priv->type_again;
-purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- priv->send_typed_timeout = g_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS,
-purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- priv = purple_im_conversation_get_instance_private(im);
- if (priv->send_typed_timeout == 0)
- g_source_remove(priv->send_typed_timeout);
- priv->send_typed_timeout = 0;
-purple_im_conversation_get_send_typed_timeout(PurpleIMConversation *im)
- PurpleIMConversationPrivate *priv = NULL;
- g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0);
- priv = purple_im_conversation_get_instance_private(im);
- return priv->send_typed_timeout;
-purple_im_conversation_update_typing(PurpleIMConversation *im)
- g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im));
- purple_conversation_update(PURPLE_CONVERSATION(im),
- PURPLE_CONVERSATION_UPDATE_TYPING);
-im_conversation_write_message(PurpleConversation *conv, PurpleMessage *msg)
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(conv);
- g_return_if_fail(im != NULL);
- g_return_if_fail(msg != NULL);
- is_recv = (purple_message_get_flags(msg) & PURPLE_MESSAGE_RECV);
- purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING);
- _purple_conversation_write_common(conv, msg);
-/**************************************************************************
- **************************************************************************/
-/* Set method for GObject properties */
-purple_im_conversation_set_property(GObject *obj, guint param_id, const GValue *value,
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj);
- case IM_PROP_TYPING_STATE:
- purple_im_conversation_set_typing_state(im, g_value_get_enum(value));
- purple_im_conversation_set_icon(im, g_value_get_pointer(value));
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-/* Get method for GObject properties */
-purple_im_conversation_get_property(GObject *obj, guint param_id, GValue *value,
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj);
- case IM_PROP_TYPING_STATE:
- g_value_set_enum(value, purple_im_conversation_get_typing_state(im));
- g_value_set_pointer(value, purple_im_conversation_get_icon(im));
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-/* GObject initialization function */
-static void purple_im_conversation_init(PurpleIMConversation *im)
-/* Called when done constructing */
-purple_im_conversation_constructed(GObject *object)
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object);
- PurpleAccount *account;
- G_OBJECT_CLASS(purple_im_conversation_parent_class)->
- if ((icon = purple_buddy_icons_find(account, name)))
- purple_im_conversation_set_icon(im, icon);
- /* purple_im_conversation_set_icon refs the icon. */
- purple_buddy_icon_unref(icon);
- if (purple_prefs_get_bool("/purple/logging/log_ims"))
- purple_conversation_set_logging(PURPLE_CONVERSATION(im), TRUE);
- g_object_unref(account);
-/* GObject dispose function */
-purple_im_conversation_dispose(GObject *object)
- PurpleIMConversationPrivate *priv =
- purple_im_conversation_get_instance_private(
- PURPLE_IM_CONVERSATION(object));
- purple_buddy_icon_unref(priv->icon);
- G_OBJECT_CLASS(purple_im_conversation_parent_class)->dispose(object);
-/* GObject finalize function */
-purple_im_conversation_finalize(GObject *object)
- PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object);
- PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im));
- PurpleProtocol *protocol = NULL;
- const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
- protocol = purple_connection_get_protocol(gc);
- if (purple_prefs_get_bool("/purple/conversations/im/send_typing"))
- purple_serv_send_typing(gc, name, PURPLE_IM_NOT_TYPING);
- purple_protocol_client_iface_convo_closed(protocol, gc, name);
- purple_im_conversation_stop_typing_timeout(im);
- purple_im_conversation_stop_send_typed_timeout(im);
- G_OBJECT_CLASS(purple_im_conversation_parent_class)->finalize(object);
-/* Class initializer function */
-static void purple_im_conversation_class_init(PurpleIMConversationClass *klass)
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
- PurpleConversationClass *conv_class = PURPLE_CONVERSATION_CLASS(klass);
- obj_class->dispose = purple_im_conversation_dispose;
- obj_class->finalize = purple_im_conversation_finalize;
- obj_class->constructed = purple_im_conversation_constructed;
- obj_class->get_property = purple_im_conversation_get_property;
- obj_class->set_property = purple_im_conversation_set_property;
- conv_class->write_message = im_conversation_write_message;
- im_properties[IM_PROP_TYPING_STATE] =
- g_param_spec_enum("typing-state", "Typing state",
- "Status of the user's typing of a message.",
- PURPLE_TYPE_IM_TYPING_STATE, PURPLE_IM_NOT_TYPING,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- im_properties[IM_PROP_ICON] = g_param_spec_pointer(
- "icon", "Buddy icon", "The buddy icon for the IM.",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(obj_class, IM_PROP_LAST, im_properties);
-purple_im_conversation_new(PurpleAccount *account, const char *name)
- PurpleIMConversation *im;
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
- g_return_val_if_fail(name != NULL, NULL);
- /* Check if this conversation already exists. */
- if ((im = purple_conversations_find_im_with_account(name, account)) != NULL)
- gc = purple_account_get_connection(account);
- g_return_val_if_fail(PURPLE_IS_CONNECTION(gc), NULL);
- im = g_object_new(PURPLE_TYPE_IM_CONVERSATION,
-/**************************************************************************
**************************************************************************/
--- a/libpurple/conversationtypes.h Mon Aug 10 19:59:56 2020 -0500
+++ b/libpurple/conversationtypes.h Thu Aug 13 18:29:17 2020 -0500
@@ -25,27 +25,18 @@
#ifndef PURPLE_CONVERSATION_TYPES_H
#define PURPLE_CONVERSATION_TYPES_H
* SECTION:conversationtypes
* @section_id: libpurple-conversationtypes
* @short_description: <filename>conversationtypes.h</filename>
- * @title: Chat and IM Conversation Objects
+ * @title: Chat Conversation Objects /**************************************************************************/
/**************************************************************************/
-#define PURPLE_TYPE_IM_CONVERSATION (purple_im_conversation_get_type())
-#define PURPLE_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversation))
-#define PURPLE_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass))
-#define PURPLE_IS_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_IM_CONVERSATION))
-#define PURPLE_IS_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_IM_CONVERSATION))
-#define PURPLE_IM_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass))
-typedef struct _PurpleIMConversation PurpleIMConversation;
-typedef struct _PurpleIMConversationClass PurpleIMConversationClass;
#define PURPLE_TYPE_CHAT_CONVERSATION (purple_chat_conversation_get_type())
#define PURPLE_CHAT_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversation))
#define PURPLE_CHAT_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationClass))
@@ -59,22 +50,6 @@
typedef struct _PurpleChatUser PurpleChatUser;
- * @PURPLE_IM_NOT_TYPING: Not typing.
- * @PURPLE_IM_TYPING: Currently typing.
- * @PURPLE_IM_TYPED: Stopped typing momentarily.
- * The typing state of a user.
- PURPLE_IM_NOT_TYPING = 0,
* @PURPLE_CHAT_USER_NONE: No flags
* @PURPLE_CHAT_USER_VOICE: Voiced user or "Participant"
@@ -98,37 +73,10 @@
+#include "purpleimconversation.h" #include "conversation.h"
/**************************************************************************/
-/* PurpleIMConversation */
-/**************************************************************************/
- * PurpleIMConversation:
- * Structure representing an IM conversation instance.
-struct _PurpleIMConversation
- PurpleConversation parent_object;
- * PurpleIMConversationClass:
- * Base class for all #PurpleIMConversation's
-struct _PurpleIMConversationClass {
- PurpleConversationClass parent_class;
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
-/**************************************************************************/
/* PurpleChatConversation */
/**************************************************************************/
@@ -159,160 +107,6 @@
/**************************************************************************/
-/* IM Conversation API */
-/**************************************************************************/
- * purple_im_conversation_get_type:
- * Returns: The #GType for the IMConversation object.
-GType purple_im_conversation_get_type(void);
- * purple_im_conversation_new:
- * @account: The account opening the conversation window on the purple
- * @name: Name of the buddy.
- * Creates a new IM conversation.
- * Returns: The new conversation.
-PurpleIMConversation *purple_im_conversation_new(PurpleAccount *account,
- * purple_im_conversation_set_icon:
- * @icon: The buddy icon.
- * Sets the IM's buddy icon.
- * This should only be called from within Purple. You probably want to
- * call purple_buddy_icon_set_data().
- * See purple_buddy_icon_set_data().
-void purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon);
- * purple_im_conversation_get_icon:
- * Returns the IM's buddy icon.
- * Returns: The buddy icon.
-PurpleBuddyIcon *purple_im_conversation_get_icon(PurpleIMConversation *im);
- * purple_im_conversation_set_typing_state:
- * @state: The typing state.
- * Sets the IM's typing state.
-void purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMTypingState state);
- * purple_im_conversation_get_typing_state:
- * Returns the IM's typing state.
- * Returns: The IM's typing state.
-PurpleIMTypingState purple_im_conversation_get_typing_state(PurpleIMConversation *im);
- * purple_im_conversation_start_typing_timeout:
- * @timeout: How long in seconds to wait before setting the typing state
- * to PURPLE_IM_NOT_TYPING.
- * Starts the IM's typing timeout.
-void purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout);
- * purple_im_conversation_stop_typing_timeout:
- * Stops the IM's typing timeout.
-void purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im);
- * purple_im_conversation_get_typing_timeout:
- * Returns the IM's typing timeout.
- * Returns: The timeout.
-guint purple_im_conversation_get_typing_timeout(PurpleIMConversation *im);
- * purple_im_conversation_set_type_again:
- * @val: The number of seconds to wait before allowing another
- * PURPLE_IM_TYPING message to be sent to the user. Or 0 to
- * not send another PURPLE_IM_TYPING message.
- * Sets the quiet-time when no PURPLE_IM_TYPING messages will be sent.
- * Few protocols need this (maybe only MSN). If the user is still
- * typing after this quiet-period, then another PURPLE_IM_TYPING message
-void purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val);
- * purple_im_conversation_get_type_again:
- * Returns the time after which another PURPLE_IM_TYPING message should be sent.
- * Returns: The time in seconds since the epoch. Or 0 if no additional
- * PURPLE_IM_TYPING message should be sent.
-time_t purple_im_conversation_get_type_again(PurpleIMConversation *im);
- * purple_im_conversation_start_send_typed_timeout:
- * Starts the IM's type again timeout.
-void purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im);
- * purple_im_conversation_stop_send_typed_timeout:
- * Stops the IM's type again timeout.
-void purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im);
- * purple_im_conversation_get_send_typed_timeout:
- * Returns the IM's type again timeout interval.
- * Returns: The type again timeout interval.
-guint purple_im_conversation_get_send_typed_timeout(PurpleIMConversation *im);
- * purple_im_conversation_update_typing:
- * Updates the visual typing notification for an IM conversation.
-void purple_im_conversation_update_typing(PurpleIMConversation *im);
-/**************************************************************************/
/* Chat Conversation API */
/**************************************************************************/
--- a/libpurple/meson.build Mon Aug 10 19:59:56 2020 -0500
+++ b/libpurple/meson.build Thu Aug 13 18:29:17 2020 -0500
@@ -49,6 +49,7 @@
'purpleaccountusersplit.c',
+ 'purpleimconversation.c', 'purpleprotocolfactory.c',
@@ -128,6 +129,7 @@
'purpleaccountusersplit.h',
+ 'purpleimconversation.h', 'purpleprotocolfactory.h',
@@ -209,6 +211,7 @@
+ 'purpleimconversation.h', --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleimconversation.c Thu Aug 13 18:29:17 2020 -0500
@@ -0,0 +1,425 @@
+ * 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 + * 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 <libpurple/purpleimconversation.h> +#include <libpurple/enums.h> +#include <libpurple/purpleprivate.h> +struct _PurpleIMConversation { + PurpleConversation parent; + PurpleIMTypingState typing_state; + guint send_typed_timeout; +static GParamSpec *properties[N_PROPERTIES]; +#define SEND_TYPED_TIMEOUT_SECONDS 5 +/****************************************************************************** + *****************************************************************************/ +purple_im_conversation_reset_typing_cb(gpointer data) + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(data); + purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING); + purple_im_conversation_stop_typing_timeout(im); +purple_im_conversation_send_typed_cb(gpointer data) + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(data); + PurpleConnection *pc = NULL; + g_return_val_if_fail(im != NULL, FALSE); + pc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); + name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + if(pc != NULL && name != NULL) { + /* We set this to 1 so that PURPLE_IM_TYPING will be sent if the Purple + * user types anything else. + purple_im_conversation_set_type_again(im, 1); + purple_serv_send_typing(pc, name, PURPLE_IM_TYPED); + purple_debug(PURPLE_DEBUG_MISC, "purple-im-conversation", "typed...\n"); +/****************************************************************************** + * PurpleConversation Implementation + *****************************************************************************/ +im_conversation_write_message(PurpleConversation *conv, PurpleMessage *msg) { + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(conv); + gboolean is_recv = FALSE; + g_return_if_fail(im != NULL); + g_return_if_fail(msg != NULL); + is_recv = (purple_message_get_flags(msg) & PURPLE_MESSAGE_RECV); + purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING); + _purple_conversation_write_common(conv, msg); +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +G_DEFINE_TYPE(PurpleIMConversation, purple_im_conversation, + PURPLE_TYPE_CONVERSATION); +purple_im_conversation_get_property(GObject *obj, guint param_id, GValue *value, + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + case PROP_TYPING_STATE: + g_value_set_enum(value, + purple_im_conversation_get_typing_state(im)); + g_value_set_pointer(value, purple_im_conversation_get_icon(im)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_im_conversation_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + case PROP_TYPING_STATE: + purple_im_conversation_set_typing_state(im, + g_value_get_enum(value)); + purple_im_conversation_set_icon(im, g_value_get_pointer(value)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_im_conversation_init(PurpleIMConversation *im) { +purple_im_conversation_constructed(GObject *object) { + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); + PurpleAccount *account = NULL; + PurpleBuddyIcon *icon = NULL; + G_OBJECT_CLASS(purple_im_conversation_parent_class)->constructed(object); + if((icon = purple_buddy_icons_find(account, name))) { + purple_im_conversation_set_icon(im, icon); + /* purple_im_conversation_set_icon refs the icon. */ + purple_buddy_icon_unref(icon); + if(purple_prefs_get_bool("/purple/logging/log_ims")) { + purple_conversation_set_logging(PURPLE_CONVERSATION(im), TRUE); + g_object_unref(account); +purple_im_conversation_dispose(GObject *obj) { + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + g_clear_pointer(&im->icon, purple_buddy_icon_unref); + G_OBJECT_CLASS(purple_im_conversation_parent_class)->dispose(obj); +purple_im_conversation_finalize(GObject *obj) { + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + PurpleConnection *pc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); + PurpleProtocol *protocol = NULL; + const gchar *name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + protocol = purple_connection_get_protocol(pc); + if(purple_prefs_get_bool("/purple/conversations/im/send_typing")) { + purple_serv_send_typing(pc, name, PURPLE_IM_NOT_TYPING); + purple_protocol_client_iface_convo_closed(protocol, pc, name); + purple_im_conversation_stop_typing_timeout(im); + purple_im_conversation_stop_send_typed_timeout(im); + G_OBJECT_CLASS(purple_im_conversation_parent_class)->finalize(obj); +purple_im_conversation_class_init(PurpleIMConversationClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleConversationClass *conv_class = PURPLE_CONVERSATION_CLASS(klass); + obj_class->get_property = purple_im_conversation_get_property; + obj_class->set_property = purple_im_conversation_set_property; + obj_class->dispose = purple_im_conversation_dispose; + obj_class->finalize = purple_im_conversation_finalize; + obj_class->constructed = purple_im_conversation_constructed; + conv_class->write_message = im_conversation_write_message; + properties[PROP_TYPING_STATE] = g_param_spec_enum( + "typing-state", "Typing state", + "Status of the user's typing of a message.", + PURPLE_TYPE_IM_TYPING_STATE, PURPLE_IM_NOT_TYPING, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_ICON] = g_param_spec_pointer( + "icon", "Buddy icon", "The buddy icon for the IM.", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +/****************************************************************************** + *****************************************************************************/ +purple_im_conversation_new(PurpleAccount *account, const char *name) + PurpleIMConversation *im = NULL; + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); + g_return_val_if_fail(name != NULL, NULL); + /* Check if this conversation already exists. */ + if((im = purple_conversations_find_im_with_account(name, account)) != NULL) { + return g_object_ref(im); + im = g_object_new(PURPLE_TYPE_IM_CONVERSATION, +purple_im_conversation_set_icon(PurpleIMConversation *im, + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + purple_buddy_icon_unref(im->icon); + im->icon = (icon == NULL) ? NULL : purple_buddy_icon_ref(icon); + g_object_notify_by_pspec(G_OBJECT(im), properties[PROP_ICON]); + purple_conversation_update(PURPLE_CONVERSATION(im), + PURPLE_CONVERSATION_UPDATE_ICON); +purple_im_conversation_get_icon(PurpleIMConversation *im) { + g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), NULL); +purple_im_conversation_set_typing_state(PurpleIMConversation *im, + PurpleIMTypingState state) + PurpleAccount *account = NULL; + const gchar *name = NULL; + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + account = purple_conversation_get_account(PURPLE_CONVERSATION(im)); + if(im->typing_state != state) { + im->typing_state = state; + g_object_notify_by_pspec(G_OBJECT(im), properties[PROP_TYPING_STATE]); + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing", account, name); + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typed", account, name); + case PURPLE_IM_NOT_TYPING: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing-stopped", account, name); + purple_im_conversation_update_typing(im); +purple_im_conversation_get_typing_state(PurpleIMConversation *im) { + g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0); + return im->typing_state; +purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + if(im->typing_timeout > 0) { + purple_im_conversation_stop_typing_timeout(im); + g_timeout_add_seconds(timeout, purple_im_conversation_reset_typing_cb, +purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im) { + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + if(im->typing_timeout == 0) { + g_source_remove(im->typing_timeout); + im->typing_timeout = 0; +purple_im_conversation_get_typing_timeout(PurpleIMConversation *im) { + g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0); + return im->typing_timeout; +purple_im_conversation_set_type_again(PurpleIMConversation *im, guint val) { + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + im->type_again = time(NULL) + val; +purple_im_conversation_get_type_again(PurpleIMConversation *im) { + g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0); +purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im) { + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + purple_im_conversation_stop_send_typed_timeout(im); + im->send_typed_timeout = + g_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, + purple_im_conversation_send_typed_cb, im); +purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im) { + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + if(im->send_typed_timeout == 0) { + g_source_remove(im->send_typed_timeout); + im->send_typed_timeout = 0; +purple_im_conversation_get_send_typed_timeout(PurpleIMConversation *im) { + g_return_val_if_fail(PURPLE_IS_IM_CONVERSATION(im), 0); + return im->send_typed_timeout; +purple_im_conversation_update_typing(PurpleIMConversation *im) { + g_return_if_fail(PURPLE_IS_IM_CONVERSATION(im)); + purple_conversation_update(PURPLE_CONVERSATION(im), + PURPLE_CONVERSATION_UPDATE_TYPING); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleimconversation.h Thu Aug 13 18:29:17 2020 -0500
@@ -0,0 +1,237 @@
+ * 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 + * 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/>. +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <purple.h> may be included directly" +#ifndef PURPLE_IM_CONVERSATION_H +#define PURPLE_IM_CONVERSATION_H +#include <glib-object.h> + * SECTION:imconversation + * @section_id: libpurple-imconversation + * @title: IM Conversation Objects + * @PURPLE_IM_NOT_TYPING: Not typing. + * @PURPLE_IM_TYPING: Currently typing. + * @PURPLE_IM_TYPED: Stopped typing momentarily. + * The typing state of a user. + PURPLE_IM_NOT_TYPING = 0, +#define PURPLE_TYPE_IM_CONVERSATION (purple_im_conversation_get_type()) +#define PURPLE_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversation)) +#define PURPLE_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass)) +#define PURPLE_IS_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IS_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IM_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass)) +typedef struct _PurpleIMConversation PurpleIMConversation; +typedef struct _PurpleIMConversationClass PurpleIMConversationClass; +#include <conversation.h> + * PurpleIMConversation: + * Structure representing an IM conversation instance. + * PurpleIMConversationClass: + * Base class for all #PurpleIMConversation's +struct _PurpleIMConversationClass { + PurpleConversationClass parent_class; + gpointer _purple_reserved[4]; + * purple_im_conversation_get_type: + * Returns: The #GType for the IMConversation object. +GType purple_im_conversation_get_type(void); + * purple_im_conversation_new: + * @account: The account opening the conversation window on the purple user's + * @name: Name of the buddy. + * Creates a new IM conversation. + * Returns: The new conversation. +PurpleIMConversation *purple_im_conversation_new(PurpleAccount *account, const gchar *name); + * purple_im_conversation_set_icon: + * @icon: The buddy icon. + * Sets the IM's buddy icon. + * This should only be called from within Purple. You probably want to + * call purple_buddy_icon_set_data(). + * See purple_buddy_icon_set_data(). +void purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon); + * purple_im_conversation_get_icon: + * Returns the IM's buddy icon. + * Returns: (transfer none): The buddy icon. +PurpleBuddyIcon *purple_im_conversation_get_icon(PurpleIMConversation *im); + * purple_im_conversation_set_typing_state: + * @state: The typing state. + * Sets the IM's typing state. +void purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMTypingState state); + * purple_im_conversation_get_typing_state: + * Returns the IM's typing state. + * Returns: The IM's typing state. +PurpleIMTypingState purple_im_conversation_get_typing_state(PurpleIMConversation *im); + * purple_im_conversation_start_typing_timeout: + * @timeout: How long in seconds to wait before setting the typing state to + * PURPLE_IM_NOT_TYPING. + * Starts the IM's typing timeout. +void purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout); + * purple_im_conversation_stop_typing_timeout: + * Stops the IM's typing timeout. +void purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im); + * purple_im_conversation_get_typing_timeout: + * Returns the IM's typing timeout. + * Returns: The timeout. +guint purple_im_conversation_get_typing_timeout(PurpleIMConversation *im); + * purple_im_conversation_set_type_again: + * @val: The number of seconds to wait before allowing another #PURPLE_IM_TYPING + * message to be sent to the user. Or 0 to not send another + * #PURPLE_IM_TYPING message. + * Sets the quiet-time when no #PURPLE_IM_TYPING messages will be sent. + * Few protocols need this (maybe only MSN). If the user is still + * typing after this quiet-period, then another #PURPLE_IM_TYPING message +void purple_im_conversation_set_type_again(PurpleIMConversation *im, guint val); + * purple_im_conversation_get_type_again: + * Returns the time after which another PURPLE_IM_TYPING message should be sent. + * Returns: The time in seconds since the epoch. Or 0 if no additional + * PURPLE_IM_TYPING message should be sent. +time_t purple_im_conversation_get_type_again(PurpleIMConversation *im); + * purple_im_conversation_start_send_typed_timeout: + * Starts the IM's type again timeout. +void purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im); + * purple_im_conversation_stop_send_typed_timeout: + * Stops the IM's type again timeout. +void purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im); + * purple_im_conversation_get_send_typed_timeout: + * Returns the IM's type again timeout interval. + * Returns: The type again timeout interval. +guint purple_im_conversation_get_send_typed_timeout(PurpleIMConversation *im); + * purple_im_conversation_update_typing: + * Updates the visual typing notification for an IM conversation. +void purple_im_conversation_update_typing(PurpleIMConversation *im); +#endif /* PURPLE_IM_CONVERSATION_H */