Merge duplicating code to move cursor left/right.
[kugel-rb.git] / apps / main.c
blob1eed068f148c8262db43316c022d604f92a72296
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"
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 const char appsversion[]=APPSVERSION;
125 static void init(void);
127 #ifdef SIMULATOR
128 void app_main(void)
129 #else
130 int main(void) __attribute__((noreturn));
131 int main(void)
132 #endif
134 int i;
135 init();
136 FOR_NB_SCREENS(i)
138 screens[i].clear_display();
139 screens[i].update();
141 #ifdef HAVE_LCD_BITMAP
142 list_init();
143 #endif
144 tree_gui_init();
145 viewportmanager_init();
146 #ifdef HAVE_USBSTACK
147 /* All threads should be created and public queues registered by now */
148 usb_start_monitoring();
149 #endif
151 #ifdef AUTOROCK
153 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
155 if(file_exists(filename)) /* no complaint if it doesn't exist */
157 plugin_load((char*)filename, NULL); /* start if it does */
160 #endif /* #ifdef AUTOROCK */
162 global_status.last_volume_change = 0;
163 root_menu();
166 static int init_dircache(bool preinit)
168 #ifdef HAVE_DIRCACHE
169 int result = 0;
170 bool clear = false;
172 if (preinit)
173 dircache_init();
175 if (!global_settings.dircache)
176 return 0;
178 # ifdef HAVE_EEPROM_SETTINGS
179 if (firmware_settings.initialized && firmware_settings.disk_clean
180 && preinit)
182 result = dircache_load();
184 if (result < 0)
186 firmware_settings.disk_clean = false;
187 if (global_status.dircache_size <= 0)
189 /* This will be in default language, settings are not
190 applied yet. Not really any easy way to fix that. */
191 splash(0, str(LANG_SCANNING_DISK));
192 clear = true;
195 dircache_build(global_status.dircache_size);
198 else
199 # endif
201 if (preinit)
202 return -1;
204 if (!dircache_is_enabled()
205 && !dircache_is_initializing())
207 if (global_status.dircache_size <= 0)
209 splash(0, str(LANG_SCANNING_DISK));
210 clear = true;
212 result = dircache_build(global_status.dircache_size);
215 if (result < 0)
217 /* Initialization of dircache failed. Manual action is
218 * necessary to enable dircache again.
220 splashf(0, "Dircache failed, disabled. Result: %d", result);
221 global_settings.dircache = false;
225 if (clear)
227 backlight_on();
228 show_logo();
229 global_status.dircache_size = dircache_get_cache_size();
230 status_save();
233 return result;
234 #else
235 (void)preinit;
236 return 0;
237 #endif
240 #ifdef HAVE_TAGCACHE
241 static void init_tagcache(void)
243 bool clear = false;
244 #if CONFIG_CODEC == SWCODEC
245 long talked_tick = 0;
246 #endif
247 tagcache_init();
249 while (!tagcache_is_initialized())
251 int ret = tagcache_get_commit_step();
253 if (ret > 0)
255 #if CONFIG_CODEC == SWCODEC
256 /* hwcodec can't use voice here, as the database commit
257 * uses the audio buffer. */
258 if(global_settings.talk_menu
259 && (talked_tick == 0
260 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
262 talked_tick = current_tick;
263 talk_id(LANG_TAGCACHE_INIT, false);
264 talk_number(ret, true);
265 talk_id(VOICE_OF, true);
266 talk_number(tagcache_get_max_commit_step(), true);
268 #endif
269 #ifdef HAVE_LCD_BITMAP
270 if (lang_is_rtl())
272 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
273 str(LANG_TAGCACHE_INIT));
275 else
277 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
278 tagcache_get_max_commit_step());
280 #else
281 lcd_double_height(false);
282 lcd_putsf(0, 1, " DB [%d/%d]", ret,
283 tagcache_get_max_commit_step());
284 lcd_update();
285 #endif
286 clear = true;
288 sleep(HZ/4);
290 tagtree_init();
292 if (clear)
294 backlight_on();
295 show_logo();
298 #endif
300 #ifdef SIMULATOR
302 static void init(void)
304 kernel_init();
305 buffer_init();
306 enable_irq();
307 lcd_init();
308 #ifdef HAVE_REMOTE_LCD
309 lcd_remote_init();
310 #endif
311 font_init();
312 show_logo();
313 button_init();
314 backlight_init();
315 sim_tasks_init();
316 lang_init(core_language_builtin, language_strings,
317 LANG_LAST_INDEX_IN_ARRAY);
318 #ifdef DEBUG
319 debug_init();
320 #endif
321 /* Must be done before any code uses the multi-screen API */
322 gui_syncstatusbar_init(&statusbars);
323 storage_init();
324 settings_reset();
325 settings_load(SETTINGS_ALL);
326 gui_sync_wps_init();
327 sb_skin_init();
328 settings_apply(true);
329 init_dircache(true);
330 init_dircache(false);
331 #ifdef HAVE_TAGCACHE
332 init_tagcache();
333 #endif
334 sleep(HZ/2);
335 tree_mem_init();
336 filetype_init();
337 playlist_init();
339 #if CONFIG_CODEC != SWCODEC
340 mp3_init( global_settings.volume,
341 global_settings.bass,
342 global_settings.treble,
343 global_settings.balance,
344 global_settings.loudness,
345 global_settings.avc,
346 global_settings.channel_config,
347 global_settings.stereo_width,
348 global_settings.mdb_strength,
349 global_settings.mdb_harmonics,
350 global_settings.mdb_center,
351 global_settings.mdb_shape,
352 global_settings.mdb_enable,
353 global_settings.superbass);
355 /* audio_init must to know the size of voice buffer so init voice first */
356 talk_init();
357 #endif /* CONFIG_CODEC != SWCODEC */
359 scrobbler_init();
360 #if CONFIG_CODEC == SWCODEC
361 tdspeed_init();
362 #endif /* CONFIG_CODEC == SWCODEC */
364 audio_init();
365 button_clear_queue(); /* Empty the keyboard buffer */
368 #else
370 static void init(void)
372 int rc;
373 bool mounted = false;
374 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
375 /* if nobody initialized ATA before, I consider this a cold start */
376 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
377 #endif
379 system_init();
380 kernel_init();
382 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
383 set_cpu_frequency(CPUFREQ_NORMAL);
384 #ifdef CPU_COLDFIRE
385 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
386 #endif
387 cpu_boost(true);
388 #endif
390 buffer_init();
392 settings_reset();
394 i2c_init();
396 power_init();
398 enable_irq();
399 #ifdef CPU_ARM
400 enable_fiq();
401 #endif
402 lcd_init();
403 #ifdef HAVE_REMOTE_LCD
404 lcd_remote_init();
405 #endif
406 font_init();
408 show_logo();
409 lang_init(core_language_builtin, language_strings,
410 LANG_LAST_INDEX_IN_ARRAY);
412 #ifdef DEBUG
413 debug_init();
414 #else
415 #ifdef HAVE_SERIAL
416 serial_setup();
417 #endif
418 #endif
420 #if CONFIG_RTC
421 rtc_init();
422 #endif
423 #ifdef HAVE_RTC_RAM
424 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
425 #endif
427 adc_init();
429 usb_init();
430 #if CONFIG_USBOTG == USBOTG_ISP1362
431 isp1362_init();
432 #elif CONFIG_USBOTG == USBOTG_M5636
433 m5636_init();
434 #endif
436 backlight_init();
438 button_init();
440 powermgmt_init();
442 #if CONFIG_TUNER
443 radio_init();
444 #endif
446 /* Must be done before any code uses the multi-screen API */
447 gui_syncstatusbar_init(&statusbars);
449 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
450 /* charger_inserted() can't be used here because power_thread()
451 hasn't checked power_input_status() yet */
452 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
453 && !global_settings.car_adapter_mode
454 #ifdef ATA_POWER_PLAYERSTYLE
455 && !ide_powered() /* relies on probing result from bootloader */
456 #endif
459 rc = charging_screen(); /* display a "charging" screen */
460 if (rc == 1) /* charger removed */
461 power_off();
462 /* "On" pressed or USB connected: proceed */
463 show_logo(); /* again, to provide better visual feedback */
465 #endif
467 rc = storage_init();
468 if(rc)
470 #ifdef HAVE_LCD_BITMAP
471 lcd_clear_display();
472 lcd_putsf(0, 1, "ATA error: %d", rc);
473 lcd_puts(0, 3, "Press ON to debug");
474 lcd_update();
475 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
476 dbg_ports();
477 #endif
478 panicf("ata: %d", rc);
481 #ifdef HAVE_EEPROM_SETTINGS
482 eeprom_settings_init();
483 #endif
485 #ifndef HAVE_USBSTACK
486 usb_start_monitoring();
487 while (usb_detect() == USB_INSERTED)
489 #ifdef HAVE_EEPROM_SETTINGS
490 firmware_settings.disk_clean = false;
491 #endif
492 /* enter USB mode early, before trying to mount */
493 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
494 #if (CONFIG_STORAGE & STORAGE_MMC)
495 if (!mmc_touched() ||
496 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
497 #endif
499 gui_usb_screen_run();
500 mounted = true; /* mounting done @ end of USB mode */
502 #ifdef HAVE_USB_POWER
503 if (usb_powered()) /* avoid deadlock */
504 break;
505 #endif
507 #endif
509 if (!mounted)
511 rc = disk_mount_all();
512 if (rc<=0)
514 lcd_clear_display();
515 lcd_puts(0, 0, "No partition");
516 lcd_puts(0, 1, "found.");
517 #ifdef HAVE_LCD_BITMAP
518 lcd_puts(0, 2, "Insert USB cable");
519 lcd_puts(0, 3, "and fix it.");
520 #endif
521 lcd_update();
523 while(button_get(true) != SYS_USB_CONNECTED) {};
524 gui_usb_screen_run();
525 system_reboot();
529 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
530 (CONFIG_KEYPAD == IRIVER_H10_PAD)
531 #ifdef SETTINGS_RESET
532 /* Reset settings if holding the reset button. (Rec on Archos,
533 A on Gigabeat) */
534 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
535 #else
536 /* Reset settings if the hold button is turned on */
537 if (button_hold())
538 #endif
540 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
541 settings_reset();
543 else
544 #endif
545 settings_load(SETTINGS_ALL);
547 if (init_dircache(true) < 0)
549 #ifdef HAVE_TAGCACHE
550 remove(TAGCACHE_STATEFILE);
551 #endif
554 gui_sync_wps_init();
555 sb_skin_init();
556 settings_apply(true);
557 init_dircache(false);
558 #ifdef HAVE_TAGCACHE
559 init_tagcache();
560 #endif
562 #ifdef HAVE_EEPROM_SETTINGS
563 if (firmware_settings.initialized)
565 /* In case we crash. */
566 firmware_settings.disk_clean = false;
567 eeprom_settings_store();
569 #endif
570 playlist_init();
571 tree_mem_init();
572 filetype_init();
573 scrobbler_init();
574 #if CONFIG_CODEC == SWCODEC
575 tdspeed_init();
576 #endif /* CONFIG_CODEC == SWCODEC */
578 #if CONFIG_CODEC != SWCODEC
579 /* No buffer allocation (see buffer.c) may take place after the call to
580 audio_init() since the mpeg thread takes the rest of the buffer space */
581 mp3_init( global_settings.volume,
582 global_settings.bass,
583 global_settings.treble,
584 global_settings.balance,
585 global_settings.loudness,
586 global_settings.avc,
587 global_settings.channel_config,
588 global_settings.stereo_width,
589 global_settings.mdb_strength,
590 global_settings.mdb_harmonics,
591 global_settings.mdb_center,
592 global_settings.mdb_shape,
593 global_settings.mdb_enable,
594 global_settings.superbass);
596 /* audio_init must to know the size of voice buffer so init voice first */
597 talk_init();
598 #endif /* CONFIG_CODEC != SWCODEC */
600 audio_init();
602 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
603 pcm_rec_init();
604 #endif
606 /* runtime database has to be initialized after audio_init() */
607 cpu_boost(false);
609 #if CONFIG_CHARGING
610 car_adapter_mode_init();
611 #endif
612 #ifdef IPOD_ACCESSORY_PROTOCOL
613 iap_setup(global_settings.serial_bitrate);
614 #endif
615 #ifdef HAVE_ACCESSORY_SUPPLY
616 accessory_supply_set(global_settings.accessory_supply);
617 #endif
620 #ifdef CPU_PP
621 void cop_main(void)
623 /* This is the entry point for the coprocessor
624 Anyone not running an upgraded bootloader will never reach this point,
625 so it should not be assumed that the coprocessor be usable even on
626 platforms which support it.
628 A kernel thread is initially setup on the coprocessor and immediately
629 destroyed for purposes of continuity. The cop sits idle until at least
630 one thread exists on it. */
632 /* 3G doesn't have Rolo or dual core support yet */
633 #if NUM_CORES > 1
634 system_init();
635 kernel_init();
636 /* This should never be reached */
637 #endif
638 while(1) {
639 sleep_core(COP);
642 #endif /* CPU_PP */
644 #endif