The threading model should be set from configure, not config.h.
[maemo-rb.git] / apps / main.c
blob4ce72497d7442300e100b1afe16532f197866f66
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 "core_alloc.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 "skin_engine/skin_engine.h"
77 #include "statusbar-skinned.h"
78 #include "bootchart.h"
79 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
80 #include "notification.h"
81 #endif
82 #include "shortcuts.h"
84 #ifdef IPOD_ACCESSORY_PROTOCOL
85 #include "iap.h"
86 #endif
88 #if (CONFIG_CODEC == SWCODEC)
89 #include "playback.h"
90 #include "tdspeed.h"
91 #endif
92 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
93 #include "pcm_record.h"
94 #endif
96 #ifdef BUTTON_REC
97 #define SETTINGS_RESET BUTTON_REC
98 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
99 #define SETTINGS_RESET BUTTON_A
100 #endif
102 #if CONFIG_TUNER
103 #include "radio.h"
104 #endif
105 #if (CONFIG_STORAGE & STORAGE_MMC)
106 #include "ata_mmc.h"
107 #endif
109 #ifdef HAVE_REMOTE_LCD
110 #include "lcd-remote.h"
111 #endif
113 #if CONFIG_USBOTG == USBOTG_ISP1362
114 #include "isp1362.h"
115 #endif
117 #if CONFIG_USBOTG == USBOTG_M5636
118 #include "m5636.h"
119 #endif
121 #ifdef HAVE_HARDWARE_CLICK
122 #include "piezo.h"
123 #endif
125 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
126 #define MAIN_NORETURN_ATTR NORETURN_ATTR
127 #else
128 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
129 * with noreturn attribute */
130 #define MAIN_NORETURN_ATTR
131 #endif
133 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
134 #ifdef SIMULATOR
135 #include "sim_tasks.h"
136 #endif
137 #include "system-sdl.h"
138 #define HAVE_ARGV_MAIN
139 /* Don't use SDL_main on windows -> no more stdio redirection */
140 #if defined(WIN32)
141 #undef main
142 #endif
143 #endif
145 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
147 static void init(void);
148 /* main(), and various functions called by main() and init() may be
149 * be INIT_ATTR. These functions must not be called after the final call
150 * to root_menu() at the end of main()
151 * see definition of INIT_ATTR in config.h */
152 #ifdef HAVE_ARGV_MAIN
153 int main(int argc, char *argv[]) INIT_ATTR MAIN_NORETURN_ATTR ;
154 int main(int argc, char *argv[])
156 sys_handle_argv(argc, argv);
157 #else
158 int main(void) INIT_ATTR MAIN_NORETURN_ATTR;
159 int main(void)
161 #endif
162 CHART(">init");
163 init();
164 CHART("<init");
165 FOR_NB_SCREENS(i)
167 screens[i].clear_display();
168 screens[i].update();
170 #ifdef HAVE_LCD_BITMAP
171 list_init();
172 #endif
173 tree_gui_init();
174 /* Keep the order of this 3
175 * Must be done before any code uses the multi-screen API */
176 #ifdef HAVE_USBSTACK
177 /* All threads should be created and public queues registered by now */
178 usb_start_monitoring();
179 #endif
181 #ifdef AUTOROCK
183 char filename[MAX_PATH];
184 const char *file =
185 #ifdef APPLICATION
186 ROCKBOX_DIR
187 #else
188 PLUGIN_APPS_DIR
189 #endif
190 "/autostart.rock";
191 if(file_exists(file)) /* no complaint if it doesn't exist */
193 plugin_load(file, NULL); /* start if it does */
196 #endif /* #ifdef AUTOROCK */
198 global_status.last_volume_change = 0;
199 /* no calls INIT_ATTR functions after this point anymore!
200 * see definition of INIT_ATTR in config.h */
201 CHART(">root_menu");
202 root_menu();
205 static int init_dircache(bool preinit) INIT_ATTR;
206 static int init_dircache(bool preinit)
208 #ifdef HAVE_DIRCACHE
209 int result = 0;
210 bool clear = false;
212 if (preinit)
213 dircache_init();
215 if (!global_settings.dircache)
216 return 0;
218 # ifdef HAVE_EEPROM_SETTINGS
219 if (firmware_settings.initialized && firmware_settings.disk_clean
220 && preinit)
222 result = dircache_load();
224 if (result < 0)
226 firmware_settings.disk_clean = false;
227 if (global_status.dircache_size <= 0)
229 /* This will be in default language, settings are not
230 applied yet. Not really any easy way to fix that. */
231 splash(0, str(LANG_SCANNING_DISK));
232 clear = true;
235 dircache_build(global_status.dircache_size);
238 else
239 # endif
241 if (preinit)
242 return -1;
244 if (!dircache_is_enabled()
245 && !dircache_is_initializing())
247 if (global_status.dircache_size <= 0)
249 splash(0, str(LANG_SCANNING_DISK));
250 clear = true;
252 result = dircache_build(global_status.dircache_size);
255 if (result < 0)
257 /* Initialization of dircache failed. Manual action is
258 * necessary to enable dircache again.
260 splashf(0, "Dircache failed, disabled. Result: %d", result);
261 global_settings.dircache = false;
265 if (clear)
267 backlight_on();
268 show_logo();
269 global_status.dircache_size = dircache_get_cache_size();
270 status_save();
273 return result;
274 #else
275 (void)preinit;
276 return 0;
277 #endif
280 #ifdef HAVE_TAGCACHE
281 static void init_tagcache(void) INIT_ATTR;
282 static void init_tagcache(void)
284 bool clear = false;
285 #if 0 /* CONFIG_CODEC == SWCODEC */
286 long talked_tick = 0;
287 #endif
288 tagcache_init();
290 while (!tagcache_is_initialized())
292 int ret = tagcache_get_commit_step();
294 if (ret > 0)
296 #if 0 /* FIXME: Audio isn't even initialized yet! */ /* CONFIG_CODEC == SWCODEC */
297 /* hwcodec can't use voice here, as the database commit
298 * uses the audio buffer. */
299 if(global_settings.talk_menu
300 && (talked_tick == 0
301 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
303 talked_tick = current_tick;
304 talk_id(LANG_TAGCACHE_INIT, false);
305 talk_number(ret, true);
306 talk_id(VOICE_OF, true);
307 talk_number(tagcache_get_max_commit_step(), true);
309 #endif
310 #ifdef HAVE_LCD_BITMAP
311 if (lang_is_rtl())
313 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
314 str(LANG_TAGCACHE_INIT));
316 else
318 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
319 tagcache_get_max_commit_step());
321 #else
322 lcd_double_height(false);
323 lcd_putsf(0, 1, " DB [%d/%d]", ret,
324 tagcache_get_max_commit_step());
325 lcd_update();
326 #endif
327 clear = true;
329 sleep(HZ/4);
331 tagtree_init();
333 if (clear)
335 backlight_on();
336 show_logo();
339 #endif
341 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
343 static void init(void)
345 system_init();
346 core_allocator_init();
347 kernel_init();
348 #ifdef APPLICATION
349 paths_init();
350 #endif
351 enable_irq();
352 lcd_init();
353 #ifdef HAVE_REMOTE_LCD
354 lcd_remote_init();
355 #endif
356 #ifdef HAVE_LCD_BITMAP
357 FOR_NB_SCREENS(i)
358 global_status.font_id[i] = FONT_SYSFIXED;
359 font_init();
360 #endif
361 show_logo();
362 button_init();
363 powermgmt_init();
364 backlight_init();
365 #ifdef SIMULATOR
366 sim_tasks_init();
367 #endif
368 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
369 notification_init();
370 #endif
371 lang_init(core_language_builtin, language_strings,
372 LANG_LAST_INDEX_IN_ARRAY);
373 #ifdef DEBUG
374 debug_init();
375 #endif
376 #if CONFIG_TUNER
377 radio_init();
378 #endif
379 /* Keep the order of this 3 (viewportmanager handles statusbars)
380 * Must be done before any code uses the multi-screen API */
381 gui_syncstatusbar_init(&statusbars);
382 gui_sync_skin_init();
383 sb_skin_init();
384 viewportmanager_init();
386 storage_init();
387 #if CONFIG_CODEC == SWCODEC
388 dsp_init();
389 #endif
390 settings_reset();
391 settings_load(SETTINGS_ALL);
392 settings_apply(true);
393 init_dircache(true);
394 init_dircache(false);
395 #ifdef HAVE_TAGCACHE
396 init_tagcache();
397 #endif
398 tree_mem_init();
399 filetype_init();
400 playlist_init();
401 shortcuts_init();
403 #if CONFIG_CODEC != SWCODEC
404 mp3_init( global_settings.volume,
405 global_settings.bass,
406 global_settings.treble,
407 global_settings.balance,
408 global_settings.loudness,
409 global_settings.avc,
410 global_settings.channel_config,
411 global_settings.stereo_width,
412 global_settings.mdb_strength,
413 global_settings.mdb_harmonics,
414 global_settings.mdb_center,
415 global_settings.mdb_shape,
416 global_settings.mdb_enable,
417 global_settings.superbass);
418 #endif /* CONFIG_CODEC != SWCODEC */
420 scrobbler_init();
422 audio_init();
424 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
425 pcm_rec_init();
426 #endif
428 settings_apply_skins();
431 #else
433 static void init(void) INIT_ATTR;
434 static void init(void)
436 int rc;
437 bool mounted = false;
438 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
439 /* if nobody initialized ATA before, I consider this a cold start */
440 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
441 #endif
443 system_init();
444 core_allocator_init();
445 kernel_init();
447 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
448 set_cpu_frequency(CPUFREQ_NORMAL);
449 #ifdef CPU_COLDFIRE
450 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
451 #endif
452 cpu_boost(true);
453 #endif
455 i2c_init();
457 power_init();
459 enable_irq();
460 #ifdef CPU_ARM
461 enable_fiq();
462 #endif
463 /* current_tick should be ticking by now */
464 CHART("ticking");
466 lcd_init();
467 #ifdef HAVE_REMOTE_LCD
468 lcd_remote_init();
469 #endif
470 #ifdef HAVE_LCD_BITMAP
471 FOR_NB_SCREENS(i)
472 global_status.font_id[i] = FONT_SYSFIXED;
473 font_init();
474 #endif
476 settings_reset();
478 CHART(">show_logo");
479 show_logo();
480 CHART("<show_logo");
481 lang_init(core_language_builtin, language_strings,
482 LANG_LAST_INDEX_IN_ARRAY);
484 #ifdef DEBUG
485 debug_init();
486 #else
487 #ifdef HAVE_SERIAL
488 serial_setup();
489 #endif
490 #endif
492 #if CONFIG_RTC
493 rtc_init();
494 #endif
495 #ifdef HAVE_RTC_RAM
496 CHART(">settings_load(RTC)");
497 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
498 CHART("<settings_load(RTC)");
499 #endif
501 adc_init();
503 usb_init();
504 #if CONFIG_USBOTG == USBOTG_ISP1362
505 isp1362_init();
506 #elif CONFIG_USBOTG == USBOTG_M5636
507 m5636_init();
508 #endif
510 backlight_init();
512 button_init();
514 /* Don't initialize power management here if it could incorrectly
515 * measure battery voltage, and it's not needed for charging. */
516 #if !defined(NEED_ATA_POWER_BATT_MEASURE) || \
517 (CONFIG_CHARGING > CHARGING_MONITOR)
518 powermgmt_init();
519 #endif
521 #if CONFIG_TUNER
522 radio_init();
523 #endif
525 #ifdef HAVE_HARDWARE_CLICK
526 piezo_init();
527 #endif
529 /* Keep the order of this 3 (viewportmanager handles statusbars)
530 * Must be done before any code uses the multi-screen API */
531 CHART(">gui_syncstatusbar_init");
532 gui_syncstatusbar_init(&statusbars);
533 CHART("<gui_syncstatusbar_init");
534 CHART(">sb_skin_init");
535 sb_skin_init();
536 CHART("<sb_skin_init");
537 CHART(">gui_sync_wps_init");
538 gui_sync_skin_init();
539 CHART("<gui_sync_wps_init");
540 CHART(">viewportmanager_init");
541 viewportmanager_init();
542 CHART("<viewportmanager_init");
544 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
545 /* charger_inserted() can't be used here because power_thread()
546 hasn't checked power_input_status() yet */
547 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
548 && !global_settings.car_adapter_mode
549 #ifdef ATA_POWER_PLAYERSTYLE
550 && !ide_powered() /* relies on probing result from bootloader */
551 #endif
554 rc = charging_screen(); /* display a "charging" screen */
555 if (rc == 1) /* charger removed */
556 power_off();
557 /* "On" pressed or USB connected: proceed */
558 show_logo(); /* again, to provide better visual feedback */
560 #endif
563 disk_init_subsystem();
564 CHART(">storage_init");
565 rc = storage_init();
566 CHART("<storage_init");
567 if(rc)
569 #ifdef HAVE_LCD_BITMAP
570 lcd_clear_display();
571 lcd_putsf(0, 1, "ATA error: %d", rc);
572 lcd_puts(0, 3, "Press ON to debug");
573 lcd_update();
574 while(!(button_get(true) & BUTTON_REL)); /* DO NOT CHANGE TO ACTION SYSTEM */
575 dbg_ports();
576 #endif
577 panicf("ata: %d", rc);
580 #if defined(NEED_ATA_POWER_BATT_MEASURE) && \
581 (CONFIG_CHARGING <= CHARGING_MONITOR)
582 /* After storage_init(), ATA power must be on, so battery voltage
583 * can be measured. Initialize power management if it was delayed. */
584 powermgmt_init();
585 #endif
586 #ifdef HAVE_EEPROM_SETTINGS
587 CHART(">eeprom_settings_init");
588 eeprom_settings_init();
589 CHART("<eeprom_settings_init");
590 #endif
592 #ifndef HAVE_USBSTACK
593 usb_start_monitoring();
594 while (usb_detect() == USB_INSERTED)
596 #ifdef HAVE_EEPROM_SETTINGS
597 firmware_settings.disk_clean = false;
598 #endif
599 /* enter USB mode early, before trying to mount */
600 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
601 #if (CONFIG_STORAGE & STORAGE_MMC)
602 if (!mmc_touched() ||
603 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
604 #endif
606 gui_usb_screen_run(true);
607 mounted = true; /* mounting done @ end of USB mode */
609 #ifdef HAVE_USB_POWER
610 if (usb_powered()) /* avoid deadlock */
611 break;
612 #endif
614 #endif
616 if (!mounted)
618 CHART(">disk_mount_all");
619 rc = disk_mount_all();
620 CHART("<disk_mount_all");
621 if (rc<=0)
623 lcd_clear_display();
624 lcd_puts(0, 0, "No partition");
625 lcd_puts(0, 1, "found.");
626 #ifdef HAVE_LCD_BITMAP
627 lcd_puts(0, 2, "Insert USB cable");
628 lcd_puts(0, 3, "and fix it.");
629 #endif
630 lcd_update();
632 while(button_get(true) != SYS_USB_CONNECTED) {};
633 gui_usb_screen_run(true);
634 system_reboot();
638 #if CONFIG_CODEC == SWCODEC
639 dsp_init();
640 #endif
642 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
643 (CONFIG_KEYPAD == IRIVER_H10_PAD)
644 #ifdef SETTINGS_RESET
645 /* Reset settings if holding the reset button. (Rec on Archos,
646 A on Gigabeat) */
647 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
648 #else
649 /* Reset settings if the hold button is turned on */
650 if (button_hold())
651 #endif
653 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
654 settings_reset();
656 else
657 #endif
659 CHART(">settings_load(ALL)");
660 settings_load(SETTINGS_ALL);
661 CHART("<settings_load(ALL)");
664 CHART(">init_dircache(true)");
665 rc = init_dircache(true);
666 CHART("<init_dircache(true)");
667 if (rc < 0)
669 #ifdef HAVE_TAGCACHE
670 remove(TAGCACHE_STATEFILE);
671 #endif
674 CHART(">settings_apply(true)");
675 settings_apply(true);
676 CHART("<settings_apply(true)");
677 CHART(">init_dircache(false)");
678 init_dircache(false);
679 CHART("<init_dircache(false)");
680 #ifdef HAVE_TAGCACHE
681 CHART(">init_tagcache");
682 init_tagcache();
683 CHART("<init_tagcache");
684 #endif
686 #ifdef HAVE_EEPROM_SETTINGS
687 if (firmware_settings.initialized)
689 /* In case we crash. */
690 firmware_settings.disk_clean = false;
691 CHART(">eeprom_settings_store");
692 eeprom_settings_store();
693 CHART("<eeprom_settings_store");
695 #endif
696 playlist_init();
697 tree_mem_init();
698 filetype_init();
699 scrobbler_init();
700 shortcuts_init();
702 #if CONFIG_CODEC != SWCODEC
703 /* No buffer allocation (see buffer.c) may take place after the call to
704 audio_init() since the mpeg thread takes the rest of the buffer space */
705 mp3_init( global_settings.volume,
706 global_settings.bass,
707 global_settings.treble,
708 global_settings.balance,
709 global_settings.loudness,
710 global_settings.avc,
711 global_settings.channel_config,
712 global_settings.stereo_width,
713 global_settings.mdb_strength,
714 global_settings.mdb_harmonics,
715 global_settings.mdb_center,
716 global_settings.mdb_shape,
717 global_settings.mdb_enable,
718 global_settings.superbass);
719 #endif /* CONFIG_CODEC != SWCODEC */
721 CHART(">audio_init");
722 audio_init();
723 CHART("<audio_init");
725 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
726 pcm_rec_init();
727 #endif
729 /* runtime database has to be initialized after audio_init() */
730 cpu_boost(false);
732 #if CONFIG_CHARGING
733 car_adapter_mode_init();
734 #endif
735 #ifdef IPOD_ACCESSORY_PROTOCOL
736 iap_setup(global_settings.serial_bitrate);
737 #endif
738 #ifdef HAVE_ACCESSORY_SUPPLY
739 accessory_supply_set(global_settings.accessory_supply);
740 #endif
741 #ifdef HAVE_LINEOUT_POWEROFF
742 lineout_set(global_settings.lineout_active);
743 #endif
744 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
745 CHART("<check_bootfile(false)");
746 check_bootfile(false); /* remember write time and filesize */
747 CHART(">check_bootfile(false)");
748 #endif
749 CHART("<settings_apply_skins");
750 settings_apply_skins();
751 CHART(">settings_apply_skins");
754 #ifdef CPU_PP
755 void cop_main(void) MAIN_NORETURN_ATTR;
756 void cop_main(void)
758 /* This is the entry point for the coprocessor
759 Anyone not running an upgraded bootloader will never reach this point,
760 so it should not be assumed that the coprocessor be usable even on
761 platforms which support it.
763 A kernel thread is initially setup on the coprocessor and immediately
764 destroyed for purposes of continuity. The cop sits idle until at least
765 one thread exists on it. */
767 #if NUM_CORES > 1
768 system_init();
769 kernel_init();
770 /* This should never be reached */
771 #endif
772 while(1) {
773 sleep_core(COP);
776 #endif /* CPU_PP */
778 #endif /* SIMULATOR */