1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
23 #include "gcc_extensions.h"
34 #include "filetypes.h"
39 #include "powermgmt.h"
46 #include "mp3_playback.h"
49 #include "backlight.h"
51 #include "debug_menu.h"
59 #include "usb_screen.h"
72 #include "eeprom_settings.h"
73 #include "scrobbler.h"
76 #include "statusbar-skinned.h"
77 #include "bootchart.h"
79 #ifdef IPOD_ACCESSORY_PROTOCOL
83 #if (CONFIG_CODEC == SWCODEC)
87 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
88 #include "pcm_record.h"
92 #define SETTINGS_RESET BUTTON_REC
93 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
94 #define SETTINGS_RESET BUTTON_A
100 #if (CONFIG_STORAGE & STORAGE_MMC)
104 #ifdef HAVE_REMOTE_LCD
105 #include "lcd-remote.h"
108 #if CONFIG_USBOTG == USBOTG_ISP1362
112 #if CONFIG_USBOTG == USBOTG_M5636
116 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
117 #define MAIN_NORETURN_ATTR NORETURN_ATTR
119 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
120 * with noreturn attribute */
121 #define MAIN_NORETURN_ATTR
124 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
125 #include "sim_tasks.h"
128 #if (CONFIG_PLATFORM & PLATFORM_SDL)
129 #include "system-sdl.h"
130 #define HAVE_ARGV_MAIN
131 /* Don't use SDL_main on windows -> no more stdio redirection */
137 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
139 static void init(void);
140 /* main(), and various functions called by main() and init() may be
141 * be INIT_ATTR. These functions must not be called after the final call
142 * to root_menu() at the end of main()
143 * see definition of INIT_ATTR in config.h */
144 #ifdef HAVE_ARGV_MAIN
145 int main(int argc
, char *argv
[]) INIT_ATTR MAIN_NORETURN_ATTR
;
146 int main(int argc
, char *argv
[])
148 sys_handle_argv(argc
, argv
);
150 int main(void) INIT_ATTR MAIN_NORETURN_ATTR
;
160 screens
[i
].clear_display();
163 #ifdef HAVE_LCD_BITMAP
167 /* Keep the order of this 3
168 * Must be done before any code uses the multi-screen API */
170 /* All threads should be created and public queues registered by now */
171 usb_start_monitoring();
176 char filename
[MAX_PATH
];
177 const char *file
= get_user_file_path(
183 "/autostart.rock", NEED_WRITE
|IS_FILE
, filename
, sizeof(filename
));
184 if(file_exists(file
)) /* no complaint if it doesn't exist */
186 plugin_load(file
, NULL
); /* start if it does */
189 #endif /* #ifdef AUTOROCK */
191 global_status
.last_volume_change
= 0;
192 /* no calls INIT_ATTR functions after this point anymore!
193 * see definition of INIT_ATTR in config.h */
198 static int init_dircache(bool preinit
) INIT_ATTR
;
199 static int init_dircache(bool preinit
)
208 if (!global_settings
.dircache
)
211 # ifdef HAVE_EEPROM_SETTINGS
212 if (firmware_settings
.initialized
&& firmware_settings
.disk_clean
215 result
= dircache_load();
219 firmware_settings
.disk_clean
= false;
220 if (global_status
.dircache_size
<= 0)
222 /* This will be in default language, settings are not
223 applied yet. Not really any easy way to fix that. */
224 splash(0, str(LANG_SCANNING_DISK
));
228 dircache_build(global_status
.dircache_size
);
237 if (!dircache_is_enabled()
238 && !dircache_is_initializing())
240 if (global_status
.dircache_size
<= 0)
242 splash(0, str(LANG_SCANNING_DISK
));
245 result
= dircache_build(global_status
.dircache_size
);
250 /* Initialization of dircache failed. Manual action is
251 * necessary to enable dircache again.
253 splashf(0, "Dircache failed, disabled. Result: %d", result
);
254 global_settings
.dircache
= false;
262 global_status
.dircache_size
= dircache_get_cache_size();
274 static void init_tagcache(void) INIT_ATTR
;
275 static void init_tagcache(void)
278 #if CONFIG_CODEC == SWCODEC
279 long talked_tick
= 0;
283 while (!tagcache_is_initialized())
285 int ret
= tagcache_get_commit_step();
289 #if CONFIG_CODEC == SWCODEC
290 /* hwcodec can't use voice here, as the database commit
291 * uses the audio buffer. */
292 if(global_settings
.talk_menu
294 || TIME_AFTER(current_tick
, talked_tick
+7*HZ
)))
296 talked_tick
= current_tick
;
297 talk_id(LANG_TAGCACHE_INIT
, false);
298 talk_number(ret
, true);
299 talk_id(VOICE_OF
, true);
300 talk_number(tagcache_get_max_commit_step(), true);
303 #ifdef HAVE_LCD_BITMAP
306 splashf(0, "[%d/%d] %s", ret
, tagcache_get_max_commit_step(),
307 str(LANG_TAGCACHE_INIT
));
311 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT
), ret
,
312 tagcache_get_max_commit_step());
315 lcd_double_height(false);
316 lcd_putsf(0, 1, " DB [%d/%d]", ret
,
317 tagcache_get_max_commit_step());
334 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
336 static void init(void)
346 #ifdef HAVE_REMOTE_LCD
354 lang_init(core_language_builtin
, language_strings
,
355 LANG_LAST_INDEX_IN_ARRAY
);
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
);
364 viewportmanager_init();
368 settings_load(SETTINGS_ALL
);
369 settings_apply(true);
371 init_dircache(false);
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
,
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 */
399 #endif /* CONFIG_CODEC != SWCODEC */
402 #if CONFIG_CODEC == SWCODEC
404 #endif /* CONFIG_CODEC == SWCODEC */
407 button_clear_queue(); /* Empty the keyboard buffer */
409 settings_apply_skins();
414 static void init(void) INIT_ATTR
;
415 static void init(void)
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 */
427 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
428 set_cpu_frequency(CPUFREQ_NORMAL
);
430 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS
);
447 /* current_tick should be ticking by now */
451 #ifdef HAVE_REMOTE_LCD
459 lang_init(core_language_builtin
, language_strings
,
460 LANG_LAST_INDEX_IN_ARRAY
);
474 CHART(">settings_load(RTC)");
475 settings_load(SETTINGS_RTC
); /* early load parts of global_settings */
476 CHART("<settings_load(RTC)");
482 #if CONFIG_USBOTG == USBOTG_ISP1362
484 #elif CONFIG_USBOTG == USBOTG_M5636
498 /* Keep the order of this 3 (viewportmanager handles statusbars)
499 * Must be done before any code uses the multi-screen API */
500 CHART(">gui_syncstatusbar_init");
501 gui_syncstatusbar_init(&statusbars
);
502 CHART("<gui_syncstatusbar_init");
503 CHART(">sb_skin_init");
505 CHART("<sb_skin_init");
506 CHART(">gui_sync_wps_init");
508 CHART("<gui_sync_wps_init");
509 CHART(">viewportmanager_init");
510 viewportmanager_init();
511 CHART("<viewportmanager_init");
513 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
514 /* charger_inserted() can't be used here because power_thread()
515 hasn't checked power_input_status() yet */
516 if (coldstart
&& (power_input_status() & POWER_INPUT_MAIN_CHARGER
)
517 && !global_settings
.car_adapter_mode
518 #ifdef ATA_POWER_PLAYERSTYLE
519 && !ide_powered() /* relies on probing result from bootloader */
523 rc
= charging_screen(); /* display a "charging" screen */
524 if (rc
== 1) /* charger removed */
526 /* "On" pressed or USB connected: proceed */
527 show_logo(); /* again, to provide better visual feedback */
532 disk_init_subsystem();
533 CHART(">storage_init");
535 CHART("<storage_init");
538 #ifdef HAVE_LCD_BITMAP
540 lcd_putsf(0, 1, "ATA error: %d", rc
);
541 lcd_puts(0, 3, "Press ON to debug");
543 while(!(button_get(true) & BUTTON_REL
)); /*DO NOT CHANGE TO ACTION SYSTEM */
546 panicf("ata: %d", rc
);
549 #ifdef HAVE_EEPROM_SETTINGS
550 CHART(">eeprom_settings_init");
551 eeprom_settings_init();
552 CHART("<eeprom_settings_init");
555 #ifndef HAVE_USBSTACK
556 usb_start_monitoring();
557 while (usb_detect() == USB_INSERTED
)
559 #ifdef HAVE_EEPROM_SETTINGS
560 firmware_settings
.disk_clean
= false;
562 /* enter USB mode early, before trying to mount */
563 if (button_get_w_tmo(HZ
/10) == SYS_USB_CONNECTED
)
564 #if (CONFIG_STORAGE & STORAGE_MMC)
565 if (!mmc_touched() ||
566 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED
))
569 gui_usb_screen_run();
570 mounted
= true; /* mounting done @ end of USB mode */
572 #ifdef HAVE_USB_POWER
573 if (usb_powered()) /* avoid deadlock */
581 CHART(">disk_mount_all");
582 rc
= disk_mount_all();
583 CHART("<disk_mount_all");
587 lcd_puts(0, 0, "No partition");
588 lcd_puts(0, 1, "found.");
589 #ifdef HAVE_LCD_BITMAP
590 lcd_puts(0, 2, "Insert USB cable");
591 lcd_puts(0, 3, "and fix it.");
595 while(button_get(true) != SYS_USB_CONNECTED
) {};
596 gui_usb_screen_run();
601 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
602 (CONFIG_KEYPAD == IRIVER_H10_PAD)
603 #ifdef SETTINGS_RESET
604 /* Reset settings if holding the reset button. (Rec on Archos,
606 if ((button_status() & SETTINGS_RESET
) == SETTINGS_RESET
)
608 /* Reset settings if the hold button is turned on */
612 splash(HZ
*2, str(LANG_RESET_DONE_CLEAR
));
618 CHART(">settings_load(ALL)");
619 settings_load(SETTINGS_ALL
);
620 CHART("<settings_load(ALL)");
623 CHART(">init_dircache(true)");
624 rc
= init_dircache(true);
625 CHART("<init_dircache(true)");
629 remove(TAGCACHE_STATEFILE
);
633 CHART(">settings_apply(true)");
634 settings_apply(true);
635 CHART("<settings_apply(true)");
636 CHART(">init_dircache(false)");
637 init_dircache(false);
638 CHART("<init_dircache(false)");
640 CHART(">init_tagcache");
642 CHART("<init_tagcache");
645 #ifdef HAVE_EEPROM_SETTINGS
646 if (firmware_settings
.initialized
)
648 /* In case we crash. */
649 firmware_settings
.disk_clean
= false;
650 CHART(">eeprom_settings_store");
651 eeprom_settings_store();
652 CHART("<eeprom_settings_store");
659 #if CONFIG_CODEC == SWCODEC
661 #endif /* CONFIG_CODEC == SWCODEC */
664 #if CONFIG_CODEC != SWCODEC
665 /* No buffer allocation (see buffer.c) may take place after the call to
666 audio_init() since the mpeg thread takes the rest of the buffer space */
667 mp3_init( global_settings
.volume
,
668 global_settings
.bass
,
669 global_settings
.treble
,
670 global_settings
.balance
,
671 global_settings
.loudness
,
673 global_settings
.channel_config
,
674 global_settings
.stereo_width
,
675 global_settings
.mdb_strength
,
676 global_settings
.mdb_harmonics
,
677 global_settings
.mdb_center
,
678 global_settings
.mdb_shape
,
679 global_settings
.mdb_enable
,
680 global_settings
.superbass
);
682 /* audio_init must to know the size of voice buffer so init voice first */
684 #endif /* CONFIG_CODEC != SWCODEC */
686 CHART(">audio_init");
688 CHART("<audio_init");
690 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
694 /* runtime database has to be initialized after audio_init() */
698 car_adapter_mode_init();
700 #ifdef IPOD_ACCESSORY_PROTOCOL
701 iap_setup(global_settings
.serial_bitrate
);
703 #ifdef HAVE_ACCESSORY_SUPPLY
704 accessory_supply_set(global_settings
.accessory_supply
);
706 #ifdef HAVE_LINEOUT_POWEROFF
707 lineout_set(global_settings
.lineout_active
);
709 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
710 CHART("<check_bootfile(false)");
711 check_bootfile(false); /* remember write time and filesize */
712 CHART(">check_bootfile(false)");
714 CHART("<settings_apply_skins");
715 settings_apply_skins();
716 CHART(">settings_apply_skins");
720 void cop_main(void) MAIN_NORETURN_ATTR
;
723 /* This is the entry point for the coprocessor
724 Anyone not running an upgraded bootloader will never reach this point,
725 so it should not be assumed that the coprocessor be usable even on
726 platforms which support it.
728 A kernel thread is initially setup on the coprocessor and immediately
729 destroyed for purposes of continuity. The cop sits idle until at least
730 one thread exists on it. */
735 /* This should never be reached */
743 #endif /* SIMULATOR */