summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2021-01-26 01:46:21 -0600
committerGary Kramlich <grim@reaperworld.com>2021-01-26 01:46:21 -0600
commit3bc249a88a166e42e6d7a0c35f5d4fcbe7d8bcbe (patch)
treee5990bf596b7a7b54ea82a1fb93cfa9367bd067e
parentaeb0d813a903f8ed6707e2ba75ed93e147ba4077 (diff)
downloadpidgin-3bc249a88a166e42e6d7a0c35f5d4fcbe7d8bcbe.tar.gz
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/
-rw-r--r--ChangeLog.API1
-rw-r--r--doc/reference/libpurple/libpurple-docs.xml1
-rw-r--r--libpurple/core.c4
-rw-r--r--libpurple/meson.build2
-rw-r--r--libpurple/protocols.c163
-rw-r--r--libpurple/protocols.h29
-rw-r--r--libpurple/purpleprivate.h14
-rw-r--r--libpurple/purpleprotocolmanager.c229
-rw-r--r--libpurple/purpleprotocolmanager.h160
-rw-r--r--pidgin/pidginprotocolstore.c34
-rw-r--r--po/POTFILES.in1
11 files changed, 455 insertions, 183 deletions
diff --git a/ChangeLog.API b/ChangeLog.API
index cf877d7579..6c05204952 100644
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -49,7 +49,6 @@ version 3.0.0 (??/??/????):
* purple_protocols_remove
* purple_protocols_find
* purple_protocols_get_all
- * purple_protocols_get_handle
* purple_protocols_init
* purple_protocols_uninit
* purple_request_certificate
diff --git a/doc/reference/libpurple/libpurple-docs.xml b/doc/reference/libpurple/libpurple-docs.xml
index d9f6b124ba..1050d451c0 100644
--- a/doc/reference/libpurple/libpurple-docs.xml
+++ b/doc/reference/libpurple/libpurple-docs.xml
@@ -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" />
diff --git a/libpurple/core.c b/libpurple/core.c
index 0641eb1683..a9c5ef7d51 100644
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -147,7 +147,7 @@ purple_core_init(const char *ui)
}
purple_cmds_init();
- purple_protocols_init();
+ purple_protocol_manager_startup();
purple_credential_manager_startup(); /* before accounts */
@@ -246,7 +246,7 @@ purple_core_quit(void)
purple_prefs_uninit();
purple_plugins_uninit();
- purple_protocols_uninit();
+ purple_protocol_manager_shutdown();
purple_cmds_uninit();
purple_log_uninit();
diff --git a/libpurple/meson.build b/libpurple/meson.build
index 887b6f03a6..7bf0c6e8ec 100644
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -63,6 +63,7 @@ purple_coresources = [
'purpleprotocolclient.c',
'purpleprotocolfactory.c',
'purpleprotocolim.c',
+ 'purpleprotocolmanager.c',
'purpleprotocolmedia.c',
'purpleprotocolprivacy.c',
'purpleprotocolserver.c',
@@ -154,6 +155,7 @@ purple_coreheaders = [
'purpleprotocolfactory.h',
'purpleprotocolim.h',
'purpleprotocolmedia.h',
+ 'purpleprotocolmanager.h',
'purpleprotocolprivacy.h',
'purpleprotocolserver.h',
'purpleuiinfo.h',
diff --git a/libpurple/protocols.c b/libpurple/protocols.c
index 8ca18a0187..292588814d 100644
--- a/libpurple/protocols.c
+++ b/libpurple/protocols.c
@@ -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 @@ do_protocol_change_account_status(PurpleAccount *account,
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 @@ do_protocol_change_account_status(PurpleAccount *account,
*/
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 @@ purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type
{
PurpleAttentionType *attn;
PurpleProtocol *protocol;
+ PurpleProtocolManager *manager;
PurpleIMConversation *im;
PurpleBuddy *buddy;
const char *alias;
@@ -379,7 +382,9 @@ purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type
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 @@ purple_protocol_got_media_caps(PurpleAccount *account, const char *name)
/**************************************************************************
* 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);
-
- if (aname) {
- if (bname)
- return strcmp(aname, bname);
- else
- return -1;
- } else {
- if (bname)
- return 1;
- else
- return 0;
- }
-}
+#define PURPLE_PROTOCOLS_DOMAIN (g_quark_from_static_string("protocols"))
PurpleProtocol *
-purple_protocols_find(const char *id)
-{
- g_return_val_if_fail(protocols != NULL && id != NULL, NULL);
+purple_protocols_find(const char *id) {
+ PurpleProtocolManager *manager = purple_protocol_manager_get_default();
- return g_hash_table_lookup(protocols, id);
+ return purple_protocol_manager_find(manager, 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 @@ purple_protocols_add(GType protocol_type, GError **error)
}
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);
- 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);
+ manager = purple_protocol_manager_get_default();
+ if(!purple_protocol_manager_register(manager, protocol, error)) {
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();
-
- 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);
-}
+purple_protocols_get_all(void) {
+ PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-void *
-purple_protocols_get_handle(void)
-{
- static int handle;
-
- return &handle;
+ return purple_protocol_manager_get_all(manager);
}
-
-void
-purple_protocols_uninit(void)
-{
- g_hash_table_destroy(protocols);
-}
-
diff --git a/libpurple/protocols.h b/libpurple/protocols.h
index f3c9b74dbe..442b4aff9b 100644
--- a/libpurple/protocols.h
+++ b/libpurple/protocols.h
@@ -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 @@ gboolean purple_protocols_remove(PurpleProtocol *protocol, GError **error);
*/
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 */
diff --git a/libpurple/purpleprivate.h b/libpurple/purpleprivate.h
index 04d87970de..84e142bc41 100644
--- a/libpurple/purpleprivate.h
+++ b/libpurple/purpleprivate.h
@@ -220,6 +220,20 @@ void purple_credential_manager_startup(void);
*/
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 */
diff --git a/libpurple/purpleprotocolmanager.c b/libpurple/purpleprotocolmanager.c
new file mode 100644
index 0000000000..3b6e5af287
--- /dev/null
+++ b/libpurple/purpleprotocolmanager.c
@@ -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);
+}
diff --git a/libpurple/purpleprotocolmanager.h b/libpurple/purpleprotocolmanager.h
new file mode 100644
index 0000000000..5180a8fa83
--- /dev/null
+++ b/libpurple/purpleprotocolmanager.h
@@ -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 */
diff --git a/pidgin/pidginprotocolstore.c b/pidgin/pidginprotocolstore.c
index 71f0fe3947..9edb374ff0 100644
--- a/pidgin/pidginprotocolstore.c
+++ b/pidgin/pidginprotocolstore.c
@@ -65,8 +65,13 @@ pidgin_protocol_store_add_protocol_helper(gpointer data, gpointer user_data) {
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 @@ pidgin_protocol_store_remove_protocol(PidginProtocolStore *store,
* 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 @@ G_DEFINE_TYPE(PidginProtocolStore, pidgin_protocol_store, GTK_TYPE_LIST_STORE)
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_init(PidginProtocolStore *store) {
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
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b9037b7952..465fd8cead 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -261,6 +261,7 @@ libpurple/purpleprotocolclient.c
libpurple/purpleprotocolfactory.c
libpurple/purpleprotocolim.c
libpurple/purpleprotocolmedia.c
+libpurple/purpleprotocolmanager.c
libpurple/purpleprotocolprivacy.c
libpurple/purpleprotocolserver.c
libpurple/purpleuiinfo.c