Update the discussion of themeing in the manual, and put a note in the wps tags appen...
[kugel-rb.git] / apps / main.c
blobb043dacede8dc0b88ffcfb224888014f54acce76
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 "version.h"
52 #include "font.h"
53 #include "language.h"
54 #include "wps.h"
55 #include "playlist.h"
56 #include "buffer.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 "statusbar-skinned.h"
77 #include "bootchart.h"
79 #ifdef IPOD_ACCESSORY_PROTOCOL
80 #include "iap.h"
81 #endif
83 #if (CONFIG_CODEC == SWCODEC)
84 #include "playback.h"
85 #include "tdspeed.h"
86 #endif
87 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
88 #include "pcm_record.h"
89 #endif
91 #ifdef BUTTON_REC
92 #define SETTINGS_RESET BUTTON_REC
93 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
94 #define SETTINGS_RESET BUTTON_A
95 #endif
97 #if CONFIG_TUNER
98 #include "radio.h"
99 #endif
100 #if (CONFIG_STORAGE & STORAGE_MMC)
101 #include "ata_mmc.h"
102 #endif
104 #ifdef HAVE_REMOTE_LCD
105 #include "lcd-remote.h"
106 #endif
108 #if CONFIG_USBOTG == USBOTG_ISP1362
109 #include "isp1362.h"
110 #endif
112 #if CONFIG_USBOTG == USBOTG_M5636
113 #include "m5636.h"
114 #endif
116 #ifdef SIMULATOR
117 #include "sim_tasks.h"
118 #include "system-sdl.h"
119 #endif
121 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
123 const char appsversion[]=APPSVERSION;
125 static void init(void);
127 #ifdef SIMULATOR
128 void app_main(void)
129 #else
130 /* main(), and various functions called by main() and init() may be
131 * be INIT_ATTR. These functions must not be called after the final call
132 * to root_menu() at the end of main()
133 * see definition of INIT_ATTR in config.h */
134 int main(void) INIT_ATTR __attribute__((noreturn));
135 int main(void)
136 #endif
138 int i;
139 CHART(">init");
140 init();
141 CHART("<init");
142 FOR_NB_SCREENS(i)
144 screens[i].clear_display();
145 screens[i].update();
147 #ifdef HAVE_LCD_BITMAP
148 list_init();
149 #endif
150 tree_gui_init();
151 /* Keep the order of this 3
152 * Must be done before any code uses the multi-screen API */
153 #ifdef HAVE_USBSTACK
154 /* All threads should be created and public queues registered by now */
155 usb_start_monitoring();
156 #endif
158 #ifdef AUTOROCK
160 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
162 if(file_exists(filename)) /* no complaint if it doesn't exist */
164 plugin_load((char*)filename, NULL); /* start if it does */
167 #endif /* #ifdef AUTOROCK */
169 global_status.last_volume_change = 0;
170 /* no calls INIT_ATTR functions after this point anymore!
171 * see definition of INIT_ATTR in config.h */
172 CHART(">root_menu");
173 root_menu();
176 static int init_dircache(bool preinit) INIT_ATTR;
177 static int init_dircache(bool preinit)
179 #ifdef HAVE_DIRCACHE
180 int result = 0;
181 bool clear = false;
183 if (preinit)
184 dircache_init();
186 if (!global_settings.dircache)
187 return 0;
189 # ifdef HAVE_EEPROM_SETTINGS
190 if (firmware_settings.initialized && firmware_settings.disk_clean
191 && preinit)
193 result = dircache_load();
195 if (result < 0)
197 firmware_settings.disk_clean = false;
198 if (global_status.dircache_size <= 0)
200 /* This will be in default language, settings are not
201 applied yet. Not really any easy way to fix that. */
202 splash(0, str(LANG_SCANNING_DISK));
203 clear = true;
206 dircache_build(global_status.dircache_size);
209 else
210 # endif
212 if (preinit)
213 return -1;
215 if (!dircache_is_enabled()
216 && !dircache_is_initializing())
218 if (global_status.dircache_size <= 0)
220 splash(0, str(LANG_SCANNING_DISK));
221 clear = true;
223 result = dircache_build(global_status.dircache_size);
226 if (result < 0)
228 /* Initialization of dircache failed. Manual action is
229 * necessary to enable dircache again.
231 splashf(0, "Dircache failed, disabled. Result: %d", result);
232 global_settings.dircache = false;
236 if (clear)
238 backlight_on();
239 show_logo();
240 global_status.dircache_size = dircache_get_cache_size();
241 status_save();
244 return result;
245 #else
246 (void)preinit;
247 return 0;
248 #endif
251 #ifdef HAVE_TAGCACHE
252 static void init_tagcache(void) INIT_ATTR;
253 static void init_tagcache(void)
255 bool clear = false;
256 #if CONFIG_CODEC == SWCODEC
257 long talked_tick = 0;
258 #endif
259 tagcache_init();
261 while (!tagcache_is_initialized())
263 int ret = tagcache_get_commit_step();
265 if (ret > 0)
267 #if CONFIG_CODEC == SWCODEC
268 /* hwcodec can't use voice here, as the database commit
269 * uses the audio buffer. */
270 if(global_settings.talk_menu
271 && (talked_tick == 0
272 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
274 talked_tick = current_tick;
275 talk_id(LANG_TAGCACHE_INIT, false);
276 talk_number(ret, true);
277 talk_id(VOICE_OF, true);
278 talk_number(tagcache_get_max_commit_step(), true);
280 #endif
281 #ifdef HAVE_LCD_BITMAP
282 if (lang_is_rtl())
284 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
285 str(LANG_TAGCACHE_INIT));
287 else
289 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
290 tagcache_get_max_commit_step());
292 #else
293 lcd_double_height(false);
294 lcd_putsf(0, 1, " DB [%d/%d]", ret,
295 tagcache_get_max_commit_step());
296 lcd_update();
297 #endif
298 clear = true;
300 sleep(HZ/4);
302 tagtree_init();
304 if (clear)
306 backlight_on();
307 show_logo();
310 #endif
312 #ifdef SIMULATOR
314 static void init(void)
316 kernel_init();
317 buffer_init();
318 enable_irq();
319 lcd_init();
320 #ifdef HAVE_REMOTE_LCD
321 lcd_remote_init();
322 #endif
323 font_init();
324 show_logo();
325 button_init();
326 backlight_init();
327 sim_tasks_init();
328 lang_init(core_language_builtin, language_strings,
329 LANG_LAST_INDEX_IN_ARRAY);
330 #ifdef DEBUG
331 debug_init();
332 #endif
333 /* Keep the order of this 3 (viewportmanager handles statusbars)
334 * Must be done before any code uses the multi-screen API */
335 gui_syncstatusbar_init(&statusbars);
336 gui_sync_wps_init();
337 sb_skin_init();
338 viewportmanager_init();
340 storage_init();
341 settings_reset();
342 settings_load(SETTINGS_ALL);
343 settings_apply(true);
344 init_dircache(true);
345 init_dircache(false);
346 #ifdef HAVE_TAGCACHE
347 init_tagcache();
348 #endif
349 sleep(HZ/2);
350 tree_mem_init();
351 filetype_init();
352 playlist_init();
354 #if CONFIG_CODEC != SWCODEC
355 mp3_init( global_settings.volume,
356 global_settings.bass,
357 global_settings.treble,
358 global_settings.balance,
359 global_settings.loudness,
360 global_settings.avc,
361 global_settings.channel_config,
362 global_settings.stereo_width,
363 global_settings.mdb_strength,
364 global_settings.mdb_harmonics,
365 global_settings.mdb_center,
366 global_settings.mdb_shape,
367 global_settings.mdb_enable,
368 global_settings.superbass);
370 /* audio_init must to know the size of voice buffer so init voice first */
371 talk_init();
372 #endif /* CONFIG_CODEC != SWCODEC */
374 scrobbler_init();
375 #if CONFIG_CODEC == SWCODEC
376 tdspeed_init();
377 #endif /* CONFIG_CODEC == SWCODEC */
379 audio_init();
380 button_clear_queue(); /* Empty the keyboard buffer */
382 settings_apply_skins();
385 #else
387 static void init(void) INIT_ATTR;
388 static void init(void)
390 int rc;
391 bool mounted = false;
392 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
393 /* if nobody initialized ATA before, I consider this a cold start */
394 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
395 #endif
397 system_init();
398 kernel_init();
400 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
401 set_cpu_frequency(CPUFREQ_NORMAL);
402 #ifdef CPU_COLDFIRE
403 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
404 #endif
405 cpu_boost(true);
406 #endif
408 buffer_init();
410 settings_reset();
412 i2c_init();
414 power_init();
416 enable_irq();
417 #ifdef CPU_ARM
418 enable_fiq();
419 #endif
420 /* current_tick should be ticking by now */
421 CHART("ticking");
423 lcd_init();
424 #ifdef HAVE_REMOTE_LCD
425 lcd_remote_init();
426 #endif
427 font_init();
429 CHART(">show_logo");
430 show_logo();
431 CHART("<show_logo");
432 lang_init(core_language_builtin, language_strings,
433 LANG_LAST_INDEX_IN_ARRAY);
435 #ifdef DEBUG
436 debug_init();
437 #else
438 #ifdef HAVE_SERIAL
439 serial_setup();
440 #endif
441 #endif
443 #if CONFIG_RTC
444 rtc_init();
445 #endif
446 #ifdef HAVE_RTC_RAM
447 CHART(">settings_load(RTC)");
448 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
449 CHART("<settings_load(RTC)");
450 #endif
452 adc_init();
454 usb_init();
455 #if CONFIG_USBOTG == USBOTG_ISP1362
456 isp1362_init();
457 #elif CONFIG_USBOTG == USBOTG_M5636
458 m5636_init();
459 #endif
461 backlight_init();
463 button_init();
465 powermgmt_init();
467 #if CONFIG_TUNER
468 radio_init();
469 #endif
471 /* Keep the order of this 3 (viewportmanager handles statusbars)
472 * Must be done before any code uses the multi-screen API */
473 CHART(">gui_syncstatusbar_init");
474 gui_syncstatusbar_init(&statusbars);
475 CHART("<gui_syncstatusbar_init");
476 CHART(">sb_skin_init");
477 sb_skin_init();
478 CHART("<sb_skin_init");
479 CHART(">gui_sync_wps_init");
480 gui_sync_wps_init();
481 CHART("<gui_sync_wps_init");
482 CHART(">viewportmanager_init");
483 viewportmanager_init();
484 CHART("<viewportmanager_init");
486 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
487 /* charger_inserted() can't be used here because power_thread()
488 hasn't checked power_input_status() yet */
489 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
490 && !global_settings.car_adapter_mode
491 #ifdef ATA_POWER_PLAYERSTYLE
492 && !ide_powered() /* relies on probing result from bootloader */
493 #endif
496 rc = charging_screen(); /* display a "charging" screen */
497 if (rc == 1) /* charger removed */
498 power_off();
499 /* "On" pressed or USB connected: proceed */
500 show_logo(); /* again, to provide better visual feedback */
502 #endif
504 CHART(">storage_init");
505 rc = storage_init();
506 CHART("<storage_init");
507 if(rc)
509 #ifdef HAVE_LCD_BITMAP
510 lcd_clear_display();
511 lcd_putsf(0, 1, "ATA error: %d", rc);
512 lcd_puts(0, 3, "Press ON to debug");
513 lcd_update();
514 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
515 dbg_ports();
516 #endif
517 panicf("ata: %d", rc);
520 #ifdef HAVE_EEPROM_SETTINGS
521 CHART(">eeprom_settings_init");
522 eeprom_settings_init();
523 CHART("<eeprom_settings_init");
524 #endif
526 #ifndef HAVE_USBSTACK
527 usb_start_monitoring();
528 while (usb_detect() == USB_INSERTED)
530 #ifdef HAVE_EEPROM_SETTINGS
531 firmware_settings.disk_clean = false;
532 #endif
533 /* enter USB mode early, before trying to mount */
534 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
535 #if (CONFIG_STORAGE & STORAGE_MMC)
536 if (!mmc_touched() ||
537 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
538 #endif
540 gui_usb_screen_run();
541 mounted = true; /* mounting done @ end of USB mode */
543 #ifdef HAVE_USB_POWER
544 if (usb_powered()) /* avoid deadlock */
545 break;
546 #endif
548 #endif
550 if (!mounted)
552 CHART(">disk_mount_all");
553 rc = disk_mount_all();
554 CHART("<disk_mount_all");
555 if (rc<=0)
557 lcd_clear_display();
558 lcd_puts(0, 0, "No partition");
559 lcd_puts(0, 1, "found.");
560 #ifdef HAVE_LCD_BITMAP
561 lcd_puts(0, 2, "Insert USB cable");
562 lcd_puts(0, 3, "and fix it.");
563 #endif
564 lcd_update();
566 while(button_get(true) != SYS_USB_CONNECTED) {};
567 gui_usb_screen_run();
568 system_reboot();
572 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
573 (CONFIG_KEYPAD == IRIVER_H10_PAD)
574 #ifdef SETTINGS_RESET
575 /* Reset settings if holding the reset button. (Rec on Archos,
576 A on Gigabeat) */
577 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
578 #else
579 /* Reset settings if the hold button is turned on */
580 if (button_hold())
581 #endif
583 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
584 settings_reset();
586 else
587 #endif
589 CHART(">settings_load(ALL)");
590 settings_load(SETTINGS_ALL);
591 CHART("<settings_load(ALL)");
594 CHART(">init_dircache(true)");
595 rc = init_dircache(true);
596 CHART("<init_dircache(true)");
597 if (rc < 0)
599 #ifdef HAVE_TAGCACHE
600 remove(TAGCACHE_STATEFILE);
601 #endif
604 CHART(">settings_apply(true)");
605 settings_apply(true);
606 CHART("<settings_apply(true)");
607 CHART(">init_dircache(false)");
608 init_dircache(false);
609 CHART("<init_dircache(false)");
610 #ifdef HAVE_TAGCACHE
611 CHART(">init_tagcache");
612 init_tagcache();
613 CHART("<init_tagcache");
614 #endif
616 #ifdef HAVE_EEPROM_SETTINGS
617 if (firmware_settings.initialized)
619 /* In case we crash. */
620 firmware_settings.disk_clean = false;
621 CHART(">eeprom_settings_store");
622 eeprom_settings_store();
623 CHART("<eeprom_settings_store");
625 #endif
626 playlist_init();
627 tree_mem_init();
628 filetype_init();
629 scrobbler_init();
630 #if CONFIG_CODEC == SWCODEC
631 tdspeed_init();
632 #endif /* CONFIG_CODEC == SWCODEC */
634 #if CONFIG_CODEC != SWCODEC
635 /* No buffer allocation (see buffer.c) may take place after the call to
636 audio_init() since the mpeg thread takes the rest of the buffer space */
637 mp3_init( global_settings.volume,
638 global_settings.bass,
639 global_settings.treble,
640 global_settings.balance,
641 global_settings.loudness,
642 global_settings.avc,
643 global_settings.channel_config,
644 global_settings.stereo_width,
645 global_settings.mdb_strength,
646 global_settings.mdb_harmonics,
647 global_settings.mdb_center,
648 global_settings.mdb_shape,
649 global_settings.mdb_enable,
650 global_settings.superbass);
652 /* audio_init must to know the size of voice buffer so init voice first */
653 talk_init();
654 #endif /* CONFIG_CODEC != SWCODEC */
656 CHART(">audio_init");
657 audio_init();
658 CHART("<audio_init");
660 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
661 pcm_rec_init();
662 #endif
664 /* runtime database has to be initialized after audio_init() */
665 cpu_boost(false);
667 #if CONFIG_CHARGING
668 car_adapter_mode_init();
669 #endif
670 #ifdef IPOD_ACCESSORY_PROTOCOL
671 iap_setup(global_settings.serial_bitrate);
672 #endif
673 #ifdef HAVE_ACCESSORY_SUPPLY
674 accessory_supply_set(global_settings.accessory_supply);
675 #endif
676 #ifdef HAVE_LINEOUT_POWEROFF
677 lineout_set(global_settings.lineout_active);
678 #endif
679 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
680 CHART("<check_bootfile(false)");
681 check_bootfile(false); /* remember write time and filesize */
682 CHART(">check_bootfile(false)");
683 #endif
684 CHART("<settings_apply_skins");
685 settings_apply_skins();
686 CHART(">settings_apply_skins");
689 #ifdef CPU_PP
690 void cop_main(void)
692 /* This is the entry point for the coprocessor
693 Anyone not running an upgraded bootloader will never reach this point,
694 so it should not be assumed that the coprocessor be usable even on
695 platforms which support it.
697 A kernel thread is initially setup on the coprocessor and immediately
698 destroyed for purposes of continuity. The cop sits idle until at least
699 one thread exists on it. */
701 /* 3G doesn't have Rolo or dual core support yet */
702 #if NUM_CORES > 1
703 system_init();
704 kernel_init();
705 /* This should never be reached */
706 #endif
707 while(1) {
708 sleep_core(COP);
711 #endif /* CPU_PP */
713 #endif