Remove unecessary casting
[maemo-rb.git] / apps / main.c
blob07a8bba44cc778e092f7c012a4bd72711a39a416
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 int i;
156 CHART(">init");
157 init();
158 CHART("<init");
159 FOR_NB_SCREENS(i)
161 screens[i].clear_display();
162 screens[i].update();
164 #ifdef HAVE_LCD_BITMAP
165 list_init();
166 #endif
167 tree_gui_init();
168 /* Keep the order of this 3
169 * Must be done before any code uses the multi-screen API */
170 #ifdef HAVE_USBSTACK
171 /* All threads should be created and public queues registered by now */
172 usb_start_monitoring();
173 #endif
175 #ifdef AUTOROCK
177 char filename[MAX_PATH];
178 const char *file =
179 #ifdef APPLICATION
180 ROCKBOX_DIR
181 #else
182 PLUGIN_APPS_DIR
183 #endif
184 "/autostart.rock";
185 if(file_exists(file)) /* no complaint if it doesn't exist */
187 plugin_load(file, NULL); /* start if it does */
190 #endif /* #ifdef AUTOROCK */
192 global_status.last_volume_change = 0;
193 /* no calls INIT_ATTR functions after this point anymore!
194 * see definition of INIT_ATTR in config.h */
195 CHART(">root_menu");
196 root_menu();
199 static int init_dircache(bool preinit) INIT_ATTR;
200 static int init_dircache(bool preinit)
202 #ifdef HAVE_DIRCACHE
203 int result = 0;
204 bool clear = false;
206 if (preinit)
207 dircache_init();
209 if (!global_settings.dircache)
210 return 0;
212 # ifdef HAVE_EEPROM_SETTINGS
213 if (firmware_settings.initialized && firmware_settings.disk_clean
214 && preinit)
216 result = dircache_load();
218 if (result < 0)
220 firmware_settings.disk_clean = false;
221 if (global_status.dircache_size <= 0)
223 /* This will be in default language, settings are not
224 applied yet. Not really any easy way to fix that. */
225 splash(0, str(LANG_SCANNING_DISK));
226 clear = true;
229 dircache_build(global_status.dircache_size);
232 else
233 # endif
235 if (preinit)
236 return -1;
238 if (!dircache_is_enabled()
239 && !dircache_is_initializing())
241 if (global_status.dircache_size <= 0)
243 splash(0, str(LANG_SCANNING_DISK));
244 clear = true;
246 result = dircache_build(global_status.dircache_size);
249 if (result < 0)
251 /* Initialization of dircache failed. Manual action is
252 * necessary to enable dircache again.
254 splashf(0, "Dircache failed, disabled. Result: %d", result);
255 global_settings.dircache = false;
259 if (clear)
261 backlight_on();
262 show_logo();
263 global_status.dircache_size = dircache_get_cache_size();
264 status_save();
267 return result;
268 #else
269 (void)preinit;
270 return 0;
271 #endif
274 #ifdef HAVE_TAGCACHE
275 static void init_tagcache(void) INIT_ATTR;
276 static void init_tagcache(void)
278 bool clear = false;
279 #if CONFIG_CODEC == SWCODEC
280 long talked_tick = 0;
281 #endif
282 tagcache_init();
284 while (!tagcache_is_initialized())
286 int ret = tagcache_get_commit_step();
288 if (ret > 0)
290 #if CONFIG_CODEC == SWCODEC
291 /* hwcodec can't use voice here, as the database commit
292 * uses the audio buffer. */
293 if(global_settings.talk_menu
294 && (talked_tick == 0
295 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
297 talked_tick = current_tick;
298 talk_id(LANG_TAGCACHE_INIT, false);
299 talk_number(ret, true);
300 talk_id(VOICE_OF, true);
301 talk_number(tagcache_get_max_commit_step(), true);
303 #endif
304 #ifdef HAVE_LCD_BITMAP
305 if (lang_is_rtl())
307 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
308 str(LANG_TAGCACHE_INIT));
310 else
312 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
313 tagcache_get_max_commit_step());
315 #else
316 lcd_double_height(false);
317 lcd_putsf(0, 1, " DB [%d/%d]", ret,
318 tagcache_get_max_commit_step());
319 lcd_update();
320 #endif
321 clear = true;
323 sleep(HZ/4);
325 tagtree_init();
327 if (clear)
329 backlight_on();
330 show_logo();
333 #endif
335 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
337 static void init(void)
339 system_init();
340 core_allocator_init();
341 kernel_init();
342 #ifdef APPLICATION
343 paths_init();
344 #endif
345 enable_irq();
346 lcd_init();
347 #ifdef HAVE_REMOTE_LCD
348 lcd_remote_init();
349 #endif
350 font_init();
351 show_logo();
352 button_init();
353 powermgmt_init();
354 backlight_init();
355 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
356 sim_tasks_init();
357 #endif
358 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
359 notification_init();
360 #endif
361 lang_init(core_language_builtin, language_strings,
362 LANG_LAST_INDEX_IN_ARRAY);
363 #ifdef DEBUG
364 debug_init();
365 #endif
366 /* Keep the order of this 3 (viewportmanager handles statusbars)
367 * Must be done before any code uses the multi-screen API */
368 gui_syncstatusbar_init(&statusbars);
369 gui_sync_skin_init();
370 sb_skin_init();
371 viewportmanager_init();
373 storage_init();
374 settings_reset();
375 settings_load(SETTINGS_ALL);
376 settings_apply(true);
377 init_dircache(true);
378 init_dircache(false);
379 #ifdef HAVE_TAGCACHE
380 init_tagcache();
381 #endif
382 sleep(HZ/2);
383 tree_mem_init();
384 filetype_init();
385 playlist_init();
386 theme_init_buffer();
388 #if CONFIG_CODEC != SWCODEC
389 mp3_init( global_settings.volume,
390 global_settings.bass,
391 global_settings.treble,
392 global_settings.balance,
393 global_settings.loudness,
394 global_settings.avc,
395 global_settings.channel_config,
396 global_settings.stereo_width,
397 global_settings.mdb_strength,
398 global_settings.mdb_harmonics,
399 global_settings.mdb_center,
400 global_settings.mdb_shape,
401 global_settings.mdb_enable,
402 global_settings.superbass);
403 #endif /* CONFIG_CODEC != SWCODEC */
405 scrobbler_init();
407 audio_init();
409 settings_apply_skins();
412 #else
414 static void init(void) INIT_ATTR;
415 static void init(void)
417 int rc;
418 bool mounted = false;
419 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
420 /* if nobody initialized ATA before, I consider this a cold start */
421 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
422 #endif
424 system_init();
425 core_allocator_init();
426 kernel_init();
428 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
429 set_cpu_frequency(CPUFREQ_NORMAL);
430 #ifdef CPU_COLDFIRE
431 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
432 #endif
433 cpu_boost(true);
434 #endif
437 settings_reset();
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 font_init();
456 CHART(">show_logo");
457 show_logo();
458 CHART("<show_logo");
459 lang_init(core_language_builtin, language_strings,
460 LANG_LAST_INDEX_IN_ARRAY);
462 #ifdef DEBUG
463 debug_init();
464 #else
465 #ifdef HAVE_SERIAL
466 serial_setup();
467 #endif
468 #endif
470 #if CONFIG_RTC
471 rtc_init();
472 #endif
473 #ifdef HAVE_RTC_RAM
474 CHART(">settings_load(RTC)");
475 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
476 CHART("<settings_load(RTC)");
477 #endif
479 adc_init();
481 usb_init();
482 #if CONFIG_USBOTG == USBOTG_ISP1362
483 isp1362_init();
484 #elif CONFIG_USBOTG == USBOTG_M5636
485 m5636_init();
486 #endif
488 backlight_init();
490 button_init();
492 powermgmt_init();
494 #if CONFIG_TUNER
495 radio_init();
496 #endif
498 /* Keep the order of this 3 (viewportmanager handles statusbars)
499 * Must be done before any code uses the multi-screen API */
500 CHART(">gui_syncstatusbar_init");
501 gui_syncstatusbar_init(&statusbars);
502 CHART("<gui_syncstatusbar_init");
503 CHART(">sb_skin_init");
504 sb_skin_init();
505 CHART("<sb_skin_init");
506 CHART(">gui_sync_wps_init");
507 gui_sync_skin_init();
508 CHART("<gui_sync_wps_init");
509 CHART(">viewportmanager_init");
510 viewportmanager_init();
511 CHART("<viewportmanager_init");
513 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
514 /* charger_inserted() can't be used here because power_thread()
515 hasn't checked power_input_status() yet */
516 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
517 && !global_settings.car_adapter_mode
518 #ifdef ATA_POWER_PLAYERSTYLE
519 && !ide_powered() /* relies on probing result from bootloader */
520 #endif
523 rc = charging_screen(); /* display a "charging" screen */
524 if (rc == 1) /* charger removed */
525 power_off();
526 /* "On" pressed or USB connected: proceed */
527 show_logo(); /* again, to provide better visual feedback */
529 #endif
532 disk_init_subsystem();
533 CHART(">storage_init");
534 rc = storage_init();
535 CHART("<storage_init");
536 if(rc)
538 #ifdef HAVE_LCD_BITMAP
539 lcd_clear_display();
540 lcd_putsf(0, 1, "ATA error: %d", rc);
541 lcd_puts(0, 3, "Press ON to debug");
542 lcd_update();
543 while(!(button_get(true) & BUTTON_REL)); /* DO NOT CHANGE TO ACTION SYSTEM */
544 dbg_ports();
545 #endif
546 panicf("ata: %d", rc);
549 #ifdef HAVE_EEPROM_SETTINGS
550 CHART(">eeprom_settings_init");
551 eeprom_settings_init();
552 CHART("<eeprom_settings_init");
553 #endif
555 #ifndef HAVE_USBSTACK
556 usb_start_monitoring();
557 while (usb_detect() == USB_INSERTED)
559 #ifdef HAVE_EEPROM_SETTINGS
560 firmware_settings.disk_clean = false;
561 #endif
562 /* enter USB mode early, before trying to mount */
563 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
564 #if (CONFIG_STORAGE & STORAGE_MMC)
565 if (!mmc_touched() ||
566 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
567 #endif
569 gui_usb_screen_run(true);
570 mounted = true; /* mounting done @ end of USB mode */
572 #ifdef HAVE_USB_POWER
573 if (usb_powered()) /* avoid deadlock */
574 break;
575 #endif
577 #endif
579 if (!mounted)
581 CHART(">disk_mount_all");
582 rc = disk_mount_all();
583 CHART("<disk_mount_all");
584 if (rc<=0)
586 lcd_clear_display();
587 lcd_puts(0, 0, "No partition");
588 lcd_puts(0, 1, "found.");
589 #ifdef HAVE_LCD_BITMAP
590 lcd_puts(0, 2, "Insert USB cable");
591 lcd_puts(0, 3, "and fix it.");
592 #endif
593 lcd_update();
595 while(button_get(true) != SYS_USB_CONNECTED) {};
596 gui_usb_screen_run(true);
597 system_reboot();
601 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
602 (CONFIG_KEYPAD == IRIVER_H10_PAD)
603 #ifdef SETTINGS_RESET
604 /* Reset settings if holding the reset button. (Rec on Archos,
605 A on Gigabeat) */
606 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
607 #else
608 /* Reset settings if the hold button is turned on */
609 if (button_hold())
610 #endif
612 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
613 settings_reset();
615 else
616 #endif
618 CHART(">settings_load(ALL)");
619 settings_load(SETTINGS_ALL);
620 CHART("<settings_load(ALL)");
623 CHART(">init_dircache(true)");
624 rc = init_dircache(true);
625 CHART("<init_dircache(true)");
626 if (rc < 0)
628 #ifdef HAVE_TAGCACHE
629 remove(TAGCACHE_STATEFILE);
630 #endif
633 CHART(">settings_apply(true)");
634 settings_apply(true);
635 CHART("<settings_apply(true)");
636 CHART(">init_dircache(false)");
637 init_dircache(false);
638 CHART("<init_dircache(false)");
639 #ifdef HAVE_TAGCACHE
640 CHART(">init_tagcache");
641 init_tagcache();
642 CHART("<init_tagcache");
643 #endif
645 #ifdef HAVE_EEPROM_SETTINGS
646 if (firmware_settings.initialized)
648 /* In case we crash. */
649 firmware_settings.disk_clean = false;
650 CHART(">eeprom_settings_store");
651 eeprom_settings_store();
652 CHART("<eeprom_settings_store");
654 #endif
655 playlist_init();
656 tree_mem_init();
657 filetype_init();
658 scrobbler_init();
659 theme_init_buffer();
661 #if CONFIG_CODEC != SWCODEC
662 /* No buffer allocation (see buffer.c) may take place after the call to
663 audio_init() since the mpeg thread takes the rest of the buffer space */
664 mp3_init( global_settings.volume,
665 global_settings.bass,
666 global_settings.treble,
667 global_settings.balance,
668 global_settings.loudness,
669 global_settings.avc,
670 global_settings.channel_config,
671 global_settings.stereo_width,
672 global_settings.mdb_strength,
673 global_settings.mdb_harmonics,
674 global_settings.mdb_center,
675 global_settings.mdb_shape,
676 global_settings.mdb_enable,
677 global_settings.superbass);
678 #endif /* CONFIG_CODEC != SWCODEC */
680 CHART(">audio_init");
681 audio_init();
682 CHART("<audio_init");
684 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
685 pcm_rec_init();
686 #endif
688 /* runtime database has to be initialized after audio_init() */
689 cpu_boost(false);
691 #if CONFIG_CHARGING
692 car_adapter_mode_init();
693 #endif
694 #ifdef IPOD_ACCESSORY_PROTOCOL
695 iap_setup(global_settings.serial_bitrate);
696 #endif
697 #ifdef HAVE_ACCESSORY_SUPPLY
698 accessory_supply_set(global_settings.accessory_supply);
699 #endif
700 #ifdef HAVE_LINEOUT_POWEROFF
701 lineout_set(global_settings.lineout_active);
702 #endif
703 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
704 CHART("<check_bootfile(false)");
705 check_bootfile(false); /* remember write time and filesize */
706 CHART(">check_bootfile(false)");
707 #endif
708 CHART("<settings_apply_skins");
709 settings_apply_skins();
710 CHART(">settings_apply_skins");
713 #ifdef CPU_PP
714 void cop_main(void) MAIN_NORETURN_ATTR;
715 void cop_main(void)
717 /* This is the entry point for the coprocessor
718 Anyone not running an upgraded bootloader will never reach this point,
719 so it should not be assumed that the coprocessor be usable even on
720 platforms which support it.
722 A kernel thread is initially setup on the coprocessor and immediately
723 destroyed for purposes of continuity. The cop sits idle until at least
724 one thread exists on it. */
726 #if NUM_CORES > 1
727 system_init();
728 kernel_init();
729 /* This should never be reached */
730 #endif
731 while(1) {
732 sleep_core(COP);
735 #endif /* CPU_PP */
737 #endif /* SIMULATOR */