libpurple/purpleprotocolmanager.c

changeset 40735
cc0679f47fd9
child 40787
8a5a20a49e9b
equal deleted inserted replaced
40734:c792b39da167 40735:cc0679f47fd9
1 /*
2 * Purple - Internet Messaging Library
3 * Copyright (C) Pidgin Developers <devel@pidgin.im>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17 */
18
19 #include <glib/gi18n-lib.h>
20
21 #include "purpleprotocolmanager.h"
22 #include "purpleprivate.h"
23
24 enum {
25 SIG_REGISTERED,
26 SIG_UNREGISTERED,
27 N_SIGNALS,
28 };
29 static guint signals[N_SIGNALS] = {0, };
30
31 typedef struct {
32 GHashTable *protocols;
33 } PurpleProtocolManagerPrivate;
34
35 G_DEFINE_TYPE_WITH_PRIVATE(PurpleProtocolManager, purple_protocol_manager,
36 G_TYPE_OBJECT);
37
38 static PurpleProtocolManager *default_manager = NULL;
39
40 /******************************************************************************
41 * GObject Implementation
42 *****************************************************************************/
43 static void
44 purple_protocol_manager_finalize(GObject *obj) {
45 PurpleProtocolManager *manager = NULL;
46 PurpleProtocolManagerPrivate *priv = NULL;
47
48 manager = PURPLE_PROTOCOL_MANAGER(obj);
49 priv = purple_protocol_manager_get_instance_private(manager);
50
51 g_clear_pointer(&priv->protocols, g_hash_table_destroy);
52
53 G_OBJECT_CLASS(purple_protocol_manager_parent_class)->finalize(obj);
54 }
55
56 static void
57 purple_protocol_manager_init(PurpleProtocolManager *manager) {
58 PurpleProtocolManagerPrivate *priv = NULL;
59
60 priv = purple_protocol_manager_get_instance_private(manager);
61
62 priv->protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
63 g_object_unref);
64 }
65
66 static void
67 purple_protocol_manager_class_init(PurpleProtocolManagerClass *klass) {
68 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
69
70 obj_class->finalize = purple_protocol_manager_finalize;
71
72 /**
73 * PurpleProtocolManager::protocol-registered:
74 * @manager: The #PurpleProtocolManager instance.
75 * @protocol: The #PurpleProtocol that was registered.
76 *
77 * Emitted after @protocol has been registered in @manager.
78 *
79 * Since: 3.0.0
80 */
81 signals[SIG_REGISTERED] = g_signal_new(
82 "registered",
83 G_OBJECT_CLASS_TYPE(klass),
84 G_SIGNAL_RUN_LAST,
85 G_STRUCT_OFFSET(PurpleProtocolManagerClass, registered),
86 NULL,
87 NULL,
88 NULL,
89 G_TYPE_NONE,
90 1,
91 PURPLE_TYPE_PROTOCOL);
92
93 /**
94 * PurpleProtocolManager::protocol-unregistered:
95 * @manager: The #PurpleProtocolManager instance.
96 * @protocol: The #PurpleProtocol that was unregistered.
97 *
98 * Emitted after @protocol has been unregistered from @manager.
99 *
100 * Since: 3.0.0
101 */
102 signals[SIG_UNREGISTERED] = g_signal_new(
103 "unregistered",
104 G_OBJECT_CLASS_TYPE(klass),
105 G_SIGNAL_RUN_LAST,
106 G_STRUCT_OFFSET(PurpleProtocolManagerClass, unregistered),
107 NULL,
108 NULL,
109 NULL,
110 G_TYPE_NONE,
111 1,
112 PURPLE_TYPE_PROTOCOL);
113 }
114
115 /******************************************************************************
116 * Private API
117 *****************************************************************************/
118 void
119 purple_protocol_manager_startup(void) {
120 if(default_manager == NULL) {
121 default_manager = g_object_new(PURPLE_TYPE_PROTOCOL_MANAGER, NULL);
122 }
123 }
124
125 void
126 purple_protocol_manager_shutdown(void) {
127 g_clear_object(&default_manager);
128 }
129
130 /******************************************************************************
131 * Public API
132 *****************************************************************************/
133 PurpleProtocolManager *
134 purple_protocol_manager_get_default(void) {
135 return default_manager;
136 }
137
138 gboolean
139 purple_protocol_manager_register(PurpleProtocolManager *manager,
140 PurpleProtocol *protocol, GError **error)
141 {
142 PurpleProtocolManagerPrivate *priv = NULL;
143 const gchar *id = NULL;
144
145 g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), FALSE);
146 g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
147
148 priv = purple_protocol_manager_get_instance_private(manager);
149
150 id = purple_protocol_get_id(protocol);
151 if(g_hash_table_lookup(priv->protocols, id) != NULL) {
152 g_set_error(error, PURPLE_PROTOCOL_MANAGER_DOMAIN, 0,
153 _("protocol %s is already registered"), id);
154
155 return FALSE;
156 }
157
158 g_hash_table_insert(priv->protocols, g_strdup(id), g_object_ref(protocol));
159
160 g_signal_emit(G_OBJECT(manager), signals[SIG_REGISTERED], 0, protocol);
161
162 return TRUE;
163 }
164
165 gboolean
166 purple_protocol_manager_unregister(PurpleProtocolManager *manager,
167 PurpleProtocol *protocol, GError **error)
168 {
169 PurpleProtocolManagerPrivate *priv = NULL;
170 const gchar *id = NULL;
171 gboolean ret = FALSE;
172
173 g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), FALSE);
174 g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
175
176 /* We need to hold a reference on the protocol as typically we will be
177 * holding the only reference on the protocol when this is called and we
178 * will need to pass it to the signal emission after it's removed from the
179 * hash table that'll unref it.
180 */
181 g_object_ref(G_OBJECT(protocol));
182
183 priv = purple_protocol_manager_get_instance_private(manager);
184 id = purple_protocol_get_id(protocol);
185
186 if(g_hash_table_remove(priv->protocols, id)) {
187 g_signal_emit(G_OBJECT(manager), signals[SIG_UNREGISTERED], 0,
188 protocol);
189
190 ret = TRUE;
191 } else {
192 g_set_error(error, PURPLE_PROTOCOL_MANAGER_DOMAIN, 0,
193 _("protocol %s is not registered"), id);
194
195 ret = FALSE;
196 }
197
198 g_object_unref(G_OBJECT(protocol));
199
200 return ret;
201 }
202
203 PurpleProtocol *
204 purple_protocol_manager_find(PurpleProtocolManager *manager, const gchar *id) {
205 PurpleProtocolManagerPrivate *priv = NULL;
206 gpointer value = NULL;
207
208 g_return_val_if_fail(PURPLE_PROTOCOL_MANAGER(manager), NULL);
209
210 priv = purple_protocol_manager_get_instance_private(manager);
211
212 value = g_hash_table_lookup(priv->protocols, id);
213 if(value == NULL) {
214 return NULL;
215 }
216
217 return PURPLE_PROTOCOL(value);
218 }
219
220 GList *
221 purple_protocol_manager_get_all(PurpleProtocolManager *manager) {
222 PurpleProtocolManagerPrivate *priv = NULL;
223
224 g_return_val_if_fail(PURPLE_IS_PROTOCOL_MANAGER(manager), NULL);
225
226 priv = purple_protocol_manager_get_instance_private(manager);
227
228 return g_hash_table_get_values(priv->protocols);
229 }

mercurial