Add libwmapro to trunk.
[kugel-rb.git] / apps / main.c
blob5b9ecdad7961ca51c3828c3886d87038b353db8b
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 "sprintf.h"
53 #include "font.h"
54 #include "language.h"
55 #include "wps.h"
56 #include "playlist.h"
57 #include "buffer.h"
58 #include "rolo.h"
59 #include "screens.h"
60 #include "usb_screen.h"
61 #include "power.h"
62 #include "talk.h"
63 #include "plugin.h"
64 #include "misc.h"
65 #include "dircache.h"
66 #ifdef HAVE_TAGCACHE
67 #include "tagcache.h"
68 #include "tagtree.h"
69 #endif
70 #include "lang.h"
71 #include "string.h"
72 #include "splash.h"
73 #include "eeprom_settings.h"
74 #include "scrobbler.h"
75 #include "icon.h"
76 #include "viewport.h"
77 #include "statusbar-skinned.h"
78 #include "bootchart.h"
80 #ifdef IPOD_ACCESSORY_PROTOCOL
81 #include "iap.h"
82 #endif
84 #if (CONFIG_CODEC == SWCODEC)
85 #include "playback.h"
86 #include "tdspeed.h"
87 #endif
88 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
89 #include "pcm_record.h"
90 #endif
92 #ifdef BUTTON_REC
93 #define SETTINGS_RESET BUTTON_REC
94 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
95 #define SETTINGS_RESET BUTTON_A
96 #endif
98 #if CONFIG_TUNER
99 #include "radio.h"
100 #endif
101 #if (CONFIG_STORAGE & STORAGE_MMC)
102 #include "ata_mmc.h"
103 #endif
105 #ifdef HAVE_REMOTE_LCD
106 #include "lcd-remote.h"
107 #endif
109 #if CONFIG_USBOTG == USBOTG_ISP1362
110 #include "isp1362.h"
111 #endif
113 #if CONFIG_USBOTG == USBOTG_M5636
114 #include "m5636.h"
115 #endif
117 #ifdef SIMULATOR
118 #include "sim_tasks.h"
119 #include "system-sdl.h"
120 #endif
122 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
124 const char appsversion[]=APPSVERSION;
126 static void init(void);
128 #ifdef SIMULATOR
129 void app_main(void)
130 #else
131 /* main(), and various functions called by main() and init() may be
132 * be INIT_ATTR. These functions must not be called after the final call
133 * to root_menu() at the end of main()
134 * see definition of INIT_ATTR in config.h */
135 int main(void) INIT_ATTR __attribute__((noreturn));
136 int main(void)
137 #endif
139 int i;
140 CHART(">init");
141 init();
142 CHART("<init");
143 FOR_NB_SCREENS(i)
145 screens[i].clear_display();
146 screens[i].update();
148 #ifdef HAVE_LCD_BITMAP
149 list_init();
150 #endif
151 tree_gui_init();
152 /* Keep the order of this 3
153 * Must be done before any code uses the multi-screen API */
154 #ifdef HAVE_USBSTACK
155 /* All threads should be created and public queues registered by now */
156 usb_start_monitoring();
157 #endif
159 #ifdef AUTOROCK
161 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
163 if(file_exists(filename)) /* no complaint if it doesn't exist */
165 plugin_load((char*)filename, NULL); /* start if it does */
168 #endif /* #ifdef AUTOROCK */
170 global_status.last_volume_change = 0;
171 /* no calls INIT_ATTR functions after this point anymore!
172 * see definition of INIT_ATTR in config.h */
173 CHART(">root_menu");
174 root_menu();
177 static int init_dircache(bool preinit) INIT_ATTR;
178 static int init_dircache(bool preinit)
180 #ifdef HAVE_DIRCACHE
181 int result = 0;
182 bool clear = false;
184 if (preinit)
185 dircache_init();
187 if (!global_settings.dircache)
188 return 0;
190 # ifdef HAVE_EEPROM_SETTINGS
191 if (firmware_settings.initialized && firmware_settings.disk_clean
192 && preinit)
194 result = dircache_load();
196 if (result < 0)
198 firmware_settings.disk_clean = false;
199 if (global_status.dircache_size <= 0)
201 /* This will be in default language, settings are not
202 applied yet. Not really any easy way to fix that. */
203 splash(0, str(LANG_SCANNING_DISK));
204 clear = true;
207 dircache_build(global_status.dircache_size);
210 else
211 # endif
213 if (preinit)
214 return -1;
216 if (!dircache_is_enabled()
217 && !dircache_is_initializing())
219 if (global_status.dircache_size <= 0)
221 splash(0, str(LANG_SCANNING_DISK));
222 clear = true;
224 result = dircache_build(global_status.dircache_size);
227 if (result < 0)
229 /* Initialization of dircache failed. Manual action is
230 * necessary to enable dircache again.
232 splashf(0, "Dircache failed, disabled. Result: %d", result);
233 global_settings.dircache = false;
237 if (clear)
239 backlight_on();
240 show_logo();
241 global_status.dircache_size = dircache_get_cache_size();
242 status_save();
245 return result;
246 #else
247 (void)preinit;
248 return 0;
249 #endif
252 #ifdef HAVE_TAGCACHE
253 static void init_tagcache(void) INIT_ATTR;
254 static void init_tagcache(void)
256 bool clear = false;
257 #if CONFIG_CODEC == SWCODEC
258 long talked_tick = 0;
259 #endif
260 tagcache_init();
262 while (!tagcache_is_initialized())
264 int ret = tagcache_get_commit_step();
266 if (ret > 0)
268 #if CONFIG_CODEC == SWCODEC
269 /* hwcodec can't use voice here, as the database commit
270 * uses the audio buffer. */
271 if(global_settings.talk_menu
272 && (talked_tick == 0
273 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
275 talked_tick = current_tick;
276 talk_id(LANG_TAGCACHE_INIT, false);
277 talk_number(ret, true);
278 talk_id(VOICE_OF, true);
279 talk_number(tagcache_get_max_commit_step(), true);
281 #endif
282 #ifdef HAVE_LCD_BITMAP
283 if (lang_is_rtl())
285 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
286 str(LANG_TAGCACHE_INIT));
288 else
290 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
291 tagcache_get_max_commit_step());
293 #else
294 lcd_double_height(false);
295 lcd_putsf(0, 1, " DB [%d/%d]", ret,
296 tagcache_get_max_commit_step());
297 lcd_update();
298 #endif
299 clear = true;
301 sleep(HZ/4);
303 tagtree_init();
305 if (clear)
307 backlight_on();
308 show_logo();
311 #endif
313 #ifdef SIMULATOR
315 static void init(void)
317 kernel_init();
318 buffer_init();
319 enable_irq();
320 lcd_init();
321 #ifdef HAVE_REMOTE_LCD
322 lcd_remote_init();
323 #endif
324 font_init();
325 show_logo();
326 button_init();
327 backlight_init();
328 sim_tasks_init();
329 lang_init(core_language_builtin, language_strings,
330 LANG_LAST_INDEX_IN_ARRAY);
331 #ifdef DEBUG
332 debug_init();
333 #endif
334 /* Keep the order of this 3 (viewportmanager handles statusbars)
335 * Must be done before any code uses the multi-screen API */
336 gui_syncstatusbar_init(&statusbars);
337 gui_sync_wps_init();
338 sb_skin_init();
339 viewportmanager_init();
341 storage_init();
342 settings_reset();
343 settings_load(SETTINGS_ALL);
344 settings_apply(true);
345 init_dircache(true);
346 init_dircache(false);
347 #ifdef HAVE_TAGCACHE
348 init_tagcache();
349 #endif
350 sleep(HZ/2);
351 tree_mem_init();
352 filetype_init();
353 playlist_init();
355 #if CONFIG_CODEC != SWCODEC
356 mp3_init( global_settings.volume,
357 global_settings.bass,
358 global_settings.treble,
359 global_settings.balance,
360 global_settings.loudness,
361 global_settings.avc,
362 global_settings.channel_config,
363 global_settings.stereo_width,
364 global_settings.mdb_strength,
365 global_settings.mdb_harmonics,
366 global_settings.mdb_center,
367 global_settings.mdb_shape,
368 global_settings.mdb_enable,
369 global_settings.superbass);
371 /* audio_init must to know the size of voice buffer so init voice first */
372 talk_init();
373 #endif /* CONFIG_CODEC != SWCODEC */
375 scrobbler_init();
376 #if CONFIG_CODEC == SWCODEC
377 tdspeed_init();
378 #endif /* CONFIG_CODEC == SWCODEC */
380 audio_init();
381 button_clear_queue(); /* Empty the keyboard buffer */
383 settings_apply_skins();
386 #else
388 static void init(void) INIT_ATTR;
389 static void init(void)
391 int rc;
392 bool mounted = false;
393 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
394 /* if nobody initialized ATA before, I consider this a cold start */
395 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
396 #endif
398 system_init();
399 kernel_init();
401 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
402 set_cpu_frequency(CPUFREQ_NORMAL);
403 #ifdef CPU_COLDFIRE
404 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
405 #endif
406 cpu_boost(true);
407 #endif
409 buffer_init();
411 settings_reset();
413 i2c_init();
415 power_init();
417 enable_irq();
418 #ifdef CPU_ARM
419 enable_fiq();
420 #endif
421 /* current_tick should be ticking by now */
422 CHART("ticking");
424 lcd_init();
425 #ifdef HAVE_REMOTE_LCD
426 lcd_remote_init();
427 #endif
428 font_init();
430 CHART(">show_logo");
431 show_logo();
432 CHART("<show_logo");
433 lang_init(core_language_builtin, language_strings,
434 LANG_LAST_INDEX_IN_ARRAY);
436 #ifdef DEBUG
437 debug_init();
438 #else
439 #ifdef HAVE_SERIAL
440 serial_setup();
441 #endif
442 #endif
444 #if CONFIG_RTC
445 rtc_init();
446 #endif
447 #ifdef HAVE_RTC_RAM
448 CHART(">settings_load(RTC)");
449 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
450 CHART("<settings_load(RTC)");
451 #endif
453 adc_init();
455 usb_init();
456 #if CONFIG_USBOTG == USBOTG_ISP1362
457 isp1362_init();
458 #elif CONFIG_USBOTG == USBOTG_M5636
459 m5636_init();
460 #endif
462 backlight_init();
464 button_init();
466 powermgmt_init();
468 #if CONFIG_TUNER
469 radio_init();
470 #endif
472 /* Keep the order of this 3 (viewportmanager handles statusbars)
473 * Must be done before any code uses the multi-screen API */
474 CHART(">gui_syncstatusbar_init");
475 gui_syncstatusbar_init(&statusbars);
476 CHART("<gui_syncstatusbar_init");
477 CHART(">sb_skin_init");
478 sb_skin_init();
479 CHART("<sb_skin_init");
480 CHART(">gui_sync_wps_init");
481 gui_sync_wps_init();
482 CHART("<gui_sync_wps_init");
483 CHART(">viewportmanager_init");
484 viewportmanager_init();
485 CHART("<viewportmanager_init");
487 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
488 /* charger_inserted() can't be used here because power_thread()
489 hasn't checked power_input_status() yet */
490 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
491 && !global_settings.car_adapter_mode
492 #ifdef ATA_POWER_PLAYERSTYLE
493 && !ide_powered() /* relies on probing result from bootloader */
494 #endif
497 rc = charging_screen(); /* display a "charging" screen */
498 if (rc == 1) /* charger removed */
499 power_off();
500 /* "On" pressed or USB connected: proceed */
501 show_logo(); /* again, to provide better visual feedback */
503 #endif
505 CHART(">storage_init");
506 rc = storage_init();
507 CHART("<storage_init");
508 if(rc)
510 #ifdef HAVE_LCD_BITMAP
511 lcd_clear_display();
512 lcd_putsf(0, 1, "ATA error: %d", rc);
513 lcd_puts(0, 3, "Press ON to debug");
514 lcd_update();
515 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
516 dbg_ports();
517 #endif
518 panicf("ata: %d", rc);
521 #ifdef HAVE_EEPROM_SETTINGS
522 CHART(">eeprom_settings_init");
523 eeprom_settings_init();
524 CHART("<eeprom_settings_init");
525 #endif
527 #ifndef HAVE_USBSTACK
528 usb_start_monitoring();
529 while (usb_detect() == USB_INSERTED)
531 #ifdef HAVE_EEPROM_SETTINGS
532 firmware_settings.disk_clean = false;
533 #endif
534 /* enter USB mode early, before trying to mount */
535 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
536 #if (CONFIG_STORAGE & STORAGE_MMC)
537 if (!mmc_touched() ||
538 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
539 #endif
541 gui_usb_screen_run();
542 mounted = true; /* mounting done @ end of USB mode */
544 #ifdef HAVE_USB_POWER
545 if (usb_powered()) /* avoid deadlock */
546 break;
547 #endif
549 #endif
551 if (!mounted)
553 CHART(">disk_mount_all");
554 rc = disk_mount_all();
555 CHART("<disk_mount_all");
556 if (rc<=0)
558 lcd_clear_display();
559 lcd_puts(0, 0, "No partition");
560 lcd_puts(0, 1, "found.");
561 #ifdef HAVE_LCD_BITMAP
562 lcd_puts(0, 2, "Insert USB cable");
563 lcd_puts(0, 3, "and fix it.");
564 #endif
565 lcd_update();
567 while(button_get(true) != SYS_USB_CONNECTED) {};
568 gui_usb_screen_run();
569 system_reboot();
573 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
574 (CONFIG_KEYPAD == IRIVER_H10_PAD)
575 #ifdef SETTINGS_RESET
576 /* Reset settings if holding the reset button. (Rec on Archos,
577 A on Gigabeat) */
578 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
579 #else
580 /* Reset settings if the hold button is turned on */
581 if (button_hold())
582 #endif
584 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
585 settings_reset();
587 else
588 #endif
590 CHART(">settings_load(ALL)");
591 settings_load(SETTINGS_ALL);
592 CHART("<settings_load(ALL)");
595 CHART(">init_dircache(true)");
596 rc = init_dircache(true);
597 CHART("<init_dircache(true)");
598 if (rc < 0)
600 #ifdef HAVE_TAGCACHE
601 remove(TAGCACHE_STATEFILE);
602 #endif
605 CHART(">settings_apply(true)");
606 settings_apply(true);
607 CHART("<settings_apply(true)");
608 CHART(">init_dircache(false)");
609 init_dircache(false);
610 CHART("<init_dircache(false)");
611 #ifdef HAVE_TAGCACHE
612 CHART(">init_tagcache");
613 init_tagcache();
614 CHART("<init_tagcache");
615 #endif
617 #ifdef HAVE_EEPROM_SETTINGS
618 if (firmware_settings.initialized)
620 /* In case we crash. */
621 firmware_settings.disk_clean = false;
622 CHART(">eeprom_settings_store");
623 eeprom_settings_store();
624 CHART("<eeprom_settings_store");
626 #endif
627 playlist_init();
628 tree_mem_init();
629 filetype_init();
630 scrobbler_init();
631 #if CONFIG_CODEC == SWCODEC
632 tdspeed_init();
633 #endif /* CONFIG_CODEC == SWCODEC */
635 #if CONFIG_CODEC != SWCODEC
636 /* No buffer allocation (see buffer.c) may take place after the call to
637 audio_init() since the mpeg thread takes the rest of the buffer space */
638 mp3_init( global_settings.volume,
639 global_settings.bass,
640 global_settings.treble,
641 global_settings.balance,
642 global_settings.loudness,
643 global_settings.avc,
644 global_settings.channel_config,
645 global_settings.stereo_width,
646 global_settings.mdb_strength,
647 global_settings.mdb_harmonics,
648 global_settings.mdb_center,
649 global_settings.mdb_shape,
650 global_settings.mdb_enable,
651 global_settings.superbass);
653 /* audio_init must to know the size of voice buffer so init voice first */
654 talk_init();
655 #endif /* CONFIG_CODEC != SWCODEC */
657 CHART(">audio_init");
658 audio_init();
659 CHART("<audio_init");
661 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
662 pcm_rec_init();
663 #endif
665 /* runtime database has to be initialized after audio_init() */
666 cpu_boost(false);
668 #if CONFIG_CHARGING
669 car_adapter_mode_init();
670 #endif
671 #ifdef IPOD_ACCESSORY_PROTOCOL
672 iap_setup(global_settings.serial_bitrate);
673 #endif
674 #ifdef HAVE_ACCESSORY_SUPPLY
675 accessory_supply_set(global_settings.accessory_supply);
676 #endif
677 #ifdef HAVE_LINEOUT_POWEROFF
678 lineout_set(global_settings.lineout_active);
679 #endif
680 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
681 CHART("<check_bootfile(false)");
682 check_bootfile(false); /* remember write time and filesize */
683 CHART(">check_bootfile(false)");
684 #endif
685 CHART("<settings_apply_skins");
686 settings_apply_skins();
687 CHART(">settings_apply_skins");
690 #ifdef CPU_PP
691 void cop_main(void)
693 /* This is the entry point for the coprocessor
694 Anyone not running an upgraded bootloader will never reach this point,
695 so it should not be assumed that the coprocessor be usable even on
696 platforms which support it.
698 A kernel thread is initially setup on the coprocessor and immediately
699 destroyed for purposes of continuity. The cop sits idle until at least
700 one thread exists on it. */
702 /* 3G doesn't have Rolo or dual core support yet */
703 #if NUM_CORES > 1
704 system_init();
705 kernel_init();
706 /* This should never be reached */
707 #endif
708 while(1) {
709 sleep_core(COP);
712 #endif /* CPU_PP */
714 #endif