diff options
author | Gary Kramlich <grim@reaperworld.com> | 2021-01-26 01:46:21 -0600 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2021-01-26 01:46:21 -0600 |
commit | 3bc249a88a166e42e6d7a0c35f5d4fcbe7d8bcbe (patch) | |
tree | e5990bf596b7a7b54ea82a1fb93cfa9367bd067e | |
parent | aeb0d813a903f8ed6707e2ba75ed93e147ba4077 (diff) | |
download | pidgin-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.API | 1 | ||||
-rw-r--r-- | doc/reference/libpurple/libpurple-docs.xml | 1 | ||||
-rw-r--r-- | libpurple/core.c | 4 | ||||
-rw-r--r-- | libpurple/meson.build | 2 | ||||
-rw-r--r-- | libpurple/protocols.c | 163 | ||||
-rw-r--r-- | libpurple/protocols.h | 29 | ||||
-rw-r--r-- | libpurple/purpleprivate.h | 14 | ||||
-rw-r--r-- | libpurple/purpleprotocolmanager.c | 229 | ||||
-rw-r--r-- | libpurple/purpleprotocolmanager.h | 160 | ||||
-rw-r--r-- | pidgin/pidginprotocolstore.c | 34 | ||||
-rw-r--r-- | po/POTFILES.in | 1 |
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 |