Theme Editor: Opening an already opened document no longer spawns a new tab
[kugel-rb.git] / apps / main.c
blob858ec038476f2877c708e24dbf8058a8d6c74145
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 static void init(void);
125 #ifdef HAVE_SDL
126 #if defined(WIN32) && defined(main)
127 /* Don't use SDL_main on windows -> no more stdio redirection */
128 #undef main
129 #endif
130 int main(int argc, char *argv[])
132 sys_handle_argv(argc, argv);
133 #else
134 /* main(), and various functions called by main() and init() may be
135 * be INIT_ATTR. These functions must not be called after the final call
136 * to root_menu() at the end of main()
137 * see definition of INIT_ATTR in config.h */
138 int main(void) INIT_ATTR __attribute__((noreturn));
139 int main(void)
141 #endif
142 int i;
143 CHART(">init");
144 init();
145 CHART("<init");
146 FOR_NB_SCREENS(i)
148 screens[i].clear_display();
149 screens[i].update();
151 #ifdef HAVE_LCD_BITMAP
152 list_init();
153 #endif
154 tree_gui_init();
155 /* Keep the order of this 3
156 * Must be done before any code uses the multi-screen API */
157 #ifdef HAVE_USBSTACK
158 /* All threads should be created and public queues registered by now */
159 usb_start_monitoring();
160 #endif
162 #ifdef AUTOROCK
164 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
166 if(file_exists(filename)) /* no complaint if it doesn't exist */
168 plugin_load((char*)filename, NULL); /* start if it does */
171 #endif /* #ifdef AUTOROCK */
173 global_status.last_volume_change = 0;
174 /* no calls INIT_ATTR functions after this point anymore!
175 * see definition of INIT_ATTR in config.h */
176 CHART(">root_menu");
177 root_menu();
180 static int init_dircache(bool preinit) INIT_ATTR;
181 static int init_dircache(bool preinit)
183 #ifdef HAVE_DIRCACHE
184 int result = 0;
185 bool clear = false;
187 if (preinit)
188 dircache_init();
190 if (!global_settings.dircache)
191 return 0;
193 # ifdef HAVE_EEPROM_SETTINGS
194 if (firmware_settings.initialized && firmware_settings.disk_clean
195 && preinit)
197 result = dircache_load();
199 if (result < 0)
201 firmware_settings.disk_clean = false;
202 if (global_status.dircache_size <= 0)
204 /* This will be in default language, settings are not
205 applied yet. Not really any easy way to fix that. */
206 splash(0, str(LANG_SCANNING_DISK));
207 clear = true;
210 dircache_build(global_status.dircache_size);
213 else
214 # endif
216 if (preinit)
217 return -1;
219 if (!dircache_is_enabled()
220 && !dircache_is_initializing())
222 if (global_status.dircache_size <= 0)
224 splash(0, str(LANG_SCANNING_DISK));
225 clear = true;
227 result = dircache_build(global_status.dircache_size);
230 if (result < 0)
232 /* Initialization of dircache failed. Manual action is
233 * necessary to enable dircache again.
235 splashf(0, "Dircache failed, disabled. Result: %d", result);
236 global_settings.dircache = false;
240 if (clear)
242 backlight_on();
243 show_logo();
244 global_status.dircache_size = dircache_get_cache_size();
245 status_save();
248 return result;
249 #else
250 (void)preinit;
251 return 0;
252 #endif
255 #ifdef HAVE_TAGCACHE
256 static void init_tagcache(void) INIT_ATTR;
257 static void init_tagcache(void)
259 bool clear = false;
260 #if CONFIG_CODEC == SWCODEC
261 long talked_tick = 0;
262 #endif
263 tagcache_init();
265 while (!tagcache_is_initialized())
267 int ret = tagcache_get_commit_step();
269 if (ret > 0)
271 #if CONFIG_CODEC == SWCODEC
272 /* hwcodec can't use voice here, as the database commit
273 * uses the audio buffer. */
274 if(global_settings.talk_menu
275 && (talked_tick == 0
276 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
278 talked_tick = current_tick;
279 talk_id(LANG_TAGCACHE_INIT, false);
280 talk_number(ret, true);
281 talk_id(VOICE_OF, true);
282 talk_number(tagcache_get_max_commit_step(), true);
284 #endif
285 #ifdef HAVE_LCD_BITMAP
286 if (lang_is_rtl())
288 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
289 str(LANG_TAGCACHE_INIT));
291 else
293 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
294 tagcache_get_max_commit_step());
296 #else
297 lcd_double_height(false);
298 lcd_putsf(0, 1, " DB [%d/%d]", ret,
299 tagcache_get_max_commit_step());
300 lcd_update();
301 #endif
302 clear = true;
304 sleep(HZ/4);
306 tagtree_init();
308 if (clear)
310 backlight_on();
311 show_logo();
314 #endif
316 #ifdef SIMULATOR
318 static void init(void)
320 system_init();
321 kernel_init();
322 buffer_init();
323 enable_irq();
324 lcd_init();
325 #ifdef HAVE_REMOTE_LCD
326 lcd_remote_init();
327 #endif
328 font_init();
329 show_logo();
330 button_init();
331 backlight_init();
332 sim_tasks_init();
333 lang_init(core_language_builtin, language_strings,
334 LANG_LAST_INDEX_IN_ARRAY);
335 #ifdef DEBUG
336 debug_init();
337 #endif
338 /* Keep the order of this 3 (viewportmanager handles statusbars)
339 * Must be done before any code uses the multi-screen API */
340 gui_syncstatusbar_init(&statusbars);
341 gui_sync_wps_init();
342 sb_skin_init();
343 viewportmanager_init();
345 storage_init();
346 settings_reset();
347 settings_load(SETTINGS_ALL);
348 settings_apply(true);
349 init_dircache(true);
350 init_dircache(false);
351 #ifdef HAVE_TAGCACHE
352 init_tagcache();
353 #endif
354 sleep(HZ/2);
355 tree_mem_init();
356 filetype_init();
357 playlist_init();
359 #if CONFIG_CODEC != SWCODEC
360 mp3_init( global_settings.volume,
361 global_settings.bass,
362 global_settings.treble,
363 global_settings.balance,
364 global_settings.loudness,
365 global_settings.avc,
366 global_settings.channel_config,
367 global_settings.stereo_width,
368 global_settings.mdb_strength,
369 global_settings.mdb_harmonics,
370 global_settings.mdb_center,
371 global_settings.mdb_shape,
372 global_settings.mdb_enable,
373 global_settings.superbass);
375 /* audio_init must to know the size of voice buffer so init voice first */
376 talk_init();
377 #endif /* CONFIG_CODEC != SWCODEC */
379 scrobbler_init();
380 #if CONFIG_CODEC == SWCODEC
381 tdspeed_init();
382 #endif /* CONFIG_CODEC == SWCODEC */
384 audio_init();
385 button_clear_queue(); /* Empty the keyboard buffer */
387 settings_apply_skins();
390 #else
392 static void init(void) INIT_ATTR;
393 static void init(void)
395 int rc;
396 bool mounted = false;
397 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
398 /* if nobody initialized ATA before, I consider this a cold start */
399 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
400 #endif
402 system_init();
403 kernel_init();
405 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
406 set_cpu_frequency(CPUFREQ_NORMAL);
407 #ifdef CPU_COLDFIRE
408 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
409 #endif
410 cpu_boost(true);
411 #endif
413 buffer_init();
415 settings_reset();
417 i2c_init();
419 power_init();
421 enable_irq();
422 #ifdef CPU_ARM
423 enable_fiq();
424 #endif
425 /* current_tick should be ticking by now */
426 CHART("ticking");
428 lcd_init();
429 #ifdef HAVE_REMOTE_LCD
430 lcd_remote_init();
431 #endif
432 font_init();
434 CHART(">show_logo");
435 show_logo();
436 CHART("<show_logo");
437 lang_init(core_language_builtin, language_strings,
438 LANG_LAST_INDEX_IN_ARRAY);
440 #ifdef DEBUG
441 debug_init();
442 #else
443 #ifdef HAVE_SERIAL
444 serial_setup();
445 #endif
446 #endif
448 #if CONFIG_RTC
449 rtc_init();
450 #endif
451 #ifdef HAVE_RTC_RAM
452 CHART(">settings_load(RTC)");
453 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
454 CHART("<settings_load(RTC)");
455 #endif
457 adc_init();
459 usb_init();
460 #if CONFIG_USBOTG == USBOTG_ISP1362
461 isp1362_init();
462 #elif CONFIG_USBOTG == USBOTG_M5636
463 m5636_init();
464 #endif
466 backlight_init();
468 button_init();
470 powermgmt_init();
472 #if CONFIG_TUNER
473 radio_init();
474 #endif
476 /* Keep the order of this 3 (viewportmanager handles statusbars)
477 * Must be done before any code uses the multi-screen API */
478 CHART(">gui_syncstatusbar_init");
479 gui_syncstatusbar_init(&statusbars);
480 CHART("<gui_syncstatusbar_init");
481 CHART(">sb_skin_init");
482 sb_skin_init();
483 CHART("<sb_skin_init");
484 CHART(">gui_sync_wps_init");
485 gui_sync_wps_init();
486 CHART("<gui_sync_wps_init");
487 CHART(">viewportmanager_init");
488 viewportmanager_init();
489 CHART("<viewportmanager_init");
491 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
492 /* charger_inserted() can't be used here because power_thread()
493 hasn't checked power_input_status() yet */
494 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
495 && !global_settings.car_adapter_mode
496 #ifdef ATA_POWER_PLAYERSTYLE
497 && !ide_powered() /* relies on probing result from bootloader */
498 #endif
501 rc = charging_screen(); /* display a "charging" screen */
502 if (rc == 1) /* charger removed */
503 power_off();
504 /* "On" pressed or USB connected: proceed */
505 show_logo(); /* again, to provide better visual feedback */
507 #endif
510 disk_init_subsystem();
511 CHART(">storage_init");
512 rc = storage_init();
513 CHART("<storage_init");
514 if(rc)
516 #ifdef HAVE_LCD_BITMAP
517 lcd_clear_display();
518 lcd_putsf(0, 1, "ATA error: %d", rc);
519 lcd_puts(0, 3, "Press ON to debug");
520 lcd_update();
521 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
522 dbg_ports();
523 #endif
524 panicf("ata: %d", rc);
527 #ifdef HAVE_EEPROM_SETTINGS
528 CHART(">eeprom_settings_init");
529 eeprom_settings_init();
530 CHART("<eeprom_settings_init");
531 #endif
533 #ifndef HAVE_USBSTACK
534 usb_start_monitoring();
535 while (usb_detect() == USB_INSERTED)
537 #ifdef HAVE_EEPROM_SETTINGS
538 firmware_settings.disk_clean = false;
539 #endif
540 /* enter USB mode early, before trying to mount */
541 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
542 #if (CONFIG_STORAGE & STORAGE_MMC)
543 if (!mmc_touched() ||
544 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
545 #endif
547 gui_usb_screen_run();
548 mounted = true; /* mounting done @ end of USB mode */
550 #ifdef HAVE_USB_POWER
551 if (usb_powered()) /* avoid deadlock */
552 break;
553 #endif
555 #endif
557 if (!mounted)
559 CHART(">disk_mount_all");
560 rc = disk_mount_all();
561 CHART("<disk_mount_all");
562 if (rc<=0)
564 lcd_clear_display();
565 lcd_puts(0, 0, "No partition");
566 lcd_puts(0, 1, "found.");
567 #ifdef HAVE_LCD_BITMAP
568 lcd_puts(0, 2, "Insert USB cable");
569 lcd_puts(0, 3, "and fix it.");
570 #endif
571 lcd_update();
573 while(button_get(true) != SYS_USB_CONNECTED) {};
574 gui_usb_screen_run();
575 system_reboot();
579 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
580 (CONFIG_KEYPAD == IRIVER_H10_PAD)
581 #ifdef SETTINGS_RESET
582 /* Reset settings if holding the reset button. (Rec on Archos,
583 A on Gigabeat) */
584 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
585 #else
586 /* Reset settings if the hold button is turned on */
587 if (button_hold())
588 #endif
590 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
591 settings_reset();
593 else
594 #endif
596 CHART(">settings_load(ALL)");
597 settings_load(SETTINGS_ALL);
598 CHART("<settings_load(ALL)");
601 CHART(">init_dircache(true)");
602 rc = init_dircache(true);
603 CHART("<init_dircache(true)");
604 if (rc < 0)
606 #ifdef HAVE_TAGCACHE
607 remove(TAGCACHE_STATEFILE);
608 #endif
611 CHART(">settings_apply(true)");
612 settings_apply(true);
613 CHART("<settings_apply(true)");
614 CHART(">init_dircache(false)");
615 init_dircache(false);
616 CHART("<init_dircache(false)");
617 #ifdef HAVE_TAGCACHE
618 CHART(">init_tagcache");
619 init_tagcache();
620 CHART("<init_tagcache");
621 #endif
623 #ifdef HAVE_EEPROM_SETTINGS
624 if (firmware_settings.initialized)
626 /* In case we crash. */
627 firmware_settings.disk_clean = false;
628 CHART(">eeprom_settings_store");
629 eeprom_settings_store();
630 CHART("<eeprom_settings_store");
632 #endif
633 playlist_init();
634 tree_mem_init();
635 filetype_init();
636 scrobbler_init();
637 #if CONFIG_CODEC == SWCODEC
638 tdspeed_init();
639 #endif /* CONFIG_CODEC == SWCODEC */
641 #if CONFIG_CODEC != SWCODEC
642 /* No buffer allocation (see buffer.c) may take place after the call to
643 audio_init() since the mpeg thread takes the rest of the buffer space */
644 mp3_init( global_settings.volume,
645 global_settings.bass,
646 global_settings.treble,
647 global_settings.balance,
648 global_settings.loudness,
649 global_settings.avc,
650 global_settings.channel_config,
651 global_settings.stereo_width,
652 global_settings.mdb_strength,
653 global_settings.mdb_harmonics,
654 global_settings.mdb_center,
655 global_settings.mdb_shape,
656 global_settings.mdb_enable,
657 global_settings.superbass);
659 /* audio_init must to know the size of voice buffer so init voice first */
660 talk_init();
661 #endif /* CONFIG_CODEC != SWCODEC */
663 CHART(">audio_init");
664 audio_init();
665 CHART("<audio_init");
667 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
668 pcm_rec_init();
669 #endif
671 /* runtime database has to be initialized after audio_init() */
672 cpu_boost(false);
674 #if CONFIG_CHARGING
675 car_adapter_mode_init();
676 #endif
677 #ifdef IPOD_ACCESSORY_PROTOCOL
678 iap_setup(global_settings.serial_bitrate);
679 #endif
680 #ifdef HAVE_ACCESSORY_SUPPLY
681 accessory_supply_set(global_settings.accessory_supply);
682 #endif
683 #ifdef HAVE_LINEOUT_POWEROFF
684 lineout_set(global_settings.lineout_active);
685 #endif
686 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
687 CHART("<check_bootfile(false)");
688 check_bootfile(false); /* remember write time and filesize */
689 CHART(">check_bootfile(false)");
690 #endif
691 CHART("<settings_apply_skins");
692 settings_apply_skins();
693 CHART(">settings_apply_skins");
696 #ifdef CPU_PP
697 void cop_main(void)
699 /* This is the entry point for the coprocessor
700 Anyone not running an upgraded bootloader will never reach this point,
701 so it should not be assumed that the coprocessor be usable even on
702 platforms which support it.
704 A kernel thread is initially setup on the coprocessor and immediately
705 destroyed for purposes of continuity. The cop sits idle until at least
706 one thread exists on it. */
708 /* 3G doesn't have Rolo or dual core support yet */
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