pidgin/pidgin

Create a new PurpleProtocolManager

2021-01-26, Gary Kramlich
cc0679f47fd9
Parents c792b39da167
Children c2b876aa4c03
Create a new PurpleProtocolManager

* Created new PurpleProtocolManager object.
* Updated the existing purple_protocols_* api to call the new api in the
manager.

Testing Done:
* Ran unit tests
* Ran libpurple-doc
* Ran pidgin locally with bonjour, xmpp, and irc.

Bugs closed: PIDGIN-17462

Reviewed at https://reviews.imfreedom.org/r/437/
--- a/ChangeLog.API Tue Jan 26 01:28:00 2021 -0600
+++ b/ChangeLog.API Tue Jan 26 01:46:21 2021 -0600
@@ -49,7 +49,6 @@
* purple_protocols_remove
* purple_protocols_find
* purple_protocols_get_all
- * purple_protocols_get_handle
* purple_protocols_init
* purple_protocols_uninit
* purple_request_certificate
--- a/doc/reference/libpurple/libpurple-docs.xml Tue Jan 26 01:28:00 2021 -0600
+++ b/doc/reference/libpurple/libpurple-docs.xml Tue Jan 26 01:46:21 2021 -0600
@@ -85,6 +85,7 @@
<xi:include href="xml/purpleprotocolclient.xml" />
<xi:include href="xml/purpleprotocolfactory.xml" />
<xi:include href="xml/purpleprotocolim.xml" />
+ <xi:include href="xml/purpleprotocolmanager.xml" />
<xi:include href="xml/purpleprotocolmedia.xml" />
<xi:include href="xml/purpleprotocolprivacy.xml" />
<xi:include href="xml/purpleprotocolserver.xml" />
--- a/libpurple/core.c Tue Jan 26 01:28:00 2021 -0600
+++ b/libpurple/core.c Tue Jan 26 01:46:21 2021 -0600
@@ -147,7 +147,7 @@
}
purple_cmds_init();
- purple_protocols_init();
+ purple_protocol_manager_startup();
purple_credential_manager_startup(); /* before accounts */
@@ -246,7 +246,7 @@
purple_prefs_uninit();
purple_plugins_uninit();
- purple_protocols_uninit();
+ purple_protocol_manager_shutdown();
purple_cmds_uninit();
purple_log_uninit();
--- a/libpurple/meson.build Tue Jan 26 01:28:00 2021 -0600
+++ b/libpurple/meson.build Tue Jan 26 01:46:21 2021 -0600
@@ -63,6 +63,7 @@
'purpleprotocolclient.c',
'purpleprotocolfactory.c',
'purpleprotocolim.c',
+ 'purpleprotocolmanager.c',
'purpleprotocolmedia.c',
'purpleprotocolprivacy.c',
'purpleprotocolserver.c',
@@ -154,6 +155,7 @@
'purpleprotocolfactory.h',
'purpleprotocolim.h',
'purpleprotocolmedia.h',
+ 'purpleprotocolmanager.h',
'purpleprotocolprivacy.h',
'purpleprotocolserver.h',
'purpleuiinfo.h',
--- a/libpurple/protocols.c Tue Jan 26 01:28:00 2021 -0600
+++ b/libpurple/protocols.c Tue Jan 26 01:46:21 2021 -0600
@@ -32,13 +32,12 @@
#include "purpleaccountoption.h"
#include "purplecredentialmanager.h"
#include "purpleprotocolattention.h"
+#include "purpleprotocolmanager.h"
#include "purpleprotocolmedia.h"
#include "purpleprotocolserver.h"
#include "request.h"
#include "util.h"
-static GHashTable *protocols = NULL;
-
/**************************************************************************
* GBoxed code for PurpleProtocolChatEntry
**************************************************************************/
@@ -273,6 +272,7 @@
PurpleStatus *old_status, PurpleStatus *new_status)
{
PurpleProtocol *protocol;
+ PurpleProtocolManager *manager;
if (purple_status_is_online(new_status) &&
purple_account_is_disconnected(account) &&
@@ -307,7 +307,9 @@
*/
return;
- protocol = purple_protocols_find(purple_account_get_protocol_id(account));
+ manager = purple_protocol_manager_get_default();
+ protocol = purple_protocol_manager_find(manager,
+ purple_account_get_protocol_id(account));
if (protocol == NULL)
return;
@@ -371,6 +373,7 @@
{
PurpleAttentionType *attn;
PurpleProtocol *protocol;
+ PurpleProtocolManager *manager;
PurpleIMConversation *im;
PurpleBuddy *buddy;
const char *alias;
@@ -379,7 +382,9 @@
g_return_if_fail(gc != NULL);
g_return_if_fail(who != NULL);
- protocol = purple_protocols_find(purple_account_get_protocol_id(purple_connection_get_account(gc)));
+ manager = purple_protocol_manager_get_default();
+ protocol = purple_protocol_manager_find(manager,
+ purple_account_get_protocol_id(purple_connection_get_account(gc)));
g_return_if_fail(PURPLE_IS_PROTOCOL_ATTENTION(protocol));
attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code);
@@ -564,41 +569,19 @@
/**************************************************************************
* Protocols API
**************************************************************************/
-/*
- * Negative if a before b, 0 if equal, positive if a after b.
- */
-static gint
-compare_protocol(PurpleProtocol *a, PurpleProtocol *b)
-{
- const gchar *aname = purple_protocol_get_name(a);
- const gchar *bname = purple_protocol_get_name(b);
+#define PURPLE_PROTOCOLS_DOMAIN (g_quark_from_static_string("protocols"))
- if (aname) {
- if (bname)
- return strcmp(aname, bname);
- else
- return -1;
- } else {
- if (bname)
- return 1;
- else
- return 0;
- }
+PurpleProtocol *
+purple_protocols_find(const char *id) {
+ PurpleProtocolManager *manager = purple_protocol_manager_get_default();
+
+ return purple_protocol_manager_find(manager, id);
}
PurpleProtocol *
-purple_protocols_find(const char *id)
-{
- g_return_val_if_fail(protocols != NULL && id != NULL, NULL);
-
- return g_hash_table_lookup(protocols, id);
-}
-
-PurpleProtocol *
-purple_protocols_add(GType protocol_type, GError **error)
-{
- PurpleProtocol *protocol;
- PurpleProtocolClass *klass;
+purple_protocols_add(GType protocol_type, GError **error) {
+ PurpleProtocol *protocol = NULL;
+ PurpleProtocolManager *manager = NULL;
if (protocol_type == G_TYPE_INVALID) {
g_set_error_literal(error, PURPLE_PROTOCOLS_DOMAIN, 0,
@@ -619,121 +602,29 @@
}
protocol = g_object_new(protocol_type, NULL);
- if (!protocol) {
- g_set_error_literal(error, PURPLE_PROTOCOLS_DOMAIN, 0,
- _("Could not create protocol instance"));
- return NULL;
- }
- if (!purple_protocol_get_id(protocol)) {
- g_set_error_literal(error, PURPLE_PROTOCOLS_DOMAIN, 0,
- _("Protocol does not provide an ID"));
-
- g_object_unref(protocol);
- return NULL;
- }
-
- if (purple_protocols_find(purple_protocol_get_id(protocol))) {
- g_set_error(error, PURPLE_PROTOCOLS_DOMAIN, 0,
- _("A protocol with the ID %s is already added."),
- purple_protocol_get_id(protocol));
-
- g_object_unref(protocol);
+ manager = purple_protocol_manager_get_default();
+ if(!purple_protocol_manager_register(manager, protocol, error)) {
return NULL;
}
- /* Make sure the protocol implements the required functions */
- klass = PURPLE_PROTOCOL_GET_CLASS(protocol);
-
- if (!klass->login || !klass->close ||
- !klass->status_types || !klass->list_icon )
- {
- g_set_error(error, PURPLE_PROTOCOLS_DOMAIN, 0,
- _("Protocol %s does not implement all the functions in "
- "PurpleProtocolClass"), purple_protocol_get_id(protocol));
-
- g_object_unref(protocol);
- return NULL;
- }
-
- g_hash_table_insert(protocols, g_strdup(purple_protocol_get_id(protocol)),
- protocol);
-
- purple_debug_info("protocols", "Added protocol %s\n",
- purple_protocol_get_id(protocol));
-
- purple_signal_emit(purple_protocols_get_handle(), "protocol-added",
- protocol);
return protocol;
}
-gboolean purple_protocols_remove(PurpleProtocol *protocol, GError **error)
-{
+gboolean
+purple_protocols_remove(PurpleProtocol *protocol, GError **error) {
+ PurpleProtocolManager *manager;
+
g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
g_return_val_if_fail(purple_protocol_get_id(protocol) != NULL, FALSE);
- if (purple_protocols_find(purple_protocol_get_id(protocol)) == NULL) {
- g_set_error(error, PURPLE_PROTOCOLS_DOMAIN, 0,
- _("Protocol %s is not added."),
- purple_protocol_get_id(protocol));
-
- return FALSE;
- }
-
- purple_debug_info("protocols", "Removing protocol %s\n",
- purple_protocol_get_id(protocol));
-
- purple_signal_emit(purple_protocols_get_handle(), "protocol-removed",
- protocol);
-
- g_hash_table_remove(protocols, purple_protocol_get_id(protocol));
- return TRUE;
+ manager = purple_protocol_manager_get_default();
+ return purple_protocol_manager_unregister(manager, protocol, error);
}
GList *
-purple_protocols_get_all(void)
-{
- GList *ret = NULL;
- PurpleProtocol *protocol;
- GHashTableIter iter;
-
- g_hash_table_iter_init(&iter, protocols);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&protocol))
- ret = g_list_insert_sorted(ret, protocol, (GCompareFunc)compare_protocol);
-
- return ret;
-}
-
-/**************************************************************************
- * Protocols Subsystem API
- **************************************************************************/
-void
-purple_protocols_init(void)
-{
- void *handle = purple_protocols_get_handle();
+purple_protocols_get_all(void) {
+ PurpleProtocolManager *manager = purple_protocol_manager_get_default();
- protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- g_object_unref);
-
- purple_signal_register(handle, "protocol-added",
- purple_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, PURPLE_TYPE_PROTOCOL);
- purple_signal_register(handle, "protocol-removed",
- purple_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, PURPLE_TYPE_PROTOCOL);
+ return purple_protocol_manager_get_all(manager);
}
-
-void *
-purple_protocols_get_handle(void)
-{
- static int handle;
-
- return &handle;
-}
-
-void
-purple_protocols_uninit(void)
-{
- g_hash_table_destroy(protocols);
-}
-
--- a/libpurple/protocols.h Tue Jan 26 01:28:00 2021 -0600
+++ b/libpurple/protocols.h Tue Jan 26 01:46:21 2021 -0600
@@ -33,8 +33,6 @@
* @see_also: <link linkend="chapter-signals-protocol">Protocol signals</link>
*/
-#define PURPLE_PROTOCOLS_DOMAIN (g_quark_from_static_string("protocols"))
-
/**************************************************************************/
/* Basic Protocol Information */
/**************************************************************************/
@@ -419,33 +417,6 @@
*/
GList *purple_protocols_get_all(void);
-/**************************************************************************/
-/* Protocols Subsytem API */
-/**************************************************************************/
-
-/**
- * purple_protocols_init:
- *
- * Initializes the protocols subsystem.
- */
-void purple_protocols_init(void);
-
-/**
- * purple_protocols_get_handle:
- *
- * Returns the protocols subsystem handle.
- *
- * Returns: The protocols subsystem handle.
- */
-void *purple_protocols_get_handle(void);
-
-/**
- * purple_protocols_uninit:
- *
- * Uninitializes the protocols subsystem.
- */
-void purple_protocols_uninit(void);
-
G_END_DECLS
#endif /* PURPLE_PROTOCOLS_H */
--- a/libpurple/purpleprivate.h Tue Jan 26 01:28:00 2021 -0600
+++ b/libpurple/purpleprivate.h Tue Jan 26 01:46:21 2021 -0600
@@ -220,6 +220,20 @@
*/
void purple_credential_manager_shutdown(void);
+/**
+ * purple_protocol_manager_start:
+ *
+ * Starts up the protocol manager by creating the default instance.
+ */
+void purple_protocol_manager_startup(void);
+
+/**
+ * purple_protocol_manager_shutdown:
+ *
+ * Shutdowns down the protocol manager by destroying the default instance.
+ */
+void purple_protocol_manager_shutdown(void);
+
G_END_DECLS
#endif /* PURPLE_PRIVATE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleprotocolmanager.c Tue Jan 26 01:46:21 2021 -0600
@@ -0,0 +1,229 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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 "purpleprotocolmanager.h"
+#include "purpleprivate.h"
+
+enum {
+ SIG_REGISTERED,
+ SIG_UNREGISTERED,
+ N_SIGNALS,
+};
+static guint signals[N_SIGNALS] = {0, };
+
+typedef struct {
+ GHashTable *protocols;
+} PurpleProtocolManagerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleProtocolManager, purple_protocol_manager,
+ G_TYPE_OBJECT);
+
+static PurpleProtocolManager *default_manager = NULL;
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+purple_protocol_manager_finalize(GObject *obj) {
+ PurpleProtocolManager *manager = NULL;
+ PurpleProtocolManagerPrivate *priv = NULL;
+
+ manager = PURPLE_PROTOCOL_MANAGER(obj);
+ priv = purple_protocol_manager_get_instance_private(manager);
+
+ g_clear_pointer(&priv->protocols, g_hash_table_destroy);
+
+ G_OBJECT_CLASS(purple_protocol_manager_parent_class)->finalize(obj);
+}
+
+static void
+purple_protocol_manager_init(PurpleProtocolManager *manager) {
+ PurpleProtocolManagerPrivate *priv = NULL;
+
+ priv = purple_protocol_manager_get_instance_private(manager);
+
+ priv->protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ g_object_unref);
+}
+
+static void
+purple_protocol_manager_class_init(PurpleProtocolManagerClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->finalize = purple_protocol_manager_finalize;
+
+ /**
+ * PurpleProtocolManager::protocol-registered:
+ * @manager: The #PurpleProtocolManager instance.
+ * @protocol: The #PurpleProtocol that was registered.
+ *
+ * Emitted after @protocol has been registered in @manager.
+ *
+ * Since: 3.0.0
+ */
+ signals[SIG_REGISTERED] = g_signal_new(
+ "registered",
+ G_OBJECT_CLASS_TYPE(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(PurpleProtocolManagerClass, registered),
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ PURPLE_TYPE_PROTOCOL);
+
+ /**
+ * PurpleProtocolManager::protocol-unregistered:
+ * @manager: The #PurpleProtocolManager instance.
+ * @protocol: The #PurpleProtocol that was unregistered.
+ *
+ * Emitted after @protocol has been unregistered from @manager.
+ *
+ * Since: 3.0.0
+ */
+ signals[SIG_UNREGISTERED] = g_signal_new(
+ "unregistered",
+ G_OBJECT_CLASS_TYPE(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(PurpleProtocolManagerClass, unregistered),
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ PURPLE_TYPE_PROTOCOL);
+}
+
+/******************************************************************************
+ * Private API
+ *****************************************************************************/
+void
+purple_protocol_manager_startup(void) {
+ if(default_manager == NULL) {
+ default_manager = g_object_new(PURPLE_TYPE_PROTOCOL_MANAGER, NULL);
+ }
+}
+
+void
+purple_protocol_manager_shutdown(void) {
+ g_clear_object(&default_manager);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+PurpleProtocolManager *
+purple_protocol_manager_get_default(void) {
+ return default_manager;
+}
+
+gboolean
+purple_protocol_manager_register(PurpleProtocolManager *manager,
+ PurpleProtocol *protocol, GError **error)
+{
+ PurpleProtocolManagerPrivate *priv = NULL;
+ const gchar *id = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), FALSE);
+ g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
+
+ priv = purple_protocol_manager_get_instance_private(manager);
+
+ id = purple_protocol_get_id(protocol);
+ if(g_hash_table_lookup(priv->protocols, id) != NULL) {
+ g_set_error(error, PURPLE_PROTOCOL_MANAGER_DOMAIN, 0,
+ _("protocol %s is already registered"), id);
+
+ return FALSE;
+ }
+
+ g_hash_table_insert(priv->protocols, g_strdup(id), g_object_ref(protocol));
+
+ g_signal_emit(G_OBJECT(manager), signals[SIG_REGISTERED], 0, protocol);
+
+ return TRUE;
+}
+
+gboolean
+purple_protocol_manager_unregister(PurpleProtocolManager *manager,
+ PurpleProtocol *protocol, GError **error)
+{
+ PurpleProtocolManagerPrivate *priv = NULL;
+ const gchar *id = NULL;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), FALSE);
+ g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
+
+ /* We need to hold a reference on the protocol as typically we will be
+ * holding the only reference on the protocol when this is called and we
+ * will need to pass it to the signal emission after it's removed from the
+ * hash table that'll unref it.
+ */
+ g_object_ref(G_OBJECT(protocol));
+
+ priv = purple_protocol_manager_get_instance_private(manager);
+ id = purple_protocol_get_id(protocol);
+
+ if(g_hash_table_remove(priv->protocols, id)) {
+ g_signal_emit(G_OBJECT(manager), signals[SIG_UNREGISTERED], 0,
+ protocol);
+
+ ret = TRUE;
+ } else {
+ g_set_error(error, PURPLE_PROTOCOL_MANAGER_DOMAIN, 0,
+ _("protocol %s is not registered"), id);
+
+ ret = FALSE;
+ }
+
+ g_object_unref(G_OBJECT(protocol));
+
+ return ret;
+}
+
+PurpleProtocol *
+purple_protocol_manager_find(PurpleProtocolManager *manager, const gchar *id) {
+ PurpleProtocolManagerPrivate *priv = NULL;
+ gpointer value = NULL;
+
+ g_return_val_if_fail(PURPLE_PROTOCOL_MANAGER(manager), NULL);
+
+ priv = purple_protocol_manager_get_instance_private(manager);
+
+ value = g_hash_table_lookup(priv->protocols, id);
+ if(value == NULL) {
+ return NULL;
+ }
+
+ return PURPLE_PROTOCOL(value);
+}
+
+GList *
+purple_protocol_manager_get_all(PurpleProtocolManager *manager) {
+ PurpleProtocolManagerPrivate *priv = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), NULL);
+
+ priv = purple_protocol_manager_get_instance_private(manager);
+
+ return g_hash_table_get_values(priv->protocols);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleprotocolmanager.h Tue Jan 26 01:46:21 2021 -0600
@@ -0,0 +1,160 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * 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 <pidgin.h> may be included directly"
+#endif
+
+#ifndef PURPLE_PROTOCOL_MANAGER_H
+#define PURPLE_PROTOCOL_MANAGER_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "protocol.h"
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:purpleprotocolmanager
+ * @section_id: libpurple-purpleprotocolmanager
+ * @title: Purple Protocol Manager
+ *
+ * #PurpleProtocolManager keeps track of all protocols and emits signals when
+ * protocols are registered and unregistered.
+ */
+
+/**
+ * PURPLE_PROTOCOL_MANAGER_DOMAIN:
+ *
+ * A #GError domain for errors from #PurpleProtocolManager.
+ *
+ * Since: 3.0.0
+ */
+#define PURPLE_PROTOCOL_MANAGER_DOMAIN (g_quark_from_static_string("purple-protocol-manager"))
+
+/**
+ * PURPLE_TYPE_PROTOCOL_MANAGER:
+ *
+ * The standard _get_type macro for #PurpleProtocolManager.
+ */
+#define PURPLE_TYPE_PROTOCOL_MANAGER (purple_protocol_manager_get_type())
+G_DECLARE_DERIVABLE_TYPE(PurpleProtocolManager, purple_protocol_manager,
+ PURPLE, PROTOCOL_MANAGER, GObject)
+
+/**
+ * PurpleProtocolManager:
+ *
+ * An opaque data structure that manages protocols.
+ *
+ * Since: 3.0.0
+ */
+
+/**
+ * PurpleProtocolManagerClass:
+ * @registered: The default signal handler for when a protocol is registered.
+ * @unregistered: The default signal handler for when a protocol is
+ * unregistered.
+ *
+ * The class structure for #PurpleProtocolManager.
+ *
+ * Since: 3.0.0
+ */
+struct _PurpleProtocolManagerClass {
+ /*< private >*/
+ GObjectClass parent;
+
+ /*< public >*/
+ void (*registered)(PurpleProtocolManager *manager, PurpleProtocol *protocol);
+ void (*unregistered)(PurpleProtocolManager *manager, PurpleProtocol *protocol);
+
+ /*< private >*/
+ gpointer reserved[4];
+};
+
+/**
+ * purple_protocol_manager_get_default:
+ *
+ * Gets the default #PurpleProtocolManager instance.
+ *
+ * Returns: (transfer none): The default #PurpleProtocolManager instance.
+ *
+ * Since: 3.0.0
+ */
+PurpleProtocolManager *purple_protocol_manager_get_default(void);
+
+/**
+ * purple_protocol_manager_register:
+ * @manager: The #PurpleProtocolManager instance.
+ * @protocol: The #PurpleProtocol to register.
+ * @error: (out) (optional) (nullable): A return address for a #GError.
+ *
+ * Registers @protocol with @manager.
+ *
+ * Returns: %TRUE if @protocol was successfully registered with @manager,
+ * %FALSE otherwise.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_protocol_manager_register(PurpleProtocolManager *manager, PurpleProtocol *protocol, GError **error);
+
+/**
+ * purple_protocol_manager_unregister:
+ * @manager: The #PurpleProtocolManager instance.
+ * @protocol: The #PurpleProtocol to unregister.
+ * @error: (out) (optional) (nullable): A return address for a #GError.
+ *
+ * Unregisters @protocol from @manager.
+ *
+ * Returns: %TRUE if @protocol was successfully unregistered from @manager,
+ * %FALSE otherwise.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_protocol_manager_unregister(PurpleProtocolManager *manager, PurpleProtocol *protocol, GError **error);
+
+/**
+ * purple_protocol_manager_find:
+ * @manager: The #PurpleProtocolManager instance.
+ * @id: The id of the #PurpleProtocol to find.
+ *
+ * Gets the #PurpleProtocol identified by @id if found, otherwise %NULL.
+ *
+ * Returns: (transfer none): The #PurpleProtocol identified by @id or %NULL.
+ *
+ * Since: 3.0.0
+ */
+PurpleProtocol *purple_protocol_manager_find(PurpleProtocolManager *manager, const gchar *id);
+
+/**
+ * purple_protocol_manager_get_all:
+ * @manager: The #PurpleProtocolManager instance.
+ *
+ * Gets a sorted list of all #PurpleProtocols that are currently registered in
+ * @manager.
+ *
+ * Returns: (transfer container) (element-type PurpleProtocol): The list
+ * containing all of the #PurpleProtocols registered with @manager.
+ *
+ * Since: 3.0.0
+ */
+GList *purple_protocol_manager_get_all(PurpleProtocolManager *manager);
+
+G_END_DECLS
+
+#endif /* PURPLE_PROTOCOL_MANAGER_H */
--- a/pidgin/pidginprotocolstore.c Tue Jan 26 01:28:00 2021 -0600
+++ b/pidgin/pidginprotocolstore.c Tue Jan 26 01:46:21 2021 -0600
@@ -65,8 +65,13 @@
static void
pidgin_protocol_store_add_protocols(PidginProtocolStore *store) {
- g_list_foreach(purple_protocols_get_all(),
- pidgin_protocol_store_add_protocol_helper, store);
+ PurpleProtocolManager *manager = purple_protocol_manager_get_default();
+ GList *protocols = NULL;
+
+ protocols = purple_protocol_manager_get_all(manager);
+ g_list_foreach(protocols, pidgin_protocol_store_add_protocol_helper,
+ store);
+ g_list_free(protocols);
}
static void
@@ -107,17 +112,18 @@
* Callbacks
*****************************************************************************/
static void
-pidgin_protocol_store_protocol_added_cb(PurpleProtocol *protocol,
- gpointer data)
+pidgin_protocol_store_registered_cb(PurpleProtocolManager *manager,
+ PurpleProtocol *protocol, gpointer data)
{
pidgin_protocol_store_add_protocol(PIDGIN_PROTOCOL_STORE(data), protocol);
}
static void
-pidgin_protocol_store_protocol_removed_cb(PurpleProtocol *protocol,
- gpointer data)
+pidgin_protocol_store_unregistered_cb(PurpleProtocolManager *manager,
+ PurpleProtocol *protocol, gpointer data)
{
- pidgin_protocol_store_remove_protocol(PIDGIN_PROTOCOL_STORE(data), protocol);
+ pidgin_protocol_store_remove_protocol(PIDGIN_PROTOCOL_STORE(data),
+ protocol);
}
/******************************************************************************
@@ -127,7 +133,7 @@
static void
pidgin_protocol_store_init(PidginProtocolStore *store) {
- gpointer protocols_handle = NULL;
+ PurpleProtocolManager *manager = NULL;
GType types[PIDGIN_PROTOCOL_STORE_N_COLUMNS] = {
PURPLE_TYPE_PROTOCOL,
G_TYPE_STRING,
@@ -144,13 +150,11 @@
pidgin_protocol_store_add_protocols(store);
/* add the signal handlers to dynamically add/remove protocols */
- protocols_handle = purple_protocols_get_handle();
- purple_signal_connect(protocols_handle, "protocol-added", store,
- G_CALLBACK(pidgin_protocol_store_protocol_added_cb),
- store);
- purple_signal_connect(protocols_handle, "protocol-removed", store,
- G_CALLBACK(pidgin_protocol_store_protocol_removed_cb),
- store);
+ manager = purple_protocol_manager_get_default();
+ g_signal_connect(G_OBJECT(manager), "registered",
+ G_CALLBACK(pidgin_protocol_store_registered_cb), store);
+ g_signal_connect(G_OBJECT(manager), "unregistered",
+ G_CALLBACK(pidgin_protocol_store_unregistered_cb), store);
}
static void
--- a/po/POTFILES.in Tue Jan 26 01:28:00 2021 -0600
+++ b/po/POTFILES.in Tue Jan 26 01:46:21 2021 -0600
@@ -261,6 +261,7 @@
libpurple/purpleprotocolfactory.c
libpurple/purpleprotocolim.c
libpurple/purpleprotocolmedia.c
+libpurple/purpleprotocolmanager.c
libpurple/purpleprotocolprivacy.c
libpurple/purpleprotocolserver.c
libpurple/purpleuiinfo.c