FS#6948 - Fix the broken 'follow playlist' feature
[Rockbox.git] / apps / main.c
blob27698e35e037abc9d952589fa2748567f2262e61
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"
74 #if (CONFIG_CODEC == SWCODEC)
75 #include "playback.h"
76 #include "pcmbuf.h"
77 #else
78 #define pcmbuf_init()
79 #endif
80 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
81 #include "pcm_record.h"
82 #endif
84 #ifdef BUTTON_REC
85 #define SETTINGS_RESET BUTTON_REC
86 #endif
88 #if CONFIG_TUNER
89 #include "radio.h"
90 #endif
91 #ifdef HAVE_MMC
92 #include "ata_mmc.h"
93 #endif
95 #ifdef HAVE_REMOTE_LCD
96 #include "lcd-remote.h"
97 #endif
99 #if CONFIG_USBOTG == USBOTG_ISP1362
100 #include "isp1362.h"
101 #endif
103 #if CONFIG_USBOTG == USBOTG_M5636
104 #include "m5636.h"
105 #endif
107 #include "cuesheet.h"
109 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
111 const char appsversion[]=APPSVERSION;
113 static void init(void);
115 #ifdef SIMULATOR
116 void app_main(void)
117 #else
118 static void app_main(void)
119 #endif
121 init();
122 browse_root();
125 static int init_dircache(bool preinit)
127 #ifdef HAVE_DIRCACHE
128 int result = 0;
129 bool clear = false;
131 if (preinit)
132 dircache_init();
134 if (!global_settings.dircache)
135 return 0;
137 # ifdef HAVE_EEPROM_SETTINGS
138 if (firmware_settings.initialized && firmware_settings.disk_clean
139 && preinit)
141 result = dircache_load();
143 if (result < 0)
145 firmware_settings.disk_clean = false;
146 if (global_status.dircache_size <= 0)
148 /* This will be in default language, settings are not
149 applied yet. Not really any easy way to fix that. */
150 gui_syncsplash(0, str(LANG_DIRCACHE_BUILDING));
151 clear = true;
154 dircache_build(global_status.dircache_size);
157 else
158 # endif
160 if (preinit)
161 return -1;
163 if (!dircache_is_enabled()
164 && !dircache_is_initializing())
166 if (global_status.dircache_size <= 0)
168 gui_syncsplash(0, str(LANG_DIRCACHE_BUILDING));
169 clear = true;
171 result = dircache_build(global_status.dircache_size);
174 if (result < 0)
175 gui_syncsplash(0, "Failed! Result: %d", result);
178 if (clear)
180 backlight_on();
181 show_logo();
182 global_status.dircache_size = dircache_get_cache_size();
183 status_save();
186 return result;
187 #else
188 (void)preinit;
189 return 0;
190 #endif
193 #ifdef HAVE_TAGCACHE
194 static void init_tagcache(void)
196 bool clear = false;
198 tagcache_init();
200 while (!tagcache_is_initialized())
202 #ifdef HAVE_LCD_CHARCELLS
203 char buf[32];
204 #endif
205 int ret = tagcache_get_commit_step();
207 if (ret > 0)
209 #ifdef HAVE_LCD_BITMAP
210 gui_syncsplash(0, "%s [%d/%d]",
211 str(LANG_TAGCACHE_INIT), ret,
212 tagcache_get_max_commit_step());
213 #else
214 lcd_double_height(false);
215 snprintf(buf, sizeof(buf), " TC [%d/%d]", ret,
216 tagcache_get_max_commit_step());
217 lcd_puts(0, 1, buf);
218 #endif
219 clear = true;
221 sleep(HZ/4);
223 tagtree_init();
225 if (clear)
227 backlight_on();
228 show_logo();
231 #endif
233 #ifdef SIMULATOR
235 static void init(void)
237 init_threads();
238 buffer_init();
239 lcd_init();
240 #ifdef HAVE_REMOTE_LCD
241 lcd_remote_init();
242 #endif
243 font_init();
244 show_logo();
245 button_init();
246 backlight_init();
247 lang_init();
248 /* Must be done before any code uses the multi-screen APi */
249 screen_access_init();
250 gui_syncstatusbar_init(&statusbars);
251 settings_reset();
252 settings_load(SETTINGS_ALL);
253 gui_sync_wps_init();
254 settings_apply();
255 init_dircache(true);
256 init_dircache(false);
257 #ifdef HAVE_TAGCACHE
258 init_tagcache();
259 #endif
260 sleep(HZ/2);
261 tree_init();
262 filetype_init();
263 playlist_init();
265 #if CONFIG_CODEC != SWCODEC
266 mp3_init( global_settings.volume,
267 global_settings.bass,
268 global_settings.treble,
269 global_settings.balance,
270 global_settings.loudness,
271 global_settings.avc,
272 global_settings.channel_config,
273 global_settings.stereo_width,
274 global_settings.mdb_strength,
275 global_settings.mdb_harmonics,
276 global_settings.mdb_center,
277 global_settings.mdb_shape,
278 global_settings.mdb_enable,
279 global_settings.superbass);
281 /* audio_init must to know the size of voice buffer so init voice first */
282 talk_init();
283 #endif /* CONFIG_CODEC != SWCODEC */
285 scrobbler_init();
286 cuesheet_init();
288 audio_init();
289 button_clear_queue(); /* Empty the keyboard buffer */
292 #else
294 static void init(void)
296 int rc;
297 bool mounted = false;
298 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
299 /* if nobody initialized ATA before, I consider this a cold start */
300 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
301 #endif
302 #ifdef CPU_PP
303 COP_CTL = PROC_WAKE;
304 #endif
305 system_init();
306 kernel_init();
308 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
309 set_cpu_frequency(CPUFREQ_NORMAL);
310 #ifdef CPU_COLDFIRE
311 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
312 #endif
313 cpu_boost(true);
314 #endif
316 buffer_init();
318 settings_reset();
320 power_init();
322 set_irq_level(0);
323 lcd_init();
324 #ifdef HAVE_REMOTE_LCD
325 lcd_remote_init();
326 #endif
327 font_init();
329 #if !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR)
330 show_logo();
331 #else
332 sleep(1); /* Weird. We crash w/o this tiny delay. */
333 #endif
334 lang_init();
336 #ifdef DEBUG
337 debug_init();
338 #else
339 #if !defined(HAVE_FMADC) && !defined(HAVE_MMC)
340 serial_setup();
341 #endif
342 #endif
344 i2c_init();
346 #if CONFIG_RTC
347 rtc_init();
348 #endif
349 #ifdef HAVE_RTC_RAM
350 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
351 #endif
353 adc_init();
355 usb_init();
356 #if CONFIG_USBOTG == USBOTG_ISP1362
357 isp1362_init();
358 #elif CONFIG_USBOTG == USBOTG_M5636
359 m5636_init();
360 #endif
362 backlight_init();
364 button_init();
366 powermgmt_init();
368 #if CONFIG_TUNER
369 radio_init();
370 #endif
372 /* Must be done before any code uses the multi-screen APi */
373 screen_access_init();
374 gui_syncstatusbar_init(&statusbars);
376 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
377 if (coldstart && charger_inserted()
378 && !global_settings.car_adapter_mode
379 #ifdef ATA_POWER_PLAYERSTYLE
380 && !ide_powered() /* relies on probing result from bootloader */
381 #endif
384 rc = charging_screen(); /* display a "charging" screen */
385 if (rc == 1) /* charger removed */
386 power_off();
387 /* "On" pressed or USB connected: proceed */
388 show_logo(); /* again, to provide better visual feedback */
390 #endif
392 ata_idle_notify_init();
393 rc = ata_init();
394 if(rc)
396 #ifdef HAVE_LCD_BITMAP
397 char str[32];
398 lcd_clear_display();
399 snprintf(str, 31, "ATA error: %d", rc);
400 lcd_puts(0, 1, str);
401 lcd_puts(0, 3, "Press ON to debug");
402 lcd_update();
403 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
404 dbg_ports();
405 #endif
406 panicf("ata: %d", rc);
409 #ifdef HAVE_EEPROM_SETTINGS
410 eeprom_settings_init();
411 #endif
413 usb_start_monitoring();
414 while (usb_detect())
416 #ifdef HAVE_EEPROM_SETTINGS
417 firmware_settings.disk_clean = false;
418 #endif
419 /* enter USB mode early, before trying to mount */
420 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
421 #ifdef HAVE_MMC
422 if (!mmc_touched() || (mmc_remove_request() == SYS_MMC_EXTRACTED))
423 #endif
425 usb_screen();
426 mounted = true; /* mounting done @ end of USB mode */
428 #ifdef HAVE_USB_POWER
429 if (usb_powered()) /* avoid deadlock */
430 break;
431 #endif
434 if (!mounted)
436 rc = disk_mount_all();
437 if (rc<=0)
439 lcd_clear_display();
440 lcd_puts(0, 0, "No partition");
441 lcd_puts(0, 1, "found.");
442 #ifdef HAVE_LCD_BITMAP
443 lcd_puts(0, 2, "Insert USB cable");
444 lcd_puts(0, 3, "and fix it.");
445 lcd_update();
446 #endif
447 while(button_get(true) != SYS_USB_CONNECTED) {};
448 usb_screen();
449 system_reboot();
453 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
454 (CONFIG_KEYPAD == IRIVER_H10_PAD) || (CONFIG_KEYPAD == GIGABEAT_PAD)
455 #ifdef SETTINGS_RESET
456 /* Reset settings if holding the rec button. */
457 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
458 #else
459 /* Reset settings if the hold button is turned on */
460 if (button_hold())
461 #endif
463 gui_syncsplash(HZ*2, str(LANG_RESET_DONE_CLEAR));
464 settings_reset();
466 else
467 #endif
468 settings_load(SETTINGS_ALL);
470 if (init_dircache(true) < 0)
472 #ifdef HAVE_TAGCACHE
473 remove(TAGCACHE_STATEFILE);
474 #endif
477 gui_sync_wps_init();
478 settings_apply();
479 init_dircache(false);
480 #ifdef HAVE_TAGCACHE
481 init_tagcache();
482 #endif
484 #ifdef HAVE_EEPROM_SETTINGS
485 if (firmware_settings.initialized)
487 /* In case we crash. */
488 firmware_settings.disk_clean = false;
489 eeprom_settings_store();
491 #endif
492 status_init();
493 playlist_init();
494 tree_init();
495 filetype_init();
496 scrobbler_init();
497 cuesheet_init();
499 #if CONFIG_CODEC != SWCODEC
500 /* No buffer allocation (see buffer.c) may take place after the call to
501 audio_init() since the mpeg thread takes the rest of the buffer space */
502 mp3_init( global_settings.volume,
503 global_settings.bass,
504 global_settings.treble,
505 global_settings.balance,
506 global_settings.loudness,
507 global_settings.avc,
508 global_settings.channel_config,
509 global_settings.stereo_width,
510 global_settings.mdb_strength,
511 global_settings.mdb_harmonics,
512 global_settings.mdb_center,
513 global_settings.mdb_shape,
514 global_settings.mdb_enable,
515 global_settings.superbass);
517 /* audio_init must to know the size of voice buffer so init voice first */
518 talk_init();
519 #endif /* CONFIG_CODEC != SWCODEC */
521 audio_init();
523 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
524 pcm_rec_init();
525 #endif
527 /* runtime database has to be initialized after audio_init() */
528 cpu_boost(false);
530 #ifdef AUTOROCK
532 int fd;
533 static const char filename[] = PLUGIN_DIR "/autostart.rock";
535 fd = open(filename, O_RDONLY);
536 if(fd >= 0) /* no complaint if it doesn't exist */
538 close(fd);
539 plugin_load((char*)filename, NULL); /* start if it does */
542 #endif /* #ifdef AUTOROCK */
544 #if CONFIG_CHARGING
545 car_adapter_mode_init();
546 #endif
549 #ifdef CPU_PP
550 void cop_main(void)
552 /* This is the entry point for the coprocessor
553 Anyone not running an upgraded bootloader will never reach this point,
554 so it should not be assumed that the coprocessor be usable even on
555 platforms which support it.
557 A kernel thread runs on the coprocessor which waits for other threads to be
558 added, and gracefully handles RoLo */
560 #if CONFIG_CPU == PP5002
561 /* 3G doesn't have Rolo or dual core support yet */
562 while(1) {
563 COP_CTL = PROC_SLEEP;
565 #else
566 extern volatile unsigned char cpu_message;
568 system_init();
569 kernel_init();
571 while(cpu_message != COP_REBOOT) {
572 sleep(HZ);
574 rolo_restart_cop();
575 #endif /* PP5002 */
577 #endif /* CPU_PP */
579 int main(void)
581 app_main();
583 while(1) {
584 #if (CONFIG_LED == LED_REAL)
585 led(true); sleep(HZ/10);
586 led(false); sleep(HZ/10);
587 #endif
589 return 0;
591 #endif