Don't search for libspeex on Windows and Mac.
[kugel-rb.git] / apps / main.c
blob5f2c9e5a58cfb41626ef21701d0eed9d32bdb0da
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
23 #include "gcc_extensions.h"
24 #include "storage.h"
25 #include "disk.h"
26 #include "fat.h"
27 #include "lcd.h"
28 #include "rtc.h"
29 #include "debug.h"
30 #include "led.h"
31 #include "kernel.h"
32 #include "button.h"
33 #include "tree.h"
34 #include "filetypes.h"
35 #include "panic.h"
36 #include "menu.h"
37 #include "system.h"
38 #include "usb.h"
39 #include "powermgmt.h"
40 #include "adc.h"
41 #include "i2c.h"
42 #ifndef DEBUG
43 #include "serial.h"
44 #endif
45 #include "audio.h"
46 #include "mp3_playback.h"
47 #include "thread.h"
48 #include "settings.h"
49 #include "backlight.h"
50 #include "status.h"
51 #include "debug_menu.h"
52 #include "font.h"
53 #include "language.h"
54 #include "wps.h"
55 #include "playlist.h"
56 #include "buffer.h"
57 #include "rolo.h"
58 #include "screens.h"
59 #include "usb_screen.h"
60 #include "power.h"
61 #include "talk.h"
62 #include "plugin.h"
63 #include "misc.h"
64 #include "dircache.h"
65 #ifdef HAVE_TAGCACHE
66 #include "tagcache.h"
67 #include "tagtree.h"
68 #endif
69 #include "lang.h"
70 #include "string.h"
71 #include "splash.h"
72 #include "eeprom_settings.h"
73 #include "scrobbler.h"
74 #include "icon.h"
75 #include "viewport.h"
76 #include "statusbar-skinned.h"
77 #include "bootchart.h"
79 #ifdef IPOD_ACCESSORY_PROTOCOL
80 #include "iap.h"
81 #endif
83 #if (CONFIG_CODEC == SWCODEC)
84 #include "playback.h"
85 #include "tdspeed.h"
86 #endif
87 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
88 #include "pcm_record.h"
89 #endif
91 #ifdef BUTTON_REC
92 #define SETTINGS_RESET BUTTON_REC
93 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
94 #define SETTINGS_RESET BUTTON_A
95 #endif
97 #if CONFIG_TUNER
98 #include "radio.h"
99 #endif
100 #if (CONFIG_STORAGE & STORAGE_MMC)
101 #include "ata_mmc.h"
102 #endif
104 #ifdef HAVE_REMOTE_LCD
105 #include "lcd-remote.h"
106 #endif
108 #if CONFIG_USBOTG == USBOTG_ISP1362
109 #include "isp1362.h"
110 #endif
112 #if CONFIG_USBOTG == USBOTG_M5636
113 #include "m5636.h"
114 #endif
116 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
117 #define MAIN_NORETURN_ATTR NORETURN_ATTR
118 #else
119 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
120 * with noreturn attribute */
121 #define MAIN_NORETURN_ATTR
122 #endif
124 #if (CONFIG_PLATFORM & PLATFORM_SDL)
125 #include "sim_tasks.h"
126 #include "system-sdl.h"
127 #define HAVE_ARGV_MAIN
128 /* Don't use SDL_main on windows -> no more stdio redirection */
129 #if defined(WIN32)
130 #undef main
131 #endif
132 #endif
134 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
136 static void init(void);
137 /* main(), and various functions called by main() and init() may be
138 * be INIT_ATTR. These functions must not be called after the final call
139 * to root_menu() at the end of main()
140 * see definition of INIT_ATTR in config.h */
141 #ifdef HAVE_ARGV_MAIN
142 int main(int argc, char *argv[]) INIT_ATTR MAIN_NORETURN_ATTR ;
143 int main(int argc, char *argv[])
145 sys_handle_argv(argc, argv);
146 #else
147 int main(void) INIT_ATTR MAIN_NORETURN_ATTR;
148 int main(void)
150 #endif
151 int i;
152 CHART(">init");
153 init();
154 CHART("<init");
155 FOR_NB_SCREENS(i)
157 screens[i].clear_display();
158 screens[i].update();
160 #ifdef HAVE_LCD_BITMAP
161 list_init();
162 #endif
163 tree_gui_init();
164 /* Keep the order of this 3
165 * Must be done before any code uses the multi-screen API */
166 #ifdef HAVE_USBSTACK
167 /* All threads should be created and public queues registered by now */
168 usb_start_monitoring();
169 #endif
171 #ifdef AUTOROCK
173 char filename[MAX_PATH];
174 const char *file = get_user_file_path(
175 #ifdef APPLICATION
176 ROCKBOX_DIR
177 #else
178 PLUGIN_APPS_DIR
179 #endif
180 "/autostart.rock", NEED_WRITE|IS_FILE, filename, sizeof(filename));
181 if(file_exists(file)) /* no complaint if it doesn't exist */
183 plugin_load(file, NULL); /* start if it does */
186 #endif /* #ifdef AUTOROCK */
188 global_status.last_volume_change = 0;
189 /* no calls INIT_ATTR functions after this point anymore!
190 * see definition of INIT_ATTR in config.h */
191 CHART(">root_menu");
192 root_menu();
195 static int init_dircache(bool preinit) INIT_ATTR;
196 static int init_dircache(bool preinit)
198 #ifdef HAVE_DIRCACHE
199 int result = 0;
200 bool clear = false;
202 if (preinit)
203 dircache_init();
205 if (!global_settings.dircache)
206 return 0;
208 # ifdef HAVE_EEPROM_SETTINGS
209 if (firmware_settings.initialized && firmware_settings.disk_clean
210 && preinit)
212 result = dircache_load();
214 if (result < 0)
216 firmware_settings.disk_clean = false;
217 if (global_status.dircache_size <= 0)
219 /* This will be in default language, settings are not
220 applied yet. Not really any easy way to fix that. */
221 splash(0, str(LANG_SCANNING_DISK));
222 clear = true;
225 dircache_build(global_status.dircache_size);
228 else
229 # endif
231 if (preinit)
232 return -1;
234 if (!dircache_is_enabled()
235 && !dircache_is_initializing())
237 if (global_status.dircache_size <= 0)
239 splash(0, str(LANG_SCANNING_DISK));
240 clear = true;
242 result = dircache_build(global_status.dircache_size);
245 if (result < 0)
247 /* Initialization of dircache failed. Manual action is
248 * necessary to enable dircache again.
250 splashf(0, "Dircache failed, disabled. Result: %d", result);
251 global_settings.dircache = false;
255 if (clear)
257 backlight_on();
258 show_logo();
259 global_status.dircache_size = dircache_get_cache_size();
260 status_save();
263 return result;
264 #else
265 (void)preinit;
266 return 0;
267 #endif
270 #ifdef HAVE_TAGCACHE
271 static void init_tagcache(void) INIT_ATTR;
272 static void init_tagcache(void)
274 bool clear = false;
275 #if CONFIG_CODEC == SWCODEC
276 long talked_tick = 0;
277 #endif
278 tagcache_init();
280 while (!tagcache_is_initialized())
282 int ret = tagcache_get_commit_step();
284 if (ret > 0)
286 #if CONFIG_CODEC == SWCODEC
287 /* hwcodec can't use voice here, as the database commit
288 * uses the audio buffer. */
289 if(global_settings.talk_menu
290 && (talked_tick == 0
291 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
293 talked_tick = current_tick;
294 talk_id(LANG_TAGCACHE_INIT, false);
295 talk_number(ret, true);
296 talk_id(VOICE_OF, true);
297 talk_number(tagcache_get_max_commit_step(), true);
299 #endif
300 #ifdef HAVE_LCD_BITMAP
301 if (lang_is_rtl())
303 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
304 str(LANG_TAGCACHE_INIT));
306 else
308 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
309 tagcache_get_max_commit_step());
311 #else
312 lcd_double_height(false);
313 lcd_putsf(0, 1, " DB [%d/%d]", ret,
314 tagcache_get_max_commit_step());
315 lcd_update();
316 #endif
317 clear = true;
319 sleep(HZ/4);
321 tagtree_init();
323 if (clear)
325 backlight_on();
326 show_logo();
329 #endif
331 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
333 static void init(void)
335 #ifdef APPLICATION
336 paths_init();
337 #endif
338 system_init();
339 kernel_init();
340 buffer_init();
341 enable_irq();
342 lcd_init();
343 #ifdef HAVE_REMOTE_LCD
344 lcd_remote_init();
345 #endif
346 font_init();
347 show_logo();
348 button_init();
349 backlight_init();
350 #if (CONFIG_PLATFORM & PLATFORM_SDL)
351 sim_tasks_init();
352 #endif
353 lang_init(core_language_builtin, language_strings,
354 LANG_LAST_INDEX_IN_ARRAY);
355 #ifdef DEBUG
356 debug_init();
357 #endif
358 /* Keep the order of this 3 (viewportmanager handles statusbars)
359 * Must be done before any code uses the multi-screen API */
360 gui_syncstatusbar_init(&statusbars);
361 gui_sync_wps_init();
362 sb_skin_init();
363 viewportmanager_init();
365 storage_init();
366 settings_reset();
367 settings_load(SETTINGS_ALL);
368 settings_apply(true);
369 init_dircache(true);
370 init_dircache(false);
371 #ifdef HAVE_TAGCACHE
372 init_tagcache();
373 #endif
374 sleep(HZ/2);
375 tree_mem_init();
376 filetype_init();
377 playlist_init();
378 theme_init_buffer();
380 #if CONFIG_CODEC != SWCODEC
381 mp3_init( global_settings.volume,
382 global_settings.bass,
383 global_settings.treble,
384 global_settings.balance,
385 global_settings.loudness,
386 global_settings.avc,
387 global_settings.channel_config,
388 global_settings.stereo_width,
389 global_settings.mdb_strength,
390 global_settings.mdb_harmonics,
391 global_settings.mdb_center,
392 global_settings.mdb_shape,
393 global_settings.mdb_enable,
394 global_settings.superbass);
396 /* audio_init must to know the size of voice buffer so init voice first */
397 talk_init();
398 #endif /* CONFIG_CODEC != SWCODEC */
400 scrobbler_init();
401 #if CONFIG_CODEC == SWCODEC
402 tdspeed_init();
403 #endif /* CONFIG_CODEC == SWCODEC */
405 audio_init();
406 button_clear_queue(); /* Empty the keyboard buffer */
408 settings_apply_skins();
411 #else
413 static void init(void) INIT_ATTR;
414 static void init(void)
416 int rc;
417 bool mounted = false;
418 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
419 /* if nobody initialized ATA before, I consider this a cold start */
420 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
421 #endif
423 system_init();
424 #if defined(IPOD_VIDEO)
425 audiobufend=(unsigned char *)audiobufend_lds;
426 if(MEM==64 && probed_ramsize!=64)
428 audiobufend -= (32<<20);
430 #endif
431 kernel_init();
433 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
434 set_cpu_frequency(CPUFREQ_NORMAL);
435 #ifdef CPU_COLDFIRE
436 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
437 #endif
438 cpu_boost(true);
439 #endif
441 buffer_init();
443 settings_reset();
445 i2c_init();
447 power_init();
449 enable_irq();
450 #ifdef CPU_ARM
451 enable_fiq();
452 #endif
453 /* current_tick should be ticking by now */
454 CHART("ticking");
456 lcd_init();
457 #ifdef HAVE_REMOTE_LCD
458 lcd_remote_init();
459 #endif
460 font_init();
462 CHART(">show_logo");
463 show_logo();
464 CHART("<show_logo");
465 lang_init(core_language_builtin, language_strings,
466 LANG_LAST_INDEX_IN_ARRAY);
468 #ifdef DEBUG
469 debug_init();
470 #else
471 #ifdef HAVE_SERIAL
472 serial_setup();
473 #endif
474 #endif
476 #if CONFIG_RTC
477 rtc_init();
478 #endif
479 #ifdef HAVE_RTC_RAM
480 CHART(">settings_load(RTC)");
481 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
482 CHART("<settings_load(RTC)");
483 #endif
485 adc_init();
487 usb_init();
488 #if CONFIG_USBOTG == USBOTG_ISP1362
489 isp1362_init();
490 #elif CONFIG_USBOTG == USBOTG_M5636
491 m5636_init();
492 #endif
494 backlight_init();
496 button_init();
498 powermgmt_init();
500 #if CONFIG_TUNER
501 radio_init();
502 #endif
504 /* Keep the order of this 3 (viewportmanager handles statusbars)
505 * Must be done before any code uses the multi-screen API */
506 CHART(">gui_syncstatusbar_init");
507 gui_syncstatusbar_init(&statusbars);
508 CHART("<gui_syncstatusbar_init");
509 CHART(">sb_skin_init");
510 sb_skin_init();
511 CHART("<sb_skin_init");
512 CHART(">gui_sync_wps_init");
513 gui_sync_wps_init();
514 CHART("<gui_sync_wps_init");
515 CHART(">viewportmanager_init");
516 viewportmanager_init();
517 CHART("<viewportmanager_init");
519 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
520 /* charger_inserted() can't be used here because power_thread()
521 hasn't checked power_input_status() yet */
522 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
523 && !global_settings.car_adapter_mode
524 #ifdef ATA_POWER_PLAYERSTYLE
525 && !ide_powered() /* relies on probing result from bootloader */
526 #endif
529 rc = charging_screen(); /* display a "charging" screen */
530 if (rc == 1) /* charger removed */
531 power_off();
532 /* "On" pressed or USB connected: proceed */
533 show_logo(); /* again, to provide better visual feedback */
535 #endif
538 disk_init_subsystem();
539 CHART(">storage_init");
540 rc = storage_init();
541 CHART("<storage_init");
542 if(rc)
544 #ifdef HAVE_LCD_BITMAP
545 lcd_clear_display();
546 lcd_putsf(0, 1, "ATA error: %d", rc);
547 lcd_puts(0, 3, "Press ON to debug");
548 lcd_update();
549 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
550 dbg_ports();
551 #endif
552 panicf("ata: %d", rc);
555 #ifdef HAVE_EEPROM_SETTINGS
556 CHART(">eeprom_settings_init");
557 eeprom_settings_init();
558 CHART("<eeprom_settings_init");
559 #endif
561 #ifndef HAVE_USBSTACK
562 usb_start_monitoring();
563 while (usb_detect() == USB_INSERTED)
565 #ifdef HAVE_EEPROM_SETTINGS
566 firmware_settings.disk_clean = false;
567 #endif
568 /* enter USB mode early, before trying to mount */
569 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
570 #if (CONFIG_STORAGE & STORAGE_MMC)
571 if (!mmc_touched() ||
572 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
573 #endif
575 gui_usb_screen_run();
576 mounted = true; /* mounting done @ end of USB mode */
578 #ifdef HAVE_USB_POWER
579 if (usb_powered()) /* avoid deadlock */
580 break;
581 #endif
583 #endif
585 if (!mounted)
587 CHART(">disk_mount_all");
588 rc = disk_mount_all();
589 CHART("<disk_mount_all");
590 if (rc<=0)
592 lcd_clear_display();
593 lcd_puts(0, 0, "No partition");
594 lcd_puts(0, 1, "found.");
595 #ifdef HAVE_LCD_BITMAP
596 lcd_puts(0, 2, "Insert USB cable");
597 lcd_puts(0, 3, "and fix it.");
598 #endif
599 lcd_update();
601 while(button_get(true) != SYS_USB_CONNECTED) {};
602 gui_usb_screen_run();
603 system_reboot();
607 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
608 (CONFIG_KEYPAD == IRIVER_H10_PAD)
609 #ifdef SETTINGS_RESET
610 /* Reset settings if holding the reset button. (Rec on Archos,
611 A on Gigabeat) */
612 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
613 #else
614 /* Reset settings if the hold button is turned on */
615 if (button_hold())
616 #endif
618 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
619 settings_reset();
621 else
622 #endif
624 CHART(">settings_load(ALL)");
625 settings_load(SETTINGS_ALL);
626 CHART("<settings_load(ALL)");
629 CHART(">init_dircache(true)");
630 rc = init_dircache(true);
631 CHART("<init_dircache(true)");
632 if (rc < 0)
634 #ifdef HAVE_TAGCACHE
635 remove(TAGCACHE_STATEFILE);
636 #endif
639 CHART(">settings_apply(true)");
640 settings_apply(true);
641 CHART("<settings_apply(true)");
642 CHART(">init_dircache(false)");
643 init_dircache(false);
644 CHART("<init_dircache(false)");
645 #ifdef HAVE_TAGCACHE
646 CHART(">init_tagcache");
647 init_tagcache();
648 CHART("<init_tagcache");
649 #endif
651 #ifdef HAVE_EEPROM_SETTINGS
652 if (firmware_settings.initialized)
654 /* In case we crash. */
655 firmware_settings.disk_clean = false;
656 CHART(">eeprom_settings_store");
657 eeprom_settings_store();
658 CHART("<eeprom_settings_store");
660 #endif
661 playlist_init();
662 tree_mem_init();
663 filetype_init();
664 scrobbler_init();
665 #if CONFIG_CODEC == SWCODEC
666 tdspeed_init();
667 #endif /* CONFIG_CODEC == SWCODEC */
668 theme_init_buffer();
670 #if CONFIG_CODEC != SWCODEC
671 /* No buffer allocation (see buffer.c) may take place after the call to
672 audio_init() since the mpeg thread takes the rest of the buffer space */
673 mp3_init( global_settings.volume,
674 global_settings.bass,
675 global_settings.treble,
676 global_settings.balance,
677 global_settings.loudness,
678 global_settings.avc,
679 global_settings.channel_config,
680 global_settings.stereo_width,
681 global_settings.mdb_strength,
682 global_settings.mdb_harmonics,
683 global_settings.mdb_center,
684 global_settings.mdb_shape,
685 global_settings.mdb_enable,
686 global_settings.superbass);
688 /* audio_init must to know the size of voice buffer so init voice first */
689 talk_init();
690 #endif /* CONFIG_CODEC != SWCODEC */
692 CHART(">audio_init");
693 audio_init();
694 CHART("<audio_init");
696 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
697 pcm_rec_init();
698 #endif
700 /* runtime database has to be initialized after audio_init() */
701 cpu_boost(false);
703 #if CONFIG_CHARGING
704 car_adapter_mode_init();
705 #endif
706 #ifdef IPOD_ACCESSORY_PROTOCOL
707 iap_setup(global_settings.serial_bitrate);
708 #endif
709 #ifdef HAVE_ACCESSORY_SUPPLY
710 accessory_supply_set(global_settings.accessory_supply);
711 #endif
712 #ifdef HAVE_LINEOUT_POWEROFF
713 lineout_set(global_settings.lineout_active);
714 #endif
715 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
716 CHART("<check_bootfile(false)");
717 check_bootfile(false); /* remember write time and filesize */
718 CHART(">check_bootfile(false)");
719 #endif
720 CHART("<settings_apply_skins");
721 settings_apply_skins();
722 CHART(">settings_apply_skins");
725 #ifdef CPU_PP
726 void cop_main(void) MAIN_NORETURN_ATTR;
727 void cop_main(void)
729 /* This is the entry point for the coprocessor
730 Anyone not running an upgraded bootloader will never reach this point,
731 so it should not be assumed that the coprocessor be usable even on
732 platforms which support it.
734 A kernel thread is initially setup on the coprocessor and immediately
735 destroyed for purposes of continuity. The cop sits idle until at least
736 one thread exists on it. */
738 #if NUM_CORES > 1
739 system_init();
740 kernel_init();
741 /* This should never be reached */
742 #endif
743 while(1) {
744 sleep_core(COP);
747 #endif /* CPU_PP */
749 #endif /* SIMULATOR */