add portable installation if built as static binary.
[Rockbox.git] / apps / main.c
blobdf250843e51d965ad53c6ac5c9ec64ff3a313b4c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "config.h"
21 #include "ata.h"
22 #include "ata_idle_notify.h"
23 #include "disk.h"
24 #include "fat.h"
25 #include "lcd.h"
26 #include "rtc.h"
27 #include "debug.h"
28 #include "led.h"
29 #include "kernel.h"
30 #include "button.h"
31 #include "tree.h"
32 #include "filetypes.h"
33 #include "panic.h"
34 #include "menu.h"
35 #include "system.h"
36 #include "usb.h"
37 #include "powermgmt.h"
38 #include "adc.h"
39 #include "i2c.h"
40 #ifndef DEBUG
41 #include "serial.h"
42 #endif
43 #include "audio.h"
44 #include "mp3_playback.h"
45 #include "thread.h"
46 #include "settings.h"
47 #include "backlight.h"
48 #include "status.h"
49 #include "debug_menu.h"
50 #include "version.h"
51 #include "sprintf.h"
52 #include "font.h"
53 #include "language.h"
54 #include "gwps.h"
55 #include "playlist.h"
56 #include "buffer.h"
57 #include "rolo.h"
58 #include "screens.h"
59 #include "power.h"
60 #include "talk.h"
61 #include "plugin.h"
62 #include "misc.h"
63 #include "dircache.h"
64 #ifdef HAVE_TAGCACHE
65 #include "tagcache.h"
66 #include "tagtree.h"
67 #endif
68 #include "lang.h"
69 #include "string.h"
70 #include "splash.h"
71 #include "eeprom_settings.h"
72 #include "scrobbler.h"
73 #include "icon.h"
75 #if (CONFIG_CODEC == SWCODEC)
76 #include "playback.h"
77 #include "pcmbuf.h"
78 #else
79 #define pcmbuf_init()
80 #endif
81 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
82 #include "pcm_record.h"
83 #endif
85 #ifdef BUTTON_REC
86 #define SETTINGS_RESET BUTTON_REC
87 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
88 #define SETTINGS_RESET BUTTON_A
89 #endif
91 #if CONFIG_TUNER
92 #include "radio.h"
93 #endif
94 #ifdef HAVE_MMC
95 #include "ata_mmc.h"
96 #endif
98 #ifdef HAVE_REMOTE_LCD
99 #include "lcd-remote.h"
100 #endif
102 #if CONFIG_USBOTG == USBOTG_ISP1362
103 #include "isp1362.h"
104 #endif
106 #if CONFIG_USBOTG == USBOTG_M5636
107 #include "m5636.h"
108 #endif
110 #include "cuesheet.h"
112 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
114 const char appsversion[]=APPSVERSION;
116 static void init(void);
118 #ifdef SIMULATOR
119 void app_main(void)
120 #else
121 static void app_main(void)
122 #endif
124 init();
125 tree_gui_init();
126 root_menu();
129 static int init_dircache(bool preinit)
131 #ifdef HAVE_DIRCACHE
132 int result = 0;
133 bool clear = false;
135 if (preinit)
136 dircache_init();
138 if (!global_settings.dircache)
139 return 0;
141 # ifdef HAVE_EEPROM_SETTINGS
142 if (firmware_settings.initialized && firmware_settings.disk_clean
143 && preinit)
145 result = dircache_load();
147 if (result < 0)
149 firmware_settings.disk_clean = false;
150 if (global_status.dircache_size <= 0)
152 /* This will be in default language, settings are not
153 applied yet. Not really any easy way to fix that. */
154 gui_syncsplash(0, str(LANG_SCANNING_DISK));
155 clear = true;
158 dircache_build(global_status.dircache_size);
161 else
162 # endif
164 if (preinit)
165 return -1;
167 if (!dircache_is_enabled()
168 && !dircache_is_initializing())
170 if (global_status.dircache_size <= 0)
172 gui_syncsplash(0, str(LANG_SCANNING_DISK));
173 clear = true;
175 result = dircache_build(global_status.dircache_size);
178 if (result < 0)
180 /* Initialization of dircache failed. Manual action is
181 * necessary to enable dircache again.
183 gui_syncsplash(0, "Dircache failed, disabled. Result: %d", result);
184 global_settings.dircache = false;
189 if (clear)
191 backlight_on();
192 show_logo();
193 global_status.dircache_size = dircache_get_cache_size();
194 status_save();
197 return result;
198 #else
199 (void)preinit;
200 return 0;
201 #endif
204 #ifdef HAVE_TAGCACHE
205 static void init_tagcache(void)
207 bool clear = false;
209 tagcache_init();
211 while (!tagcache_is_initialized())
213 #ifdef HAVE_LCD_CHARCELLS
214 char buf[32];
215 #endif
216 int ret = tagcache_get_commit_step();
218 if (ret > 0)
220 static long talked_tick = 0;
221 if(talk_menus_enabled()
222 && (talked_tick == 0
223 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
225 talked_tick = current_tick;
226 talk_id(LANG_TAGCACHE_INIT, false);
227 talk_number(ret, true);
228 talk_id(VOICE_OF, true);
229 talk_number(tagcache_get_max_commit_step(), true);
231 #ifdef HAVE_LCD_BITMAP
232 gui_syncsplash(0, "%s [%d/%d]",
233 str(LANG_TAGCACHE_INIT), ret,
234 tagcache_get_max_commit_step());
235 #else
236 lcd_double_height(false);
237 snprintf(buf, sizeof(buf), " DB [%d/%d]", ret,
238 tagcache_get_max_commit_step());
239 lcd_puts(0, 1, buf);
240 lcd_update();
241 #endif
242 clear = true;
244 sleep(HZ/4);
246 tagtree_init();
248 if (clear)
250 backlight_on();
251 show_logo();
254 #endif
256 #ifdef SIMULATOR
258 static void init(void)
260 init_threads();
261 buffer_init();
262 lcd_init();
263 #ifdef HAVE_REMOTE_LCD
264 lcd_remote_init();
265 #endif
266 font_init();
267 show_logo();
268 button_init();
269 backlight_init();
270 lang_init();
271 #ifdef DEBUG
272 debug_init();
273 #endif
274 /* Must be done before any code uses the multi-screen APi */
275 screen_access_init();
276 gui_syncstatusbar_init(&statusbars);
277 settings_reset();
278 settings_load(SETTINGS_ALL);
279 gui_sync_wps_init();
280 settings_apply();
281 init_dircache(true);
282 init_dircache(false);
283 #ifdef HAVE_TAGCACHE
284 init_tagcache();
285 #endif
286 sleep(HZ/2);
287 tree_mem_init();
288 filetype_init();
289 playlist_init();
291 #if CONFIG_CODEC != SWCODEC
292 mp3_init( global_settings.volume,
293 global_settings.bass,
294 global_settings.treble,
295 global_settings.balance,
296 global_settings.loudness,
297 global_settings.avc,
298 global_settings.channel_config,
299 global_settings.stereo_width,
300 global_settings.mdb_strength,
301 global_settings.mdb_harmonics,
302 global_settings.mdb_center,
303 global_settings.mdb_shape,
304 global_settings.mdb_enable,
305 global_settings.superbass);
307 /* audio_init must to know the size of voice buffer so init voice first */
308 talk_init();
309 #endif /* CONFIG_CODEC != SWCODEC */
311 scrobbler_init();
312 cuesheet_init();
314 audio_init();
315 button_clear_queue(); /* Empty the keyboard buffer */
318 #else
320 static void init(void)
322 int rc;
323 bool mounted = false;
324 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
325 /* if nobody initialized ATA before, I consider this a cold start */
326 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
327 #endif
328 #ifdef CPU_PP
329 COP_CTL = PROC_WAKE;
330 #endif
331 system_init();
332 kernel_init();
334 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
335 set_cpu_frequency(CPUFREQ_NORMAL);
336 #ifdef CPU_COLDFIRE
337 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
338 #endif
339 cpu_boost(true);
340 #endif
342 buffer_init();
344 settings_reset();
346 power_init();
348 set_irq_level(0);
349 lcd_init();
350 #ifdef HAVE_REMOTE_LCD
351 lcd_remote_init();
352 #endif
353 font_init();
355 show_logo();
356 lang_init();
358 #ifdef DEBUG
359 debug_init();
360 #else
361 #if !defined(HAVE_FMADC) && !defined(HAVE_MMC)
362 serial_setup();
363 #endif
364 #endif
366 i2c_init();
368 #if CONFIG_RTC
369 rtc_init();
370 #endif
371 #ifdef HAVE_RTC_RAM
372 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
373 #endif
375 adc_init();
377 usb_init();
378 #if CONFIG_USBOTG == USBOTG_ISP1362
379 isp1362_init();
380 #elif CONFIG_USBOTG == USBOTG_M5636
381 m5636_init();
382 #endif
384 backlight_init();
386 button_init();
388 powermgmt_init();
390 #if CONFIG_TUNER
391 radio_init();
392 #endif
394 /* Must be done before any code uses the multi-screen APi */
395 screen_access_init();
396 gui_syncstatusbar_init(&statusbars);
398 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
399 if (coldstart && charger_inserted()
400 && !global_settings.car_adapter_mode
401 #ifdef ATA_POWER_PLAYERSTYLE
402 && !ide_powered() /* relies on probing result from bootloader */
403 #endif
406 rc = charging_screen(); /* display a "charging" screen */
407 if (rc == 1) /* charger removed */
408 power_off();
409 /* "On" pressed or USB connected: proceed */
410 show_logo(); /* again, to provide better visual feedback */
412 #endif
414 ata_idle_notify_init();
415 rc = ata_init();
416 if(rc)
418 #ifdef HAVE_LCD_BITMAP
419 char str[32];
420 lcd_clear_display();
421 snprintf(str, 31, "ATA error: %d", rc);
422 lcd_puts(0, 1, str);
423 lcd_puts(0, 3, "Press ON to debug");
424 lcd_update();
425 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
426 dbg_ports();
427 #endif
428 panicf("ata: %d", rc);
431 #ifdef HAVE_EEPROM_SETTINGS
432 eeprom_settings_init();
433 #endif
435 usb_start_monitoring();
436 while (usb_detect())
438 #ifdef HAVE_EEPROM_SETTINGS
439 firmware_settings.disk_clean = false;
440 #endif
441 /* enter USB mode early, before trying to mount */
442 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
443 #ifdef HAVE_MMC
444 if (!mmc_touched() ||
445 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
446 #endif
448 usb_screen();
449 mounted = true; /* mounting done @ end of USB mode */
451 #ifdef HAVE_USB_POWER
452 if (usb_powered()) /* avoid deadlock */
453 break;
454 #endif
457 if (!mounted)
459 rc = disk_mount_all();
460 if (rc<=0)
462 lcd_clear_display();
463 lcd_puts(0, 0, "No partition");
464 lcd_puts(0, 1, "found.");
465 #ifdef HAVE_LCD_BITMAP
466 lcd_puts(0, 2, "Insert USB cable");
467 lcd_puts(0, 3, "and fix it.");
468 #endif
469 lcd_update();
471 while(button_get(true) != SYS_USB_CONNECTED) {};
472 usb_screen();
473 system_reboot();
477 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
478 (CONFIG_KEYPAD == IRIVER_H10_PAD)
479 #ifdef SETTINGS_RESET
480 /* Reset settings if holding the reset button. (Rec on Archos,
481 A on Gigabeat) */
482 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
483 #else
484 /* Reset settings if the hold button is turned on */
485 if (button_hold())
486 #endif
488 gui_syncsplash(HZ*2, str(LANG_RESET_DONE_CLEAR));
489 settings_reset();
491 else
492 #endif
493 settings_load(SETTINGS_ALL);
495 if (init_dircache(true) < 0)
497 #ifdef HAVE_TAGCACHE
498 remove(TAGCACHE_STATEFILE);
499 #endif
502 gui_sync_wps_init();
503 settings_apply();
504 init_dircache(false);
505 #ifdef HAVE_TAGCACHE
506 init_tagcache();
507 #endif
509 #ifdef HAVE_EEPROM_SETTINGS
510 if (firmware_settings.initialized)
512 /* In case we crash. */
513 firmware_settings.disk_clean = false;
514 eeprom_settings_store();
516 #endif
517 status_init();
518 playlist_init();
519 tree_mem_init();
520 filetype_init();
521 scrobbler_init();
522 cuesheet_init();
524 #if CONFIG_CODEC != SWCODEC
525 /* No buffer allocation (see buffer.c) may take place after the call to
526 audio_init() since the mpeg thread takes the rest of the buffer space */
527 mp3_init( global_settings.volume,
528 global_settings.bass,
529 global_settings.treble,
530 global_settings.balance,
531 global_settings.loudness,
532 global_settings.avc,
533 global_settings.channel_config,
534 global_settings.stereo_width,
535 global_settings.mdb_strength,
536 global_settings.mdb_harmonics,
537 global_settings.mdb_center,
538 global_settings.mdb_shape,
539 global_settings.mdb_enable,
540 global_settings.superbass);
542 /* audio_init must to know the size of voice buffer so init voice first */
543 talk_init();
544 #endif /* CONFIG_CODEC != SWCODEC */
546 audio_init();
548 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
549 pcm_rec_init();
550 #endif
552 /* runtime database has to be initialized after audio_init() */
553 cpu_boost(false);
555 #ifdef AUTOROCK
557 int fd;
558 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
560 fd = open(filename, O_RDONLY);
561 if(fd >= 0) /* no complaint if it doesn't exist */
563 close(fd);
564 plugin_load((char*)filename, NULL); /* start if it does */
567 #endif /* #ifdef AUTOROCK */
569 #if CONFIG_CHARGING
570 car_adapter_mode_init();
571 #endif
574 #ifdef CPU_PP
575 void cop_main(void)
577 /* This is the entry point for the coprocessor
578 Anyone not running an upgraded bootloader will never reach this point,
579 so it should not be assumed that the coprocessor be usable even on
580 platforms which support it.
582 A kernel thread runs on the coprocessor which waits for other threads to be
583 added, and gracefully handles RoLo */
585 #if CONFIG_CPU == PP5002
586 /* 3G doesn't have Rolo or dual core support yet */
587 while(1) {
588 COP_CTL = PROC_SLEEP;
590 #else
591 extern volatile unsigned char cpu_message;
593 system_init();
594 kernel_init();
596 while(cpu_message != COP_REBOOT) {
597 sleep(HZ);
599 rolo_restart_cop();
600 #endif /* PP5002 */
602 #endif /* CPU_PP */
604 int main(void)
606 app_main();
608 while(1) {
609 #if (CONFIG_LED == LED_REAL)
610 led(true); sleep(HZ/10);
611 led(false); sleep(HZ/10);
612 #endif
614 return 0;
616 #endif