| |
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 } |