Merge tag 'v3.13-final' into maemo-port
[maemo-rb.git] / apps / main.c
blob6b6566c7ca1b9241ebfff6f477d73784707e8a1c
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 #include "logdiskf.h"
80 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
81 #include "notification.h"
82 #endif
83 #include "shortcuts.h"
85 #ifdef IPOD_ACCESSORY_PROTOCOL
86 #include "iap.h"
87 #endif
89 #if (CONFIG_CODEC == SWCODEC)
90 #include "playback.h"
91 #include "tdspeed.h"
92 #endif
93 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
94 #include "pcm_record.h"
95 #endif
97 #ifdef BUTTON_REC
98 #define SETTINGS_RESET BUTTON_REC
99 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
100 #define SETTINGS_RESET BUTTON_A
101 #endif
103 #if CONFIG_TUNER
104 #include "radio.h"
105 #endif
106 #if (CONFIG_STORAGE & STORAGE_MMC)
107 #include "ata_mmc.h"
108 #endif
110 #ifdef HAVE_REMOTE_LCD
111 #include "lcd-remote.h"
112 #endif
114 #if CONFIG_USBOTG == USBOTG_ISP1362
115 #include "isp1362.h"
116 #endif
118 #if CONFIG_USBOTG == USBOTG_M5636
119 #include "m5636.h"
120 #endif
122 #ifdef HAVE_HARDWARE_CLICK
123 #include "piezo.h"
124 #endif
126 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
127 #define MAIN_NORETURN_ATTR NORETURN_ATTR
128 #else
129 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
130 * with noreturn attribute */
131 #define MAIN_NORETURN_ATTR
132 #endif
134 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
135 #ifdef SIMULATOR
136 #include "sim_tasks.h"
137 #endif
138 #include "system-sdl.h"
139 #define HAVE_ARGV_MAIN
140 /* Don't use SDL_main on windows -> no more stdio redirection */
141 #if defined(WIN32)
142 #undef main
143 #endif
144 #endif
146 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
148 static void init(void);
149 /* main(), and various functions called by main() and init() may be
150 * be INIT_ATTR. These functions must not be called after the final call
151 * to root_menu() at the end of main()
152 * see definition of INIT_ATTR in config.h */
153 #ifdef HAVE_ARGV_MAIN
154 int main(int argc, char *argv[]) INIT_ATTR MAIN_NORETURN_ATTR ;
155 int main(int argc, char *argv[])
157 sys_handle_argv(argc, argv);
158 #else
159 int main(void) INIT_ATTR MAIN_NORETURN_ATTR;
160 int main(void)
162 #endif
163 CHART(">init");
164 init();
165 CHART("<init");
166 FOR_NB_SCREENS(i)
168 screens[i].clear_display();
169 screens[i].update();
171 #ifdef HAVE_LCD_BITMAP
172 list_init();
173 #endif
174 tree_gui_init();
175 /* Keep the order of this 3
176 * Must be done before any code uses the multi-screen API */
177 #ifdef HAVE_USBSTACK
178 /* All threads should be created and public queues registered by now */
179 usb_start_monitoring();
180 #endif
182 #ifdef AUTOROCK
184 char filename[MAX_PATH];
185 const char *file =
186 #ifdef APPLICATION
187 ROCKBOX_DIR
188 #else
189 PLUGIN_APPS_DIR
190 #endif
191 "/autostart.rock";
192 if(file_exists(file)) /* no complaint if it doesn't exist */
194 plugin_load(file, NULL); /* start if it does */
197 #endif /* #ifdef AUTOROCK */
199 global_status.last_volume_change = 0;
200 /* no calls INIT_ATTR functions after this point anymore!
201 * see definition of INIT_ATTR in config.h */
202 CHART(">root_menu");
203 root_menu();
206 static int init_dircache(bool preinit) INIT_ATTR;
207 static int init_dircache(bool preinit)
209 #ifdef HAVE_DIRCACHE
210 int result = 0;
211 bool clear = false;
213 if (preinit)
214 dircache_init();
216 if (!global_settings.dircache)
217 return 0;
219 # ifdef HAVE_EEPROM_SETTINGS
220 if (firmware_settings.initialized && firmware_settings.disk_clean
221 && preinit)
223 result = dircache_load();
225 if (result < 0)
227 firmware_settings.disk_clean = false;
228 if (global_status.dircache_size <= 0)
230 /* This will be in default language, settings are not
231 applied yet. Not really any easy way to fix that. */
232 splash(0, str(LANG_SCANNING_DISK));
233 clear = true;
236 dircache_build(global_status.dircache_size);
239 else
240 # endif
242 if (preinit)
243 return -1;
245 if (!dircache_is_enabled()
246 && !dircache_is_initializing())
248 if (global_status.dircache_size <= 0)
250 splash(0, str(LANG_SCANNING_DISK));
251 clear = true;
253 result = dircache_build(global_status.dircache_size);
256 if (result < 0)
258 /* Initialization of dircache failed. Manual action is
259 * necessary to enable dircache again.
261 splashf(0, "Dircache failed, disabled. Result: %d", result);
262 global_settings.dircache = false;
266 if (clear)
268 backlight_on();
269 show_logo();
270 global_status.dircache_size = dircache_get_cache_size();
271 status_save();
274 return result;
275 #else
276 (void)preinit;
277 return 0;
278 #endif
281 #ifdef HAVE_TAGCACHE
282 static void init_tagcache(void) INIT_ATTR;
283 static void init_tagcache(void)
285 bool clear = false;
286 #if 0 /* CONFIG_CODEC == SWCODEC */
287 long talked_tick = 0;
288 #endif
289 tagcache_init();
291 while (!tagcache_is_initialized())
293 int ret = tagcache_get_commit_step();
295 if (ret > 0)
297 #if 0 /* FIXME: Audio isn't even initialized yet! */ /* CONFIG_CODEC == SWCODEC */
298 /* hwcodec can't use voice here, as the database commit
299 * uses the audio buffer. */
300 if(global_settings.talk_menu
301 && (talked_tick == 0
302 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
304 talked_tick = current_tick;
305 talk_id(LANG_TAGCACHE_INIT, false);
306 talk_number(ret, true);
307 talk_id(VOICE_OF, true);
308 talk_number(tagcache_get_max_commit_step(), true);
310 #endif
311 #ifdef HAVE_LCD_BITMAP
312 if (lang_is_rtl())
314 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
315 str(LANG_TAGCACHE_INIT));
317 else
319 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
320 tagcache_get_max_commit_step());
322 #else
323 lcd_double_height(false);
324 lcd_putsf(0, 1, " DB [%d/%d]", ret,
325 tagcache_get_max_commit_step());
326 lcd_update();
327 #endif
328 clear = true;
330 sleep(HZ/4);
332 tagtree_init();
334 if (clear)
336 backlight_on();
337 show_logo();
340 #endif
342 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
344 static void init(void)
346 system_init();
347 core_allocator_init();
348 kernel_init();
349 #ifdef APPLICATION
350 paths_init();
351 #endif
352 enable_irq();
353 lcd_init();
354 #ifdef HAVE_REMOTE_LCD
355 lcd_remote_init();
356 #endif
357 #ifdef HAVE_LCD_BITMAP
358 FOR_NB_SCREENS(i)
359 global_status.font_id[i] = FONT_SYSFIXED;
360 font_init();
361 #endif
362 show_logo();
363 button_init();
364 powermgmt_init();
365 backlight_init();
366 #ifdef SIMULATOR
367 sim_tasks_init();
368 #endif
369 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
370 notification_init();
371 #endif
372 lang_init(core_language_builtin, language_strings,
373 LANG_LAST_INDEX_IN_ARRAY);
374 #ifdef DEBUG
375 debug_init();
376 #endif
377 #if CONFIG_TUNER
378 radio_init();
379 #endif
380 /* Keep the order of this 3 (viewportmanager handles statusbars)
381 * Must be done before any code uses the multi-screen API */
382 gui_syncstatusbar_init(&statusbars);
383 gui_sync_skin_init();
384 sb_skin_init();
385 viewportmanager_init();
387 storage_init();
388 #if CONFIG_CODEC == SWCODEC
389 dsp_init();
390 #endif
391 settings_reset();
392 settings_load(SETTINGS_ALL);
393 settings_apply(true);
394 init_dircache(true);
395 init_dircache(false);
396 #ifdef HAVE_TAGCACHE
397 init_tagcache();
398 #endif
399 tree_mem_init();
400 filetype_init();
401 playlist_init();
402 shortcuts_init();
404 #if CONFIG_CODEC != SWCODEC
405 mp3_init( global_settings.volume,
406 global_settings.bass,
407 global_settings.treble,
408 global_settings.balance,
409 global_settings.loudness,
410 global_settings.avc,
411 global_settings.channel_config,
412 global_settings.stereo_width,
413 global_settings.mdb_strength,
414 global_settings.mdb_harmonics,
415 global_settings.mdb_center,
416 global_settings.mdb_shape,
417 global_settings.mdb_enable,
418 global_settings.superbass);
419 #endif /* CONFIG_CODEC != SWCODEC */
421 scrobbler_init();
423 audio_init();
425 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
426 pcm_rec_init();
427 #endif
429 settings_apply_skins();
432 #else
434 static void init(void) INIT_ATTR;
435 static void init(void)
437 int rc;
438 bool mounted = false;
439 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
440 /* if nobody initialized ATA before, I consider this a cold start */
441 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
442 #endif
444 system_init();
445 core_allocator_init();
446 kernel_init();
448 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
449 set_cpu_frequency(CPUFREQ_NORMAL);
450 #ifdef CPU_COLDFIRE
451 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
452 #endif
453 cpu_boost(true);
454 #endif
456 i2c_init();
458 power_init();
460 enable_irq();
461 #ifdef CPU_ARM
462 enable_fiq();
463 #endif
464 /* current_tick should be ticking by now */
465 CHART("ticking");
467 lcd_init();
468 #ifdef HAVE_REMOTE_LCD
469 lcd_remote_init();
470 #endif
471 #ifdef HAVE_LCD_BITMAP
472 FOR_NB_SCREENS(i)
473 global_status.font_id[i] = FONT_SYSFIXED;
474 font_init();
475 #endif
477 settings_reset();
479 CHART(">show_logo");
480 show_logo();
481 CHART("<show_logo");
482 lang_init(core_language_builtin, language_strings,
483 LANG_LAST_INDEX_IN_ARRAY);
485 #ifdef DEBUG
486 debug_init();
487 #else
488 #ifdef HAVE_SERIAL
489 serial_setup();
490 #endif
491 #endif
493 #ifdef ROCKBOX_HAS_LOGDISKF
494 init_logdiskf();
495 #endif
497 #if CONFIG_RTC
498 rtc_init();
499 #endif
500 #ifdef HAVE_RTC_RAM
501 CHART(">settings_load(RTC)");
502 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
503 CHART("<settings_load(RTC)");
504 #endif
506 adc_init();
508 usb_init();
509 #if CONFIG_USBOTG == USBOTG_ISP1362
510 isp1362_init();
511 #elif CONFIG_USBOTG == USBOTG_M5636
512 m5636_init();
513 #endif
515 backlight_init();
517 button_init();
519 /* Don't initialize power management here if it could incorrectly
520 * measure battery voltage, and it's not needed for charging. */
521 #if !defined(NEED_ATA_POWER_BATT_MEASURE) || \
522 (CONFIG_CHARGING > CHARGING_MONITOR)
523 powermgmt_init();
524 #endif
526 #if CONFIG_TUNER
527 radio_init();
528 #endif
530 #ifdef HAVE_HARDWARE_CLICK
531 piezo_init();
532 #endif
534 /* Keep the order of this 3 (viewportmanager handles statusbars)
535 * Must be done before any code uses the multi-screen API */
536 CHART(">gui_syncstatusbar_init");
537 gui_syncstatusbar_init(&statusbars);
538 CHART("<gui_syncstatusbar_init");
539 CHART(">sb_skin_init");
540 sb_skin_init();
541 CHART("<sb_skin_init");
542 CHART(">gui_sync_wps_init");
543 gui_sync_skin_init();
544 CHART("<gui_sync_wps_init");
545 CHART(">viewportmanager_init");
546 viewportmanager_init();
547 CHART("<viewportmanager_init");
549 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
550 /* charger_inserted() can't be used here because power_thread()
551 hasn't checked power_input_status() yet */
552 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
553 && !global_settings.car_adapter_mode
554 #ifdef ATA_POWER_PLAYERSTYLE
555 && !ide_powered() /* relies on probing result from bootloader */
556 #endif
559 rc = charging_screen(); /* display a "charging" screen */
560 if (rc == 1) /* charger removed */
561 power_off();
562 /* "On" pressed or USB connected: proceed */
563 show_logo(); /* again, to provide better visual feedback */
565 #endif
568 disk_init_subsystem();
569 CHART(">storage_init");
570 rc = storage_init();
571 CHART("<storage_init");
572 if(rc)
574 #ifdef HAVE_LCD_BITMAP
575 lcd_clear_display();
576 lcd_putsf(0, 1, "ATA error: %d", rc);
577 lcd_puts(0, 3, "Press ON to debug");
578 lcd_update();
579 while(!(button_get(true) & BUTTON_REL)); /* DO NOT CHANGE TO ACTION SYSTEM */
580 dbg_ports();
581 #endif
582 panicf("ata: %d", rc);
585 #if defined(NEED_ATA_POWER_BATT_MEASURE) && \
586 (CONFIG_CHARGING <= CHARGING_MONITOR)
587 /* After storage_init(), ATA power must be on, so battery voltage
588 * can be measured. Initialize power management if it was delayed. */
589 powermgmt_init();
590 #endif
591 #ifdef HAVE_EEPROM_SETTINGS
592 CHART(">eeprom_settings_init");
593 eeprom_settings_init();
594 CHART("<eeprom_settings_init");
595 #endif
597 #ifndef HAVE_USBSTACK
598 usb_start_monitoring();
599 while (usb_detect() == USB_INSERTED)
601 #ifdef HAVE_EEPROM_SETTINGS
602 firmware_settings.disk_clean = false;
603 #endif
604 /* enter USB mode early, before trying to mount */
605 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
606 #if (CONFIG_STORAGE & STORAGE_MMC)
607 if (!mmc_touched() ||
608 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
609 #endif
611 gui_usb_screen_run(true);
612 mounted = true; /* mounting done @ end of USB mode */
614 #ifdef HAVE_USB_POWER
615 if (usb_powered()) /* avoid deadlock */
616 break;
617 #endif
619 #endif
621 if (!mounted)
623 CHART(">disk_mount_all");
624 rc = disk_mount_all();
625 CHART("<disk_mount_all");
626 if (rc<=0)
628 lcd_clear_display();
629 lcd_puts(0, 0, "No partition");
630 lcd_puts(0, 1, "found.");
631 #ifdef HAVE_LCD_BITMAP
632 lcd_puts(0, 2, "Insert USB cable");
633 lcd_puts(0, 3, "and fix it.");
634 #endif
635 lcd_update();
637 while(button_get(true) != SYS_USB_CONNECTED) {};
638 gui_usb_screen_run(true);
639 system_reboot();
643 #if CONFIG_CODEC == SWCODEC
644 dsp_init();
645 #endif
647 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
648 (CONFIG_KEYPAD == IRIVER_H10_PAD)
649 #ifdef SETTINGS_RESET
650 /* Reset settings if holding the reset button. (Rec on Archos,
651 A on Gigabeat) */
652 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
653 #else
654 /* Reset settings if the hold button is turned on */
655 if (button_hold())
656 #endif
658 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
659 settings_reset();
661 else
662 #endif
664 CHART(">settings_load(ALL)");
665 settings_load(SETTINGS_ALL);
666 CHART("<settings_load(ALL)");
669 CHART(">init_dircache(true)");
670 rc = init_dircache(true);
671 CHART("<init_dircache(true)");
672 if (rc < 0)
674 #ifdef HAVE_TAGCACHE
675 remove(TAGCACHE_STATEFILE);
676 #endif
679 CHART(">settings_apply(true)");
680 settings_apply(true);
681 CHART("<settings_apply(true)");
682 CHART(">init_dircache(false)");
683 init_dircache(false);
684 CHART("<init_dircache(false)");
685 #ifdef HAVE_TAGCACHE
686 CHART(">init_tagcache");
687 init_tagcache();
688 CHART("<init_tagcache");
689 #endif
691 #ifdef HAVE_EEPROM_SETTINGS
692 if (firmware_settings.initialized)
694 /* In case we crash. */
695 firmware_settings.disk_clean = false;
696 CHART(">eeprom_settings_store");
697 eeprom_settings_store();
698 CHART("<eeprom_settings_store");
700 #endif
701 playlist_init();
702 tree_mem_init();
703 filetype_init();
704 scrobbler_init();
705 shortcuts_init();
707 #if CONFIG_CODEC != SWCODEC
708 /* No buffer allocation (see buffer.c) may take place after the call to
709 audio_init() since the mpeg thread takes the rest of the buffer space */
710 mp3_init( global_settings.volume,
711 global_settings.bass,
712 global_settings.treble,
713 global_settings.balance,
714 global_settings.loudness,
715 global_settings.avc,
716 global_settings.channel_config,
717 global_settings.stereo_width,
718 global_settings.mdb_strength,
719 global_settings.mdb_harmonics,
720 global_settings.mdb_center,
721 global_settings.mdb_shape,
722 global_settings.mdb_enable,
723 global_settings.superbass);
724 #endif /* CONFIG_CODEC != SWCODEC */
726 CHART(">audio_init");
727 audio_init();
728 CHART("<audio_init");
730 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
731 pcm_rec_init();
732 #endif
734 /* runtime database has to be initialized after audio_init() */
735 cpu_boost(false);
737 #if CONFIG_CHARGING
738 car_adapter_mode_init();
739 #endif
740 #ifdef IPOD_ACCESSORY_PROTOCOL
741 iap_setup(global_settings.serial_bitrate);
742 #endif
743 #ifdef HAVE_ACCESSORY_SUPPLY
744 accessory_supply_set(global_settings.accessory_supply);
745 #endif
746 #ifdef HAVE_LINEOUT_POWEROFF
747 lineout_set(global_settings.lineout_active);
748 #endif
749 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
750 CHART("<check_bootfile(false)");
751 check_bootfile(false); /* remember write time and filesize */
752 CHART(">check_bootfile(false)");
753 #endif
754 CHART("<settings_apply_skins");
755 settings_apply_skins();
756 CHART(">settings_apply_skins");
759 #ifdef CPU_PP
760 void cop_main(void) MAIN_NORETURN_ATTR;
761 void cop_main(void)
763 /* This is the entry point for the coprocessor
764 Anyone not running an upgraded bootloader will never reach this point,
765 so it should not be assumed that the coprocessor be usable even on
766 platforms which support it.
768 A kernel thread is initially setup on the coprocessor and immediately
769 destroyed for purposes of continuity. The cop sits idle until at least
770 one thread exists on it. */
772 #if NUM_CORES > 1
773 system_init();
774 kernel_init();
775 /* This should never be reached */
776 #endif
777 while(1) {
778 sleep_core(COP);
781 #endif /* CPU_PP */
783 #endif /* SIMULATOR */