strtok() is recursive by default on win32.
[mpd-mk.git] / src / main.c
blob80102968e63fb4ef9e92433dea0b7dd359660ad2
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
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.
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.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "main.h"
22 #include "daemon.h"
23 #include "client.h"
24 #include "idle.h"
25 #include "command.h"
26 #include "playlist.h"
27 #include "stored_playlist.h"
28 #include "database.h"
29 #include "update.h"
30 #include "player_thread.h"
31 #include "listen.h"
32 #include "cmdline.h"
33 #include "conf.h"
34 #include "path.h"
35 #include "mapper.h"
36 #include "chunk.h"
37 #include "player_control.h"
38 #include "stats.h"
39 #include "sig_handlers.h"
40 #include "audio.h"
41 #include "output_all.h"
42 #include "volume.h"
43 #include "log.h"
44 #include "permission.h"
45 #include "replay_gain_config.h"
46 #include "decoder_list.h"
47 #include "input_init.h"
48 #include "playlist_list.h"
49 #include "state_file.h"
50 #include "tag.h"
51 #include "dbUtils.h"
52 #include "zeroconf.h"
53 #include "event_pipe.h"
54 #include "dirvec.h"
55 #include "songvec.h"
56 #include "tag_pool.h"
58 #ifdef ENABLE_INOTIFY
59 #include "inotify_update.h"
60 #endif
62 #ifdef ENABLE_SQLITE
63 #include "sticker.h"
64 #endif
66 #ifdef ENABLE_ARCHIVE
67 #include "archive_list.h"
68 #endif
70 #include <glib.h>
72 #include <unistd.h>
73 #include <stdlib.h>
74 #include <errno.h>
75 #include <string.h>
77 #ifdef HAVE_LOCALE_H
78 #include <locale.h>
79 #endif
81 #ifdef WIN32
82 #include <winsock2.h>
83 #include <ws2tcpip.h>
84 #endif
86 enum {
87 DEFAULT_BUFFER_SIZE = 2048,
88 DEFAULT_BUFFER_BEFORE_PLAY = 10,
91 GThread *main_task;
92 GMainLoop *main_loop;
94 GCond *main_cond;
96 static void
97 glue_daemonize_init(const struct options *options)
99 daemonize_init(config_get_string(CONF_USER, NULL),
100 config_get_string(CONF_GROUP, NULL),
101 config_get_path(CONF_PID_FILE));
103 if (options->kill)
104 daemonize_kill();
107 static void
108 glue_mapper_init(void)
110 const char *music_dir, *playlist_dir;
112 music_dir = config_get_path(CONF_MUSIC_DIR);
113 #if GLIB_CHECK_VERSION(2,14,0)
114 if (music_dir == NULL)
115 music_dir = g_get_user_special_dir(G_USER_DIRECTORY_MUSIC);
116 #endif
118 playlist_dir = config_get_path(CONF_PLAYLIST_DIR);
120 mapper_init(music_dir, playlist_dir);
124 * Returns the database. If this function returns false, this has not
125 * succeeded, and the caller should create the database after the
126 * process has been daemonized.
128 static bool
129 glue_db_init_and_load(void)
131 const char *path = config_get_path(CONF_DB_FILE);
132 bool ret;
133 GError *error = NULL;
135 if (!mapper_has_music_directory()) {
136 if (path != NULL)
137 g_message("Found " CONF_DB_FILE " setting without "
138 CONF_MUSIC_DIR " - disabling database");
139 db_init(NULL);
140 return true;
143 if (path == NULL)
144 g_error(CONF_DB_FILE " setting missing");
146 db_init(path);
148 ret = db_load(&error);
149 if (!ret) {
150 g_warning("Failed to load database: %s", error->message);
151 g_error_free(error);
153 if (!db_check())
154 exit(EXIT_FAILURE);
156 db_clear();
158 /* run database update after daemonization */
159 return false;
162 return true;
166 * Configure and initialize the sticker subsystem.
168 static void
169 glue_sticker_init(void)
171 #ifdef ENABLE_SQLITE
172 bool success;
173 GError *error = NULL;
175 success = sticker_global_init(config_get_path(CONF_STICKER_FILE),
176 &error);
177 if (!success)
178 g_error("%s", error->message);
179 #endif
182 static void
183 glue_state_file_init(void)
185 state_file_init(config_get_path(CONF_STATE_FILE));
189 * Windows-only initialization of the Winsock2 library.
191 static void winsock_init(void)
193 #ifdef WIN32
194 WSADATA sockinfo;
195 int retval;
197 retval = WSAStartup(MAKEWORD(2, 2), &sockinfo);
198 if(retval != 0)
200 g_error("Attempt to open Winsock2 failed; error code %d\n",
201 retval);
204 if (LOBYTE(sockinfo.wVersion) != 2)
206 g_error("We use Winsock2 but your version is either too new or "
207 "old; please install Winsock 2.x\n");
209 #endif
213 * Initialize the decoder and player core, including the music pipe.
215 static void
216 initialize_decoder_and_player(void)
218 const struct config_param *param;
219 char *test;
220 size_t buffer_size;
221 float perc;
222 unsigned buffered_chunks;
223 unsigned buffered_before_play;
225 param = config_get_param(CONF_AUDIO_BUFFER_SIZE);
226 if (param != NULL) {
227 buffer_size = strtol(param->value, &test, 10);
228 if (*test != '\0' || buffer_size <= 0)
229 g_error("buffer size \"%s\" is not a positive integer, "
230 "line %i\n", param->value, param->line);
231 } else
232 buffer_size = DEFAULT_BUFFER_SIZE;
234 buffer_size *= 1024;
236 buffered_chunks = buffer_size / CHUNK_SIZE;
238 if (buffered_chunks >= 1 << 15)
239 g_error("buffer size \"%li\" is too big\n", (long)buffer_size);
241 param = config_get_param(CONF_BUFFER_BEFORE_PLAY);
242 if (param != NULL) {
243 perc = strtod(param->value, &test);
244 if (*test != '%' || perc < 0 || perc > 100) {
245 g_error("buffered before play \"%s\" is not a positive "
246 "percentage and less than 100 percent, line %i",
247 param->value, param->line);
249 } else
250 perc = DEFAULT_BUFFER_BEFORE_PLAY;
252 buffered_before_play = (perc / 100) * buffered_chunks;
253 if (buffered_before_play > buffered_chunks)
254 buffered_before_play = buffered_chunks;
256 pc_init(buffered_chunks, buffered_before_play);
260 * event_pipe callback function for PIPE_EVENT_IDLE
262 static void
263 idle_event_emitted(void)
265 /* send "idle" notificaions to all subscribed
266 clients */
267 unsigned flags = idle_get();
268 if (flags != 0)
269 client_manager_idle_add(flags);
272 int main(int argc, char *argv[])
274 struct options options;
275 clock_t start;
276 bool create_db;
277 GError *error = NULL;
278 bool success;
280 daemonize_close_stdin();
282 #ifdef HAVE_LOCALE_H
283 /* initialize locale */
284 setlocale(LC_CTYPE,"");
285 #endif
287 g_set_application_name("Music Player Daemon");
289 /* enable GLib's thread safety code */
290 g_thread_init(NULL);
292 winsock_init();
293 idle_init();
294 dirvec_init();
295 songvec_init();
296 tag_pool_init();
297 config_global_init();
299 success = parse_cmdline(argc, argv, &options, &error);
300 if (!success) {
301 g_warning("%s", error->message);
302 g_error_free(error);
303 return EXIT_FAILURE;
306 glue_daemonize_init(&options);
308 stats_global_init();
309 tag_lib_init();
310 log_init(options.verbose, options.log_stderr);
312 success = listen_global_init(&error);
313 if (!success) {
314 g_warning("%s", error->message);
315 g_error_free(error);
316 return EXIT_FAILURE;
319 daemonize_set_user();
321 main_task = g_thread_self();
322 main_loop = g_main_loop_new(NULL, FALSE);
323 main_cond = g_cond_new();
325 event_pipe_init();
326 event_pipe_register(PIPE_EVENT_IDLE, idle_event_emitted);
328 path_global_init();
329 glue_mapper_init();
330 initPermissions();
331 playlist_global_init();
332 spl_global_init();
333 #ifdef ENABLE_ARCHIVE
334 archive_plugin_init_all();
335 #endif
336 decoder_plugin_init_all();
337 update_global_init();
339 create_db = !glue_db_init_and_load();
341 glue_sticker_init();
343 command_init();
344 initialize_decoder_and_player();
345 volume_init();
346 initAudioConfig();
347 audio_output_all_init();
348 client_manager_init();
349 replay_gain_global_init();
351 if (!input_stream_global_init(&error)) {
352 g_warning("%s", error->message);
353 g_error_free(error);
354 return EXIT_FAILURE;
357 playlist_list_global_init();
359 daemonize(options.daemon);
361 setup_log_output(options.log_stderr);
363 initSigHandlers();
365 initZeroconf();
367 player_create();
369 if (create_db) {
370 /* the database failed to load: recreate the
371 database */
372 unsigned job = update_enqueue(NULL, true);
373 if (job == 0)
374 g_error("directory update failed");
377 glue_state_file_init();
379 success = config_get_bool(CONF_AUTO_UPDATE, false);
380 #ifdef ENABLE_INOTIFY
381 if (success && mapper_has_music_directory())
382 mpd_inotify_init();
383 #else
384 if (success)
385 g_warning("inotify: auto_update was disabled. enable during compilation phase");
386 #endif
388 config_global_check();
390 /* enable all audio outputs (if not already done by
391 playlist_state_restore() */
392 pc_update_audio();
394 /* run the main loop */
396 g_main_loop_run(main_loop);
398 /* cleanup */
400 g_main_loop_unref(main_loop);
402 #ifdef ENABLE_INOTIFY
403 mpd_inotify_finish();
404 #endif
406 state_file_finish();
407 pc_kill();
408 finishZeroconf();
409 client_manager_deinit();
410 listen_global_finish();
411 playlist_global_finish();
413 start = clock();
414 db_finish();
415 g_debug("db_finish took %f seconds",
416 ((float)(clock()-start))/CLOCKS_PER_SEC);
418 #ifdef ENABLE_SQLITE
419 sticker_global_finish();
420 #endif
422 g_cond_free(main_cond);
423 event_pipe_deinit();
425 playlist_list_global_finish();
426 input_stream_global_finish();
427 audio_output_all_finish();
428 volume_finish();
429 mapper_finish();
430 path_global_finish();
431 finishPermissions();
432 pc_deinit();
433 command_finish();
434 update_global_finish();
435 decoder_plugin_deinit_all();
436 #ifdef ENABLE_ARCHIVE
437 archive_plugin_deinit_all();
438 #endif
439 config_global_finish();
440 tag_pool_deinit();
441 songvec_deinit();
442 dirvec_deinit();
443 idle_deinit();
444 stats_global_finish();
445 daemonize_finish();
446 #ifdef WIN32
447 WSACleanup();
448 #endif
450 close_log_files();
451 return EXIT_SUCCESS;