Merged in default (pull request #594)
[pidgin-git.git] / libpurple / core.c
blobef5513b89586d539015529f2c22af3c96b21ef2a
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include "internal.h"
22 #include "cmds.h"
23 #include "connection.h"
24 #include "conversation.h"
25 #include "core.h"
26 #include "debug.h"
27 #include "xfer.h"
28 #include "glibcompat.h"
29 #include "http.h"
30 #include "idle.h"
31 #include "image-store.h"
32 #include "keyring.h"
33 #include "message.h"
34 #include "network.h"
35 #include "notify.h"
36 #include "plugins.h"
37 #include "pounce.h"
38 #include "prefs.h"
39 #include "proxy.h"
40 #include "savedstatuses.h"
41 #include "signals.h"
42 #include "smiley-custom.h"
43 #include "smiley-parser.h"
44 #include "smiley-theme.h"
45 #include "sound.h"
46 #include "sound-theme-loader.h"
47 #include "sslconn.h"
48 #include "status.h"
49 #include "stun.h"
50 #include "theme-manager.h"
51 #include "util.h"
53 struct PurpleCore
55 char *ui;
57 void *reserved;
60 static PurpleCoreUiOps *_ops = NULL;
61 static PurpleCore *_core = NULL;
63 static void
64 purple_core_print_version(void)
66 GHashTable *ui_info = purple_core_get_ui_info();
67 const gchar *ui_name;
68 const gchar *ui_version;
69 gchar *ui_full_name = NULL;
71 ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
72 ui_version = ui_info ? g_hash_table_lookup(ui_info, "version") : NULL;
74 if (ui_name) {
75 if (ui_version) {
76 ui_full_name = g_strdup_printf("%s %s", ui_name, ui_version);
77 } else {
78 ui_full_name = g_strdup(ui_name);
82 purple_debug_info("main", "Launching %s%slibpurple %s",
83 ui_full_name ? ui_full_name : "",
84 ui_full_name ? " with " : "",
85 purple_core_get_version());
87 g_free(ui_full_name);
90 gboolean
91 purple_core_init(const char *ui)
93 PurpleCoreUiOps *ops;
94 PurpleCore *core;
96 g_return_val_if_fail(ui != NULL, FALSE);
97 g_return_val_if_fail(purple_get_core() == NULL, FALSE);
99 bindtextdomain(PACKAGE, PURPLE_LOCALEDIR);
101 #ifdef _WIN32
102 wpurple_init();
103 #endif
105 _core = core = g_new0(PurpleCore, 1);
106 core->ui = g_strdup(ui);
107 core->reserved = NULL;
109 ops = purple_core_get_ui_ops();
111 /* The signals subsystem is important and should be first. */
112 purple_signals_init();
114 purple_util_init();
116 purple_signal_register(core, "uri-handler",
117 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER,
118 G_TYPE_BOOLEAN, 3,
119 G_TYPE_STRING, /* Protocol */
120 G_TYPE_STRING, /* Command */
121 G_TYPE_POINTER); /* Parameters (GHashTable *) */
123 purple_signal_register(core, "quitting", purple_marshal_VOID, G_TYPE_NONE,
125 purple_signal_register(core, "core-initialized", purple_marshal_VOID,
126 G_TYPE_NONE, 0);
128 purple_core_print_version();
130 /* The prefs subsystem needs to be initialized before static protocols
131 * for protocol prefs to work. */
132 purple_prefs_init();
134 purple_debug_init();
136 if (ops != NULL)
138 if (ops->ui_prefs_init != NULL)
139 ops->ui_prefs_init();
141 if (ops->debug_ui_init != NULL)
142 ops->debug_ui_init();
145 purple_cmds_init();
146 purple_protocols_init();
148 /* Since plugins get probed so early we should probably initialize their
149 * subsystem right away too.
151 purple_plugins_init();
153 purple_keyring_init(); /* before accounts */
154 purple_theme_manager_init();
156 /* The buddy icon code uses the image store, so init it early. */
157 _purple_image_store_init();
159 /* Accounts use status, buddy icons and connection signals, so
160 * initialize these before accounts
162 purple_statuses_init();
163 purple_buddy_icons_init();
164 purple_connections_init();
166 purple_accounts_init();
167 purple_savedstatuses_init();
168 purple_notify_init();
169 _purple_message_init();
170 purple_conversations_init();
171 purple_blist_init();
172 purple_log_init();
173 purple_network_init();
174 purple_pounces_init();
175 purple_proxy_init();
176 purple_sound_init();
177 purple_stun_init();
178 purple_xfers_init();
179 purple_idle_init();
180 purple_http_init();
181 _purple_smiley_custom_init();
182 _purple_smiley_parser_init();
185 * Call this early on to try to auto-detect our IP address and
186 * hopefully save some time later.
188 purple_network_get_my_ip(-1);
190 if (ops != NULL && ops->ui_init != NULL)
191 ops->ui_init();
193 /* The UI may have registered some theme types, so refresh them */
194 purple_theme_manager_refresh();
196 /* Load the buddy list after UI init */
197 purple_blist_boot();
199 purple_signal_emit(purple_get_core(), "core-initialized");
201 return TRUE;
204 void
205 purple_core_quit(void)
207 PurpleCoreUiOps *ops;
208 PurpleCore *core = purple_get_core();
210 g_return_if_fail(core != NULL);
212 /* The self destruct sequence has been initiated */
213 purple_signal_emit(purple_get_core(), "quitting");
215 /* Transmission ends */
216 purple_connections_disconnect_all();
218 /* Save .xml files, remove signals, etc. */
219 _purple_smiley_theme_uninit();
220 _purple_smiley_custom_uninit();
221 _purple_smiley_parser_uninit();
222 purple_http_uninit();
223 purple_idle_uninit();
224 purple_pounces_uninit();
225 purple_conversations_uninit();
226 purple_blist_uninit();
227 purple_notify_uninit();
228 purple_connections_uninit();
229 purple_buddy_icons_uninit();
230 purple_savedstatuses_uninit();
231 purple_statuses_uninit();
232 purple_accounts_uninit();
233 purple_keyring_uninit(); /* after accounts */
234 purple_sound_uninit();
235 purple_theme_manager_uninit();
236 purple_xfers_uninit();
237 purple_proxy_uninit();
238 _purple_image_store_uninit();
239 purple_network_uninit();
241 ops = purple_core_get_ui_ops();
242 if (ops != NULL && ops->quit != NULL)
243 ops->quit();
245 /* Everything after prefs_uninit must not try to read any prefs */
246 purple_prefs_uninit();
247 purple_plugins_uninit();
249 purple_protocols_uninit();
251 purple_cmds_uninit();
252 purple_log_uninit();
253 _purple_message_uninit();
254 /* Everything after util_uninit cannot try to write things to the
255 * confdir nor use purple_escape_js
257 purple_util_uninit();
259 purple_signals_uninit();
261 g_free(core->ui);
262 g_free(core);
264 #ifdef _WIN32
265 wpurple_cleanup();
266 #endif
268 _core = NULL;
271 gboolean
272 purple_core_quit_cb(gpointer unused)
274 purple_core_quit();
276 return FALSE;
279 const char *
280 purple_core_get_version(void)
282 return VERSION;
285 const char *
286 purple_core_get_ui(void)
288 PurpleCore *core = purple_get_core();
290 g_return_val_if_fail(core != NULL, NULL);
292 return core->ui;
295 PurpleCore *
296 purple_get_core(void)
298 return _core;
301 static PurpleCoreUiOps *
302 purple_core_ui_ops_copy(PurpleCoreUiOps *ops)
304 PurpleCoreUiOps *ops_new;
306 g_return_val_if_fail(ops != NULL, NULL);
308 ops_new = g_new(PurpleCoreUiOps, 1);
309 *ops_new = *ops;
311 return ops_new;
314 GType
315 purple_core_ui_ops_get_type(void)
317 static GType type = 0;
319 if (type == 0) {
320 type = g_boxed_type_register_static("PurpleCoreUiOps",
321 (GBoxedCopyFunc)purple_core_ui_ops_copy,
322 (GBoxedFreeFunc)g_free);
325 return type;
328 void
329 purple_core_set_ui_ops(PurpleCoreUiOps *ops)
331 _ops = ops;
334 PurpleCoreUiOps *
335 purple_core_get_ui_ops(void)
337 return _ops;
340 GHashTable* purple_core_get_ui_info() {
341 PurpleCoreUiOps *ops = purple_core_get_ui_ops();
343 if(NULL == ops || NULL == ops->get_ui_info)
344 return NULL;
346 return ops->get_ui_info();
349 #define MIGRATE_TO_XDG_DIR(xdg_base_dir, legacy_path) \
350 G_STMT_START { \
351 gboolean migrate_res; \
353 migrate_res = purple_move_to_xdg_base_dir(xdg_base_dir, legacy_path); \
354 if (!migrate_res) { \
355 purple_debug_error("core", "Error migrating %s to %s\n", \
356 legacy_path, xdg_base_dir); \
357 return FALSE; \
359 } G_STMT_END
361 gboolean
362 purple_core_migrate_to_xdg_base_dirs(void)
364 gboolean xdg_dir_exists;
366 xdg_dir_exists = g_file_test(purple_data_dir(), G_FILE_TEST_EXISTS);
367 if (!xdg_dir_exists) {
368 MIGRATE_TO_XDG_DIR(purple_data_dir(), "certificates");
369 MIGRATE_TO_XDG_DIR(purple_data_dir(), "custom_smiley");
370 MIGRATE_TO_XDG_DIR(purple_data_dir(), "logs");
371 MIGRATE_TO_XDG_DIR(purple_config_dir(), "accounts.xml");
372 MIGRATE_TO_XDG_DIR(purple_config_dir(), "blist.xml");
373 MIGRATE_TO_XDG_DIR(purple_config_dir(), "fs-codec.conf");
374 MIGRATE_TO_XDG_DIR(purple_config_dir(), "fs-element.conf");
375 MIGRATE_TO_XDG_DIR(purple_config_dir(), "pounces.xml");
376 MIGRATE_TO_XDG_DIR(purple_config_dir(), "prefs.xml");
377 MIGRATE_TO_XDG_DIR(purple_config_dir(), "smileys.xml");
378 MIGRATE_TO_XDG_DIR(purple_config_dir(), "status.xml");
381 return TRUE;