Onle one table row per WPS tag
[maemo-rb.git] / apps / main.c
blobb3252d8bd8d543beca07457e548df00359659704
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 "storage.h"
24 #include "disk.h"
25 #include "fat.h"
26 #include "lcd.h"
27 #include "rtc.h"
28 #include "debug.h"
29 #include "led.h"
30 #include "kernel.h"
31 #include "button.h"
32 #include "tree.h"
33 #include "filetypes.h"
34 #include "panic.h"
35 #include "menu.h"
36 #include "system.h"
37 #include "usb.h"
38 #include "powermgmt.h"
39 #include "adc.h"
40 #include "i2c.h"
41 #ifndef DEBUG
42 #include "serial.h"
43 #endif
44 #include "audio.h"
45 #include "mp3_playback.h"
46 #include "thread.h"
47 #include "settings.h"
48 #include "backlight.h"
49 #include "status.h"
50 #include "debug_menu.h"
51 #include "font.h"
52 #include "language.h"
53 #include "wps.h"
54 #include "playlist.h"
55 #include "buffer.h"
56 #include "rolo.h"
57 #include "screens.h"
58 #include "usb_screen.h"
59 #include "power.h"
60 #include "talk.h"
61 #include "plugin.h"
62 #include "misc.h"
63 #include "dircache.h"
64 #ifdef HAVE_TAGCACHE
65 #include "tagcache.h"
66 #include "tagtree.h"
67 #endif
68 #include "lang.h"
69 #include "string.h"
70 #include "splash.h"
71 #include "eeprom_settings.h"
72 #include "scrobbler.h"
73 #include "icon.h"
74 #include "viewport.h"
75 #include "statusbar-skinned.h"
76 #include "bootchart.h"
78 #ifdef IPOD_ACCESSORY_PROTOCOL
79 #include "iap.h"
80 #endif
82 #if (CONFIG_CODEC == SWCODEC)
83 #include "playback.h"
84 #include "tdspeed.h"
85 #endif
86 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
87 #include "pcm_record.h"
88 #endif
90 #ifdef BUTTON_REC
91 #define SETTINGS_RESET BUTTON_REC
92 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93 #define SETTINGS_RESET BUTTON_A
94 #endif
96 #if CONFIG_TUNER
97 #include "radio.h"
98 #endif
99 #if (CONFIG_STORAGE & STORAGE_MMC)
100 #include "ata_mmc.h"
101 #endif
103 #ifdef HAVE_REMOTE_LCD
104 #include "lcd-remote.h"
105 #endif
107 #if CONFIG_USBOTG == USBOTG_ISP1362
108 #include "isp1362.h"
109 #endif
111 #if CONFIG_USBOTG == USBOTG_M5636
112 #include "m5636.h"
113 #endif
115 #ifdef SIMULATOR
116 #include "sim_tasks.h"
117 #endif
118 #ifdef HAVE_SDL
119 #include "system-sdl.h"
120 #endif
122 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
124 static void init(void);
126 #ifdef HAVE_SDL
127 #if defined(WIN32) && defined(main)
128 /* Don't use SDL_main on windows -> no more stdio redirection */
129 #undef main
130 #endif
131 int main(int argc, char *argv[])
133 sys_handle_argv(argc, argv);
134 #else
135 /* main(), and various functions called by main() and init() may be
136 * be INIT_ATTR. These functions must not be called after the final call
137 * to root_menu() at the end of main()
138 * see definition of INIT_ATTR in config.h */
139 int main(void) INIT_ATTR __attribute__((noreturn));
140 int main(void)
142 #endif
143 int i;
144 CHART(">init");
145 init();
146 CHART("<init");
147 FOR_NB_SCREENS(i)
149 screens[i].clear_display();
150 screens[i].update();
152 #ifdef HAVE_LCD_BITMAP
153 list_init();
154 #endif
155 tree_gui_init();
156 /* Keep the order of this 3
157 * Must be done before any code uses the multi-screen API */
158 #ifdef HAVE_USBSTACK
159 /* All threads should be created and public queues registered by now */
160 usb_start_monitoring();
161 #endif
163 #ifdef AUTOROCK
165 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
167 if(file_exists(filename)) /* no complaint if it doesn't exist */
169 plugin_load((char*)filename, NULL); /* start if it does */
172 #endif /* #ifdef AUTOROCK */
174 global_status.last_volume_change = 0;
175 /* no calls INIT_ATTR functions after this point anymore!
176 * see definition of INIT_ATTR in config.h */
177 CHART(">root_menu");
178 root_menu();
181 static int init_dircache(bool preinit) INIT_ATTR;
182 static int init_dircache(bool preinit)
184 #ifdef HAVE_DIRCACHE
185 int result = 0;
186 bool clear = false;
188 if (preinit)
189 dircache_init();
191 if (!global_settings.dircache)
192 return 0;
194 # ifdef HAVE_EEPROM_SETTINGS
195 if (firmware_settings.initialized && firmware_settings.disk_clean
196 && preinit)
198 result = dircache_load();
200 if (result < 0)
202 firmware_settings.disk_clean = false;
203 if (global_status.dircache_size <= 0)
205 /* This will be in default language, settings are not
206 applied yet. Not really any easy way to fix that. */
207 splash(0, str(LANG_SCANNING_DISK));
208 clear = true;
211 dircache_build(global_status.dircache_size);
214 else
215 # endif
217 if (preinit)
218 return -1;
220 if (!dircache_is_enabled()
221 && !dircache_is_initializing())
223 if (global_status.dircache_size <= 0)
225 splash(0, str(LANG_SCANNING_DISK));
226 clear = true;
228 result = dircache_build(global_status.dircache_size);
231 if (result < 0)
233 /* Initialization of dircache failed. Manual action is
234 * necessary to enable dircache again.
236 splashf(0, "Dircache failed, disabled. Result: %d", result);
237 global_settings.dircache = false;
241 if (clear)
243 backlight_on();
244 show_logo();
245 global_status.dircache_size = dircache_get_cache_size();
246 status_save();
249 return result;
250 #else
251 (void)preinit;
252 return 0;
253 #endif
256 #ifdef HAVE_TAGCACHE
257 static void init_tagcache(void) INIT_ATTR;
258 static void init_tagcache(void)
260 bool clear = false;
261 #if CONFIG_CODEC == SWCODEC
262 long talked_tick = 0;
263 #endif
264 tagcache_init();
266 while (!tagcache_is_initialized())
268 int ret = tagcache_get_commit_step();
270 if (ret > 0)
272 #if CONFIG_CODEC == SWCODEC
273 /* hwcodec can't use voice here, as the database commit
274 * uses the audio buffer. */
275 if(global_settings.talk_menu
276 && (talked_tick == 0
277 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
279 talked_tick = current_tick;
280 talk_id(LANG_TAGCACHE_INIT, false);
281 talk_number(ret, true);
282 talk_id(VOICE_OF, true);
283 talk_number(tagcache_get_max_commit_step(), true);
285 #endif
286 #ifdef HAVE_LCD_BITMAP
287 if (lang_is_rtl())
289 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
290 str(LANG_TAGCACHE_INIT));
292 else
294 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
295 tagcache_get_max_commit_step());
297 #else
298 lcd_double_height(false);
299 lcd_putsf(0, 1, " DB [%d/%d]", ret,
300 tagcache_get_max_commit_step());
301 lcd_update();
302 #endif
303 clear = true;
305 sleep(HZ/4);
307 tagtree_init();
309 if (clear)
311 backlight_on();
312 show_logo();
315 #endif
317 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
319 static void init(void)
321 system_init();
322 kernel_init();
323 buffer_init();
324 enable_irq();
325 lcd_init();
326 #ifdef HAVE_REMOTE_LCD
327 lcd_remote_init();
328 #endif
329 font_init();
330 show_logo();
331 button_init();
332 backlight_init();
333 sim_tasks_init();
334 lang_init(core_language_builtin, language_strings,
335 LANG_LAST_INDEX_IN_ARRAY);
336 #ifdef DEBUG
337 debug_init();
338 #endif
339 /* Keep the order of this 3 (viewportmanager handles statusbars)
340 * Must be done before any code uses the multi-screen API */
341 gui_syncstatusbar_init(&statusbars);
342 gui_sync_wps_init();
343 sb_skin_init();
344 viewportmanager_init();
346 storage_init();
347 settings_reset();
348 settings_load(SETTINGS_ALL);
349 settings_apply(true);
350 init_dircache(true);
351 init_dircache(false);
352 #ifdef HAVE_TAGCACHE
353 init_tagcache();
354 #endif
355 sleep(HZ/2);
356 tree_mem_init();
357 filetype_init();
358 playlist_init();
360 #if CONFIG_CODEC != SWCODEC
361 mp3_init( global_settings.volume,
362 global_settings.bass,
363 global_settings.treble,
364 global_settings.balance,
365 global_settings.loudness,
366 global_settings.avc,
367 global_settings.channel_config,
368 global_settings.stereo_width,
369 global_settings.mdb_strength,
370 global_settings.mdb_harmonics,
371 global_settings.mdb_center,
372 global_settings.mdb_shape,
373 global_settings.mdb_enable,
374 global_settings.superbass);
376 /* audio_init must to know the size of voice buffer so init voice first */
377 talk_init();
378 #endif /* CONFIG_CODEC != SWCODEC */
380 scrobbler_init();
381 #if CONFIG_CODEC == SWCODEC
382 tdspeed_init();
383 #endif /* CONFIG_CODEC == SWCODEC */
385 audio_init();
386 button_clear_queue(); /* Empty the keyboard buffer */
388 settings_apply_skins();
391 #else
393 static void init(void) INIT_ATTR;
394 static void init(void)
396 int rc;
397 bool mounted = false;
398 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
399 /* if nobody initialized ATA before, I consider this a cold start */
400 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
401 #endif
403 system_init();
404 kernel_init();
406 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
407 set_cpu_frequency(CPUFREQ_NORMAL);
408 #ifdef CPU_COLDFIRE
409 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
410 #endif
411 cpu_boost(true);
412 #endif
414 buffer_init();
416 settings_reset();
418 i2c_init();
420 power_init();
422 enable_irq();
423 #ifdef CPU_ARM
424 enable_fiq();
425 #endif
426 /* current_tick should be ticking by now */
427 CHART("ticking");
429 lcd_init();
430 #ifdef HAVE_REMOTE_LCD
431 lcd_remote_init();
432 #endif
433 font_init();
435 CHART(">show_logo");
436 show_logo();
437 CHART("<show_logo");
438 lang_init(core_language_builtin, language_strings,
439 LANG_LAST_INDEX_IN_ARRAY);
441 #ifdef DEBUG
442 debug_init();
443 #else
444 #ifdef HAVE_SERIAL
445 serial_setup();
446 #endif
447 #endif
449 #if CONFIG_RTC
450 rtc_init();
451 #endif
452 #ifdef HAVE_RTC_RAM
453 CHART(">settings_load(RTC)");
454 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
455 CHART("<settings_load(RTC)");
456 #endif
458 adc_init();
460 usb_init();
461 #if CONFIG_USBOTG == USBOTG_ISP1362
462 isp1362_init();
463 #elif CONFIG_USBOTG == USBOTG_M5636
464 m5636_init();
465 #endif
467 backlight_init();
469 button_init();
471 powermgmt_init();
473 #if CONFIG_TUNER
474 radio_init();
475 #endif
477 /* Keep the order of this 3 (viewportmanager handles statusbars)
478 * Must be done before any code uses the multi-screen API */
479 CHART(">gui_syncstatusbar_init");
480 gui_syncstatusbar_init(&statusbars);
481 CHART("<gui_syncstatusbar_init");
482 CHART(">sb_skin_init");
483 sb_skin_init();
484 CHART("<sb_skin_init");
485 CHART(">gui_sync_wps_init");
486 gui_sync_wps_init();
487 CHART("<gui_sync_wps_init");
488 CHART(">viewportmanager_init");
489 viewportmanager_init();
490 CHART("<viewportmanager_init");
492 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
493 /* charger_inserted() can't be used here because power_thread()
494 hasn't checked power_input_status() yet */
495 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
496 && !global_settings.car_adapter_mode
497 #ifdef ATA_POWER_PLAYERSTYLE
498 && !ide_powered() /* relies on probing result from bootloader */
499 #endif
502 rc = charging_screen(); /* display a "charging" screen */
503 if (rc == 1) /* charger removed */
504 power_off();
505 /* "On" pressed or USB connected: proceed */
506 show_logo(); /* again, to provide better visual feedback */
508 #endif
511 disk_init_subsystem();
512 CHART(">storage_init");
513 rc = storage_init();
514 CHART("<storage_init");
515 if(rc)
517 #ifdef HAVE_LCD_BITMAP
518 lcd_clear_display();
519 lcd_putsf(0, 1, "ATA error: %d", rc);
520 lcd_puts(0, 3, "Press ON to debug");
521 lcd_update();
522 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
523 dbg_ports();
524 #endif
525 panicf("ata: %d", rc);
528 #ifdef HAVE_EEPROM_SETTINGS
529 CHART(">eeprom_settings_init");
530 eeprom_settings_init();
531 CHART("<eeprom_settings_init");
532 #endif
534 #ifndef HAVE_USBSTACK
535 usb_start_monitoring();
536 while (usb_detect() == USB_INSERTED)
538 #ifdef HAVE_EEPROM_SETTINGS
539 firmware_settings.disk_clean = false;
540 #endif
541 /* enter USB mode early, before trying to mount */
542 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
543 #if (CONFIG_STORAGE & STORAGE_MMC)
544 if (!mmc_touched() ||
545 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
546 #endif
548 gui_usb_screen_run();
549 mounted = true; /* mounting done @ end of USB mode */
551 #ifdef HAVE_USB_POWER
552 if (usb_powered()) /* avoid deadlock */
553 break;
554 #endif
556 #endif
558 if (!mounted)
560 CHART(">disk_mount_all");
561 rc = disk_mount_all();
562 CHART("<disk_mount_all");
563 if (rc<=0)
565 lcd_clear_display();
566 lcd_puts(0, 0, "No partition");
567 lcd_puts(0, 1, "found.");
568 #ifdef HAVE_LCD_BITMAP
569 lcd_puts(0, 2, "Insert USB cable");
570 lcd_puts(0, 3, "and fix it.");
571 #endif
572 lcd_update();
574 while(button_get(true) != SYS_USB_CONNECTED) {};
575 gui_usb_screen_run();
576 system_reboot();
580 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
581 (CONFIG_KEYPAD == IRIVER_H10_PAD)
582 #ifdef SETTINGS_RESET
583 /* Reset settings if holding the reset button. (Rec on Archos,
584 A on Gigabeat) */
585 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
586 #else
587 /* Reset settings if the hold button is turned on */
588 if (button_hold())
589 #endif
591 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
592 settings_reset();
594 else
595 #endif
597 CHART(">settings_load(ALL)");
598 settings_load(SETTINGS_ALL);
599 CHART("<settings_load(ALL)");
602 CHART(">init_dircache(true)");
603 rc = init_dircache(true);
604 CHART("<init_dircache(true)");
605 if (rc < 0)
607 #ifdef HAVE_TAGCACHE
608 remove(TAGCACHE_STATEFILE);
609 #endif
612 CHART(">settings_apply(true)");
613 settings_apply(true);
614 CHART("<settings_apply(true)");
615 CHART(">init_dircache(false)");
616 init_dircache(false);
617 CHART("<init_dircache(false)");
618 #ifdef HAVE_TAGCACHE
619 CHART(">init_tagcache");
620 init_tagcache();
621 CHART("<init_tagcache");
622 #endif
624 #ifdef HAVE_EEPROM_SETTINGS
625 if (firmware_settings.initialized)
627 /* In case we crash. */
628 firmware_settings.disk_clean = false;
629 CHART(">eeprom_settings_store");
630 eeprom_settings_store();
631 CHART("<eeprom_settings_store");
633 #endif
634 playlist_init();
635 tree_mem_init();
636 filetype_init();
637 scrobbler_init();
638 #if CONFIG_CODEC == SWCODEC
639 tdspeed_init();
640 #endif /* CONFIG_CODEC == SWCODEC */
642 #if CONFIG_CODEC != SWCODEC
643 /* No buffer allocation (see buffer.c) may take place after the call to
644 audio_init() since the mpeg thread takes the rest of the buffer space */
645 mp3_init( global_settings.volume,
646 global_settings.bass,
647 global_settings.treble,
648 global_settings.balance,
649 global_settings.loudness,
650 global_settings.avc,
651 global_settings.channel_config,
652 global_settings.stereo_width,
653 global_settings.mdb_strength,
654 global_settings.mdb_harmonics,
655 global_settings.mdb_center,
656 global_settings.mdb_shape,
657 global_settings.mdb_enable,
658 global_settings.superbass);
660 /* audio_init must to know the size of voice buffer so init voice first */
661 talk_init();
662 #endif /* CONFIG_CODEC != SWCODEC */
664 CHART(">audio_init");
665 audio_init();
666 CHART("<audio_init");
668 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
669 pcm_rec_init();
670 #endif
672 /* runtime database has to be initialized after audio_init() */
673 cpu_boost(false);
675 #if CONFIG_CHARGING
676 car_adapter_mode_init();
677 #endif
678 #ifdef IPOD_ACCESSORY_PROTOCOL
679 iap_setup(global_settings.serial_bitrate);
680 #endif
681 #ifdef HAVE_ACCESSORY_SUPPLY
682 accessory_supply_set(global_settings.accessory_supply);
683 #endif
684 #ifdef HAVE_LINEOUT_POWEROFF
685 lineout_set(global_settings.lineout_active);
686 #endif
687 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
688 CHART("<check_bootfile(false)");
689 check_bootfile(false); /* remember write time and filesize */
690 CHART(">check_bootfile(false)");
691 #endif
692 CHART("<settings_apply_skins");
693 settings_apply_skins();
694 CHART(">settings_apply_skins");
697 #ifdef CPU_PP
698 void __attribute__((noreturn)) cop_main(void)
700 /* This is the entry point for the coprocessor
701 Anyone not running an upgraded bootloader will never reach this point,
702 so it should not be assumed that the coprocessor be usable even on
703 platforms which support it.
705 A kernel thread is initially setup on the coprocessor and immediately
706 destroyed for purposes of continuity. The cop sits idle until at least
707 one thread exists on it. */
709 #if NUM_CORES > 1
710 system_init();
711 kernel_init();
712 /* This should never be reached */
713 #endif
714 while(1) {
715 sleep_core(COP);
718 #endif /* CPU_PP */
720 #endif /* SIMULATOR */