Fix buttonbar and line padding in time&date screen.
[maemo-rb.git] / apps / main.c
blob8f635ed9b16c4b720c3a20f9fa6902435975280e
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
83 #ifdef IPOD_ACCESSORY_PROTOCOL
84 #include "iap.h"
85 #endif
87 #if (CONFIG_CODEC == SWCODEC)
88 #include "playback.h"
89 #include "tdspeed.h"
90 #endif
91 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
92 #include "pcm_record.h"
93 #endif
95 #ifdef BUTTON_REC
96 #define SETTINGS_RESET BUTTON_REC
97 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
98 #define SETTINGS_RESET BUTTON_A
99 #endif
101 #if CONFIG_TUNER
102 #include "radio.h"
103 #endif
104 #if (CONFIG_STORAGE & STORAGE_MMC)
105 #include "ata_mmc.h"
106 #endif
108 #ifdef HAVE_REMOTE_LCD
109 #include "lcd-remote.h"
110 #endif
112 #if CONFIG_USBOTG == USBOTG_ISP1362
113 #include "isp1362.h"
114 #endif
116 #if CONFIG_USBOTG == USBOTG_M5636
117 #include "m5636.h"
118 #endif
120 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
121 #define MAIN_NORETURN_ATTR NORETURN_ATTR
122 #else
123 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
124 * with noreturn attribute */
125 #define MAIN_NORETURN_ATTR
126 #endif
128 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
129 #include "sim_tasks.h"
130 #include "system-sdl.h"
131 #define HAVE_ARGV_MAIN
132 /* Don't use SDL_main on windows -> no more stdio redirection */
133 #if defined(WIN32)
134 #undef main
135 #endif
136 #endif
138 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
140 static void init(void);
141 /* main(), and various functions called by main() and init() may be
142 * be INIT_ATTR. These functions must not be called after the final call
143 * to root_menu() at the end of main()
144 * see definition of INIT_ATTR in config.h */
145 #ifdef HAVE_ARGV_MAIN
146 int main(int argc, char *argv[]) INIT_ATTR MAIN_NORETURN_ATTR ;
147 int main(int argc, char *argv[])
149 sys_handle_argv(argc, argv);
150 #else
151 int main(void) INIT_ATTR MAIN_NORETURN_ATTR;
152 int main(void)
154 #endif
155 CHART(">init");
156 init();
157 CHART("<init");
158 FOR_NB_SCREENS(i)
160 screens[i].clear_display();
161 screens[i].update();
163 #ifdef HAVE_LCD_BITMAP
164 list_init();
165 #endif
166 tree_gui_init();
167 /* Keep the order of this 3
168 * Must be done before any code uses the multi-screen API */
169 #ifdef HAVE_USBSTACK
170 /* All threads should be created and public queues registered by now */
171 usb_start_monitoring();
172 #endif
174 #ifdef AUTOROCK
176 char filename[MAX_PATH];
177 const char *file =
178 #ifdef APPLICATION
179 ROCKBOX_DIR
180 #else
181 PLUGIN_APPS_DIR
182 #endif
183 "/autostart.rock";
184 if(file_exists(file)) /* no complaint if it doesn't exist */
186 plugin_load(file, NULL); /* start if it does */
189 #endif /* #ifdef AUTOROCK */
191 global_status.last_volume_change = 0;
192 /* no calls INIT_ATTR functions after this point anymore!
193 * see definition of INIT_ATTR in config.h */
194 CHART(">root_menu");
195 root_menu();
198 static int init_dircache(bool preinit) INIT_ATTR;
199 static int init_dircache(bool preinit)
201 #ifdef HAVE_DIRCACHE
202 int result = 0;
203 bool clear = false;
205 if (preinit)
206 dircache_init();
208 if (!global_settings.dircache)
209 return 0;
211 # ifdef HAVE_EEPROM_SETTINGS
212 if (firmware_settings.initialized && firmware_settings.disk_clean
213 && preinit)
215 result = dircache_load();
217 if (result < 0)
219 firmware_settings.disk_clean = false;
220 if (global_status.dircache_size <= 0)
222 /* This will be in default language, settings are not
223 applied yet. Not really any easy way to fix that. */
224 splash(0, str(LANG_SCANNING_DISK));
225 clear = true;
228 dircache_build(global_status.dircache_size);
231 else
232 # endif
234 if (preinit)
235 return -1;
237 if (!dircache_is_enabled()
238 && !dircache_is_initializing())
240 if (global_status.dircache_size <= 0)
242 splash(0, str(LANG_SCANNING_DISK));
243 clear = true;
245 result = dircache_build(global_status.dircache_size);
248 if (result < 0)
250 /* Initialization of dircache failed. Manual action is
251 * necessary to enable dircache again.
253 splashf(0, "Dircache failed, disabled. Result: %d", result);
254 global_settings.dircache = false;
258 if (clear)
260 backlight_on();
261 show_logo();
262 global_status.dircache_size = dircache_get_cache_size();
263 status_save();
266 return result;
267 #else
268 (void)preinit;
269 return 0;
270 #endif
273 #ifdef HAVE_TAGCACHE
274 static void init_tagcache(void) INIT_ATTR;
275 static void init_tagcache(void)
277 bool clear = false;
278 #if CONFIG_CODEC == SWCODEC
279 long talked_tick = 0;
280 #endif
281 tagcache_init();
283 while (!tagcache_is_initialized())
285 int ret = tagcache_get_commit_step();
287 if (ret > 0)
289 #if CONFIG_CODEC == SWCODEC
290 /* hwcodec can't use voice here, as the database commit
291 * uses the audio buffer. */
292 if(global_settings.talk_menu
293 && (talked_tick == 0
294 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
296 talked_tick = current_tick;
297 talk_id(LANG_TAGCACHE_INIT, false);
298 talk_number(ret, true);
299 talk_id(VOICE_OF, true);
300 talk_number(tagcache_get_max_commit_step(), true);
302 #endif
303 #ifdef HAVE_LCD_BITMAP
304 if (lang_is_rtl())
306 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
307 str(LANG_TAGCACHE_INIT));
309 else
311 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
312 tagcache_get_max_commit_step());
314 #else
315 lcd_double_height(false);
316 lcd_putsf(0, 1, " DB [%d/%d]", ret,
317 tagcache_get_max_commit_step());
318 lcd_update();
319 #endif
320 clear = true;
322 sleep(HZ/4);
324 tagtree_init();
326 if (clear)
328 backlight_on();
329 show_logo();
332 #endif
334 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
336 static void init(void)
338 system_init();
339 core_allocator_init();
340 kernel_init();
341 #ifdef APPLICATION
342 paths_init();
343 #endif
344 enable_irq();
345 lcd_init();
346 #ifdef HAVE_REMOTE_LCD
347 lcd_remote_init();
348 #endif
349 #ifdef HAVE_LCD_BITMAP
350 FOR_NB_SCREENS(i)
351 global_status.font_id[i] = FONT_SYSFIXED;
352 font_init();
353 #endif
354 show_logo();
355 button_init();
356 powermgmt_init();
357 backlight_init();
358 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
359 sim_tasks_init();
360 #endif
361 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
362 notification_init();
363 #endif
364 lang_init(core_language_builtin, language_strings,
365 LANG_LAST_INDEX_IN_ARRAY);
366 #ifdef DEBUG
367 debug_init();
368 #endif
369 /* Keep the order of this 3 (viewportmanager handles statusbars)
370 * Must be done before any code uses the multi-screen API */
371 gui_syncstatusbar_init(&statusbars);
372 gui_sync_skin_init();
373 sb_skin_init();
374 viewportmanager_init();
376 storage_init();
377 settings_reset();
378 settings_load(SETTINGS_ALL);
379 settings_apply(true);
380 init_dircache(true);
381 init_dircache(false);
382 #ifdef HAVE_TAGCACHE
383 init_tagcache();
384 #endif
385 sleep(HZ/2);
386 tree_mem_init();
387 filetype_init();
388 playlist_init();
389 theme_init_buffer();
391 #if CONFIG_CODEC != SWCODEC
392 mp3_init( global_settings.volume,
393 global_settings.bass,
394 global_settings.treble,
395 global_settings.balance,
396 global_settings.loudness,
397 global_settings.avc,
398 global_settings.channel_config,
399 global_settings.stereo_width,
400 global_settings.mdb_strength,
401 global_settings.mdb_harmonics,
402 global_settings.mdb_center,
403 global_settings.mdb_shape,
404 global_settings.mdb_enable,
405 global_settings.superbass);
406 #endif /* CONFIG_CODEC != SWCODEC */
408 scrobbler_init();
410 audio_init();
412 settings_apply_skins();
415 #else
417 static void init(void) INIT_ATTR;
418 static void init(void)
420 int rc;
421 bool mounted = false;
422 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
423 /* if nobody initialized ATA before, I consider this a cold start */
424 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
425 #endif
427 system_init();
428 core_allocator_init();
429 kernel_init();
431 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
432 set_cpu_frequency(CPUFREQ_NORMAL);
433 #ifdef CPU_COLDFIRE
434 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
435 #endif
436 cpu_boost(true);
437 #endif
439 i2c_init();
441 power_init();
443 enable_irq();
444 #ifdef CPU_ARM
445 enable_fiq();
446 #endif
447 /* current_tick should be ticking by now */
448 CHART("ticking");
450 lcd_init();
451 #ifdef HAVE_REMOTE_LCD
452 lcd_remote_init();
453 #endif
454 #ifdef HAVE_LCD_BITMAP
455 FOR_NB_SCREENS(i)
456 global_status.font_id[i] = FONT_SYSFIXED;
457 font_init();
458 #endif
460 settings_reset();
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_skin_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(true);
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(true);
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 theme_init_buffer();
667 #if CONFIG_CODEC != SWCODEC
668 /* No buffer allocation (see buffer.c) may take place after the call to
669 audio_init() since the mpeg thread takes the rest of the buffer space */
670 mp3_init( global_settings.volume,
671 global_settings.bass,
672 global_settings.treble,
673 global_settings.balance,
674 global_settings.loudness,
675 global_settings.avc,
676 global_settings.channel_config,
677 global_settings.stereo_width,
678 global_settings.mdb_strength,
679 global_settings.mdb_harmonics,
680 global_settings.mdb_center,
681 global_settings.mdb_shape,
682 global_settings.mdb_enable,
683 global_settings.superbass);
684 #endif /* CONFIG_CODEC != SWCODEC */
686 CHART(">audio_init");
687 audio_init();
688 CHART("<audio_init");
690 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
691 pcm_rec_init();
692 #endif
694 /* runtime database has to be initialized after audio_init() */
695 cpu_boost(false);
697 #if CONFIG_CHARGING
698 car_adapter_mode_init();
699 #endif
700 #ifdef IPOD_ACCESSORY_PROTOCOL
701 iap_setup(global_settings.serial_bitrate);
702 #endif
703 #ifdef HAVE_ACCESSORY_SUPPLY
704 accessory_supply_set(global_settings.accessory_supply);
705 #endif
706 #ifdef HAVE_LINEOUT_POWEROFF
707 lineout_set(global_settings.lineout_active);
708 #endif
709 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
710 CHART("<check_bootfile(false)");
711 check_bootfile(false); /* remember write time and filesize */
712 CHART(">check_bootfile(false)");
713 #endif
714 CHART("<settings_apply_skins");
715 settings_apply_skins();
716 CHART(">settings_apply_skins");
719 #ifdef CPU_PP
720 void cop_main(void) MAIN_NORETURN_ATTR;
721 void cop_main(void)
723 /* This is the entry point for the coprocessor
724 Anyone not running an upgraded bootloader will never reach this point,
725 so it should not be assumed that the coprocessor be usable even on
726 platforms which support it.
728 A kernel thread is initially setup on the coprocessor and immediately
729 destroyed for purposes of continuity. The cop sits idle until at least
730 one thread exists on it. */
732 #if NUM_CORES > 1
733 system_init();
734 kernel_init();
735 /* This should never be reached */
736 #endif
737 while(1) {
738 sleep_core(COP);
741 #endif /* CPU_PP */
743 #endif /* SIMULATOR */