Manual: Add button mappings for the equalizer for the clip/clip+. Fixes part of FS...
[kugel-rb.git] / apps / main.c
blob950168d8edb41023d516e62df2c350b8dbaa8e49
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 "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 "skin_engine/skin_engine.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 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
118 #define MAIN_NORETURN_ATTR NORETURN_ATTR
119 #else
120 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
121 * with noreturn attribute */
122 #define MAIN_NORETURN_ATTR
123 #endif
125 #if (CONFIG_PLATFORM & PLATFORM_SDL)
126 #include "sim_tasks.h"
127 #include "system-sdl.h"
128 #define HAVE_ARGV_MAIN
129 /* Don't use SDL_main on windows -> no more stdio redirection */
130 #if defined(WIN32)
131 #undef main
132 #endif
133 #endif
135 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
137 static void init(void);
138 /* main(), and various functions called by main() and init() may be
139 * be INIT_ATTR. These functions must not be called after the final call
140 * to root_menu() at the end of main()
141 * see definition of INIT_ATTR in config.h */
142 #ifdef HAVE_ARGV_MAIN
143 int main(int argc, char *argv[]) INIT_ATTR MAIN_NORETURN_ATTR ;
144 int main(int argc, char *argv[])
146 sys_handle_argv(argc, argv);
147 #else
148 int main(void) INIT_ATTR MAIN_NORETURN_ATTR;
149 int main(void)
151 #endif
152 int i;
153 CHART(">init");
154 init();
155 CHART("<init");
156 FOR_NB_SCREENS(i)
158 screens[i].clear_display();
159 screens[i].update();
161 #ifdef HAVE_LCD_BITMAP
162 list_init();
163 #endif
164 tree_gui_init();
165 /* Keep the order of this 3
166 * Must be done before any code uses the multi-screen API */
167 #ifdef HAVE_USBSTACK
168 /* All threads should be created and public queues registered by now */
169 usb_start_monitoring();
170 #endif
172 #ifdef AUTOROCK
174 char filename[MAX_PATH];
175 const char *file = get_user_file_path(
176 #ifdef APPLICATION
177 ROCKBOX_DIR
178 #else
179 PLUGIN_APPS_DIR
180 #endif
181 "/autostart.rock", NEED_WRITE|IS_FILE, filename, sizeof(filename));
182 if(file_exists(file)) /* no complaint if it doesn't exist */
184 plugin_load(file, NULL); /* start if it does */
187 #endif /* #ifdef AUTOROCK */
189 global_status.last_volume_change = 0;
190 /* no calls INIT_ATTR functions after this point anymore!
191 * see definition of INIT_ATTR in config.h */
192 CHART(">root_menu");
193 root_menu();
196 static int init_dircache(bool preinit) INIT_ATTR;
197 static int init_dircache(bool preinit)
199 #ifdef HAVE_DIRCACHE
200 int result = 0;
201 bool clear = false;
203 if (preinit)
204 dircache_init();
206 if (!global_settings.dircache)
207 return 0;
209 # ifdef HAVE_EEPROM_SETTINGS
210 if (firmware_settings.initialized && firmware_settings.disk_clean
211 && preinit)
213 result = dircache_load();
215 if (result < 0)
217 firmware_settings.disk_clean = false;
218 if (global_status.dircache_size <= 0)
220 /* This will be in default language, settings are not
221 applied yet. Not really any easy way to fix that. */
222 splash(0, str(LANG_SCANNING_DISK));
223 clear = true;
226 dircache_build(global_status.dircache_size);
229 else
230 # endif
232 if (preinit)
233 return -1;
235 if (!dircache_is_enabled()
236 && !dircache_is_initializing())
238 if (global_status.dircache_size <= 0)
240 splash(0, str(LANG_SCANNING_DISK));
241 clear = true;
243 result = dircache_build(global_status.dircache_size);
246 if (result < 0)
248 /* Initialization of dircache failed. Manual action is
249 * necessary to enable dircache again.
251 splashf(0, "Dircache failed, disabled. Result: %d", result);
252 global_settings.dircache = false;
256 if (clear)
258 backlight_on();
259 show_logo();
260 global_status.dircache_size = dircache_get_cache_size();
261 status_save();
264 return result;
265 #else
266 (void)preinit;
267 return 0;
268 #endif
271 #ifdef HAVE_TAGCACHE
272 static void init_tagcache(void) INIT_ATTR;
273 static void init_tagcache(void)
275 bool clear = false;
276 #if CONFIG_CODEC == SWCODEC
277 long talked_tick = 0;
278 #endif
279 tagcache_init();
281 while (!tagcache_is_initialized())
283 int ret = tagcache_get_commit_step();
285 if (ret > 0)
287 #if CONFIG_CODEC == SWCODEC
288 /* hwcodec can't use voice here, as the database commit
289 * uses the audio buffer. */
290 if(global_settings.talk_menu
291 && (talked_tick == 0
292 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
294 talked_tick = current_tick;
295 talk_id(LANG_TAGCACHE_INIT, false);
296 talk_number(ret, true);
297 talk_id(VOICE_OF, true);
298 talk_number(tagcache_get_max_commit_step(), true);
300 #endif
301 #ifdef HAVE_LCD_BITMAP
302 if (lang_is_rtl())
304 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
305 str(LANG_TAGCACHE_INIT));
307 else
309 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
310 tagcache_get_max_commit_step());
312 #else
313 lcd_double_height(false);
314 lcd_putsf(0, 1, " DB [%d/%d]", ret,
315 tagcache_get_max_commit_step());
316 lcd_update();
317 #endif
318 clear = true;
320 sleep(HZ/4);
322 tagtree_init();
324 if (clear)
326 backlight_on();
327 show_logo();
330 #endif
332 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
334 static void init(void)
336 #ifdef APPLICATION
337 paths_init();
338 #endif
339 system_init();
340 kernel_init();
341 buffer_init();
342 enable_irq();
343 lcd_init();
344 #ifdef HAVE_REMOTE_LCD
345 lcd_remote_init();
346 #endif
347 font_init();
348 show_logo();
349 button_init();
350 backlight_init();
351 #if (CONFIG_PLATFORM & PLATFORM_SDL)
352 sim_tasks_init();
353 #endif
354 lang_init(core_language_builtin, language_strings,
355 LANG_LAST_INDEX_IN_ARRAY);
356 #ifdef DEBUG
357 debug_init();
358 #endif
359 /* Keep the order of this 3 (viewportmanager handles statusbars)
360 * Must be done before any code uses the multi-screen API */
361 gui_syncstatusbar_init(&statusbars);
362 gui_sync_skin_init();
363 sb_skin_init();
364 viewportmanager_init();
366 storage_init();
367 settings_reset();
368 settings_load(SETTINGS_ALL);
369 settings_apply(true);
370 init_dircache(true);
371 init_dircache(false);
372 #ifdef HAVE_TAGCACHE
373 init_tagcache();
374 #endif
375 sleep(HZ/2);
376 tree_mem_init();
377 filetype_init();
378 playlist_init();
379 theme_init_buffer();
381 #if CONFIG_CODEC != SWCODEC
382 mp3_init( global_settings.volume,
383 global_settings.bass,
384 global_settings.treble,
385 global_settings.balance,
386 global_settings.loudness,
387 global_settings.avc,
388 global_settings.channel_config,
389 global_settings.stereo_width,
390 global_settings.mdb_strength,
391 global_settings.mdb_harmonics,
392 global_settings.mdb_center,
393 global_settings.mdb_shape,
394 global_settings.mdb_enable,
395 global_settings.superbass);
397 /* audio_init must to know the size of voice buffer so init voice first */
398 talk_init();
399 #endif /* CONFIG_CODEC != SWCODEC */
401 scrobbler_init();
402 #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
403 tdspeed_init();
404 #endif /* CONFIG_CODEC == SWCODEC */
406 audio_init();
407 button_clear_queue(); /* Empty the keyboard buffer */
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 #if defined(IPOD_VIDEO)
426 audiobufend=(unsigned char *)audiobufend_lds;
427 if(MEM==64 && probed_ramsize!=64)
429 audiobufend -= (32<<20);
431 #endif
432 kernel_init();
434 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
435 set_cpu_frequency(CPUFREQ_NORMAL);
436 #ifdef CPU_COLDFIRE
437 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
438 #endif
439 cpu_boost(true);
440 #endif
442 buffer_init();
444 settings_reset();
446 i2c_init();
448 power_init();
450 enable_irq();
451 #ifdef CPU_ARM
452 enable_fiq();
453 #endif
454 /* current_tick should be ticking by now */
455 CHART("ticking");
457 lcd_init();
458 #ifdef HAVE_REMOTE_LCD
459 lcd_remote_init();
460 #endif
461 font_init();
463 CHART(">show_logo");
464 show_logo();
465 CHART("<show_logo");
466 lang_init(core_language_builtin, language_strings,
467 LANG_LAST_INDEX_IN_ARRAY);
469 #ifdef DEBUG
470 debug_init();
471 #else
472 #ifdef HAVE_SERIAL
473 serial_setup();
474 #endif
475 #endif
477 #if CONFIG_RTC
478 rtc_init();
479 #endif
480 #ifdef HAVE_RTC_RAM
481 CHART(">settings_load(RTC)");
482 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
483 CHART("<settings_load(RTC)");
484 #endif
486 adc_init();
488 usb_init();
489 #if CONFIG_USBOTG == USBOTG_ISP1362
490 isp1362_init();
491 #elif CONFIG_USBOTG == USBOTG_M5636
492 m5636_init();
493 #endif
495 backlight_init();
497 button_init();
499 powermgmt_init();
501 #if CONFIG_TUNER
502 radio_init();
503 #endif
505 /* Keep the order of this 3 (viewportmanager handles statusbars)
506 * Must be done before any code uses the multi-screen API */
507 CHART(">gui_syncstatusbar_init");
508 gui_syncstatusbar_init(&statusbars);
509 CHART("<gui_syncstatusbar_init");
510 CHART(">sb_skin_init");
511 sb_skin_init();
512 CHART("<sb_skin_init");
513 CHART(">gui_sync_wps_init");
514 gui_sync_skin_init();
515 CHART("<gui_sync_wps_init");
516 CHART(">viewportmanager_init");
517 viewportmanager_init();
518 CHART("<viewportmanager_init");
520 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
521 /* charger_inserted() can't be used here because power_thread()
522 hasn't checked power_input_status() yet */
523 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
524 && !global_settings.car_adapter_mode
525 #ifdef ATA_POWER_PLAYERSTYLE
526 && !ide_powered() /* relies on probing result from bootloader */
527 #endif
530 rc = charging_screen(); /* display a "charging" screen */
531 if (rc == 1) /* charger removed */
532 power_off();
533 /* "On" pressed or USB connected: proceed */
534 show_logo(); /* again, to provide better visual feedback */
536 #endif
539 disk_init_subsystem();
540 CHART(">storage_init");
541 rc = storage_init();
542 CHART("<storage_init");
543 if(rc)
545 #ifdef HAVE_LCD_BITMAP
546 lcd_clear_display();
547 lcd_putsf(0, 1, "ATA error: %d", rc);
548 lcd_puts(0, 3, "Press ON to debug");
549 lcd_update();
550 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
551 dbg_ports();
552 #endif
553 panicf("ata: %d", rc);
556 #ifdef HAVE_EEPROM_SETTINGS
557 CHART(">eeprom_settings_init");
558 eeprom_settings_init();
559 CHART("<eeprom_settings_init");
560 #endif
562 #ifndef HAVE_USBSTACK
563 usb_start_monitoring();
564 while (usb_detect() == USB_INSERTED)
566 #ifdef HAVE_EEPROM_SETTINGS
567 firmware_settings.disk_clean = false;
568 #endif
569 /* enter USB mode early, before trying to mount */
570 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
571 #if (CONFIG_STORAGE & STORAGE_MMC)
572 if (!mmc_touched() ||
573 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
574 #endif
576 gui_usb_screen_run(true);
577 mounted = true; /* mounting done @ end of USB mode */
579 #ifdef HAVE_USB_POWER
580 if (usb_powered()) /* avoid deadlock */
581 break;
582 #endif
584 #endif
586 if (!mounted)
588 CHART(">disk_mount_all");
589 rc = disk_mount_all();
590 CHART("<disk_mount_all");
591 if (rc<=0)
593 lcd_clear_display();
594 lcd_puts(0, 0, "No partition");
595 lcd_puts(0, 1, "found.");
596 #ifdef HAVE_LCD_BITMAP
597 lcd_puts(0, 2, "Insert USB cable");
598 lcd_puts(0, 3, "and fix it.");
599 #endif
600 lcd_update();
602 while(button_get(true) != SYS_USB_CONNECTED) {};
603 gui_usb_screen_run(true);
604 system_reboot();
608 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
609 (CONFIG_KEYPAD == IRIVER_H10_PAD)
610 #ifdef SETTINGS_RESET
611 /* Reset settings if holding the reset button. (Rec on Archos,
612 A on Gigabeat) */
613 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
614 #else
615 /* Reset settings if the hold button is turned on */
616 if (button_hold())
617 #endif
619 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
620 settings_reset();
622 else
623 #endif
625 CHART(">settings_load(ALL)");
626 settings_load(SETTINGS_ALL);
627 CHART("<settings_load(ALL)");
630 CHART(">init_dircache(true)");
631 rc = init_dircache(true);
632 CHART("<init_dircache(true)");
633 if (rc < 0)
635 #ifdef HAVE_TAGCACHE
636 remove(TAGCACHE_STATEFILE);
637 #endif
640 CHART(">settings_apply(true)");
641 settings_apply(true);
642 CHART("<settings_apply(true)");
643 CHART(">init_dircache(false)");
644 init_dircache(false);
645 CHART("<init_dircache(false)");
646 #ifdef HAVE_TAGCACHE
647 CHART(">init_tagcache");
648 init_tagcache();
649 CHART("<init_tagcache");
650 #endif
652 #ifdef HAVE_EEPROM_SETTINGS
653 if (firmware_settings.initialized)
655 /* In case we crash. */
656 firmware_settings.disk_clean = false;
657 CHART(">eeprom_settings_store");
658 eeprom_settings_store();
659 CHART("<eeprom_settings_store");
661 #endif
662 playlist_init();
663 tree_mem_init();
664 filetype_init();
665 scrobbler_init();
666 #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
667 tdspeed_init();
668 #endif /* CONFIG_CODEC == SWCODEC */
669 theme_init_buffer();
671 #if CONFIG_CODEC != SWCODEC
672 /* No buffer allocation (see buffer.c) may take place after the call to
673 audio_init() since the mpeg thread takes the rest of the buffer space */
674 mp3_init( global_settings.volume,
675 global_settings.bass,
676 global_settings.treble,
677 global_settings.balance,
678 global_settings.loudness,
679 global_settings.avc,
680 global_settings.channel_config,
681 global_settings.stereo_width,
682 global_settings.mdb_strength,
683 global_settings.mdb_harmonics,
684 global_settings.mdb_center,
685 global_settings.mdb_shape,
686 global_settings.mdb_enable,
687 global_settings.superbass);
689 /* audio_init must to know the size of voice buffer so init voice first */
690 talk_init();
691 #endif /* CONFIG_CODEC != SWCODEC */
693 CHART(">audio_init");
694 audio_init();
695 CHART("<audio_init");
697 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
698 pcm_rec_init();
699 #endif
701 /* runtime database has to be initialized after audio_init() */
702 cpu_boost(false);
704 #if CONFIG_CHARGING
705 car_adapter_mode_init();
706 #endif
707 #ifdef IPOD_ACCESSORY_PROTOCOL
708 iap_setup(global_settings.serial_bitrate);
709 #endif
710 #ifdef HAVE_ACCESSORY_SUPPLY
711 accessory_supply_set(global_settings.accessory_supply);
712 #endif
713 #ifdef HAVE_LINEOUT_POWEROFF
714 lineout_set(global_settings.lineout_active);
715 #endif
716 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
717 CHART("<check_bootfile(false)");
718 check_bootfile(false); /* remember write time and filesize */
719 CHART(">check_bootfile(false)");
720 #endif
721 CHART("<settings_apply_skins");
722 settings_apply_skins();
723 CHART(">settings_apply_skins");
726 #ifdef CPU_PP
727 void cop_main(void) MAIN_NORETURN_ATTR;
728 void cop_main(void)
730 /* This is the entry point for the coprocessor
731 Anyone not running an upgraded bootloader will never reach this point,
732 so it should not be assumed that the coprocessor be usable even on
733 platforms which support it.
735 A kernel thread is initially setup on the coprocessor and immediately
736 destroyed for purposes of continuity. The cop sits idle until at least
737 one thread exists on it. */
739 #if NUM_CORES > 1
740 system_init();
741 kernel_init();
742 /* This should never be reached */
743 #endif
744 while(1) {
745 sleep_core(COP);
748 #endif /* CPU_PP */
750 #endif /* SIMULATOR */