Fix it dropping back to the file browser.
[Rockbox.git] / apps / root_menu.c
blob8a7daf41744a1dc36a8cab7f04975d420a87bf1c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: main.c 12101 2007-01-24 02:19:22Z jdgordon $
10 * Copyright (C) 2007 Jonathan Gordon
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 <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include "config.h"
24 #include "menu.h"
25 #include "root_menu.h"
26 #include "lang.h"
27 #include "settings.h"
28 #include "kernel.h"
29 #include "debug.h"
30 #include "misc.h"
31 #include "rolo.h"
32 #include "powermgmt.h"
34 #if LCD_DEPTH > 1
35 #include "backdrop.h"
36 #endif
37 #include "talk.h"
38 #include "audio.h"
40 /* gui api */
41 #include "list.h"
42 #include "statusbar.h"
43 #include "splash.h"
44 #include "buttonbar.h"
45 #include "textarea.h"
46 #include "action.h"
47 #include "yesno.h"
49 #include "main_menu.h"
50 #include "tree.h"
51 #if CONFIG_TUNER
52 #include "radio.h"
53 #endif
54 #ifdef HAVE_RECORDING
55 #include "recording.h"
56 #endif
57 #include "gwps-common.h"
58 #include "bookmark.h"
59 #include "tagtree.h"
60 #include "menus/exported_menus.h"
61 #ifdef HAVE_RTC_ALARM
62 #include "rtc.h"
63 #endif
64 #ifdef HAVE_TAGCACHE
65 #include "tagcache.h"
66 #endif
68 struct root_items {
69 int (*function)(void* param);
70 void* param;
72 static int last_screen = GO_TO_ROOT; /* unfortunatly needed so we can resume
73 or goto current track based on previous
74 screen */
75 static int browser(void* param)
77 int ret_val;
78 #ifdef HAVE_TAGCACHE
79 struct tree_context* tc = tree_get_context();
80 #endif
81 int filter = SHOW_SUPPORTED;
82 char folder[MAX_PATH] = "/";
83 /* stuff needed to remember position in file browser */
84 static char last_folder[MAX_PATH] = "/";
85 /* and stuff for the database browser */
86 #ifdef HAVE_TAGCACHE
87 static int last_db_dirlevel = 0, last_db_selection = 0;
88 #endif
90 switch ((intptr_t)param)
92 case GO_TO_FILEBROWSER:
93 filter = global_settings.dirfilter;
94 if (global_settings.browse_current &&
95 last_screen == GO_TO_WPS && audio_status() &&
96 wps_state.current_track_path[0] != '\0')
98 strcpy(folder, wps_state.current_track_path);
100 else
101 strcpy(folder, last_folder);
102 break;
103 #ifdef HAVE_TAGCACHE
104 case GO_TO_DBBROWSER:
105 if (!tagcache_is_usable())
107 bool reinit_attempted = false;
109 /* Now display progress until it's ready or the user exits */
110 while(!tagcache_is_usable())
112 gui_syncstatusbar_draw(&statusbars, false);
113 struct tagcache_stat *stat = tagcache_get_stat();
115 /* Allow user to exit */
116 if (action_userabort(HZ/2))
117 break;
119 /* Maybe just needs to reboot due to delayed commit */
120 if (stat->commit_delayed)
122 gui_syncsplash(HZ*2, str(LANG_PLEASE_REBOOT));
123 break;
126 /* Check if ready status is known */
127 if (!stat->readyvalid)
129 gui_syncsplash(0, str(LANG_TAGCACHE_BUSY));
130 continue;
133 /* Re-init if required */
134 if (!reinit_attempted && !stat->ready &&
135 stat->processed_entries == 0 && stat->commit_step == 0)
137 /* Prompt the user */
138 reinit_attempted = true;
139 char *lines[]={str(LANG_TAGCACHE_BUSY), str(LANG_TAGCACHE_FORCE_UPDATE)};
140 struct text_message message={lines, 2};
141 if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO)
142 break;
143 int i;
144 FOR_NB_SCREENS(i)
145 screens[i].clear_display();
147 /* Start initialisation */
148 tagcache_rebuild();
151 /* Display building progress */
152 if (stat->commit_step > 0)
154 gui_syncsplash(0, "%s [%d/%d]",
155 str(LANG_TAGCACHE_INIT), stat->commit_step,
156 tagcache_get_max_commit_step());
158 else
160 gui_syncsplash(0, str(LANG_BUILDING_DATABASE),
161 stat->processed_entries);
165 if (!tagcache_is_usable())
166 return GO_TO_PREVIOUS;
167 filter = SHOW_ID3DB;
168 tc->dirlevel = last_db_dirlevel;
169 tc->selected_item = last_db_selection;
170 break;
171 #endif
172 case GO_TO_BROWSEPLUGINS:
173 filter = SHOW_PLUGINS;
174 snprintf(folder, MAX_PATH, "%s/", PLUGIN_DIR);
175 break;
177 ret_val = rockbox_browse(folder, filter);
178 switch ((intptr_t)param)
180 case GO_TO_FILEBROWSER:
181 get_current_file(last_folder, MAX_PATH);
182 break;
183 #ifdef HAVE_TAGCACHE
184 case GO_TO_DBBROWSER:
185 last_db_dirlevel = tc->dirlevel;
186 last_db_selection = tc->selected_item;
187 break;
188 #endif
190 /* hopefully only happens trying to go back into the WPS
191 from plugins, if music is stopped... */
192 if ((ret_val == GO_TO_PREVIOUS) && (last_screen == (intptr_t)param))
193 ret_val = GO_TO_ROOT;
195 return ret_val;
198 static int menu(void* param)
200 (void)param;
201 return do_menu(NULL, 0);
204 #ifdef HAVE_RECORDING
205 static int recscrn(void* param)
207 (void)param;
208 recording_screen(false);
209 return GO_TO_ROOT;
211 #endif
212 static int wpsscrn(void* param)
214 int ret_val = GO_TO_PREVIOUS;
215 (void)param;
216 if (audio_status())
218 ret_val = gui_wps_show();
220 else if ( global_status.resume_index != -1 )
222 DEBUGF("Resume index %X offset %lX\n",
223 global_status.resume_index,
224 (unsigned long)global_status.resume_offset);
225 if (playlist_resume() != -1)
227 playlist_start(global_status.resume_index,
228 global_status.resume_offset);
229 ret_val = gui_wps_show();
232 else
234 gui_syncsplash(HZ*2, str(LANG_NOTHING_TO_RESUME));
236 #if LCD_DEPTH > 1
237 show_main_backdrop();
238 #endif
239 return ret_val;
241 #if CONFIG_TUNER
242 static int radio(void* param)
244 (void)param;
245 radio_screen();
246 return GO_TO_ROOT;
248 #endif
250 static int load_bmarks(void* param)
252 (void)param;
253 bookmark_mrb_load();
254 return GO_TO_PREVIOUS;
257 static const struct root_items items[] = {
258 [GO_TO_FILEBROWSER] = { browser, (void*)GO_TO_FILEBROWSER },
259 [GO_TO_DBBROWSER] = { browser, (void*)GO_TO_DBBROWSER },
260 [GO_TO_WPS] = { wpsscrn, NULL },
261 [GO_TO_MAINMENU] = { menu, NULL },
263 #ifdef HAVE_RECORDING
264 [GO_TO_RECSCREEN] = { recscrn, NULL },
265 #endif
267 #if CONFIG_TUNER
268 [GO_TO_FM] = { radio, NULL },
269 #endif
271 [GO_TO_RECENTBMARKS] = { load_bmarks, NULL },
272 [GO_TO_BROWSEPLUGINS] = { browser, (void*)GO_TO_BROWSEPLUGINS },
275 static const int nb_items = sizeof(items)/sizeof(*items);
277 #ifdef BOOTFILE
278 extern bool boot_changed; /* from tree.c */
279 static void check_boot(void)
281 if (boot_changed) {
282 char *lines[]={str(LANG_BOOT_CHANGED), str(LANG_REBOOT_NOW)};
283 struct text_message message={lines, 2};
284 if(gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES)
285 rolo_load("/" BOOTFILE);
286 boot_changed = false;
289 #else
290 # define check_boot()
291 #endif
292 int item_callback(int action, const struct menu_item_ex *this_item) ;
294 MENUITEM_RETURNVALUE(file_browser, ID2P(LANG_DIR_BROWSER), GO_TO_FILEBROWSER,
295 NULL, Icon_file_view_menu);
296 #ifdef HAVE_TAGCACHE
297 MENUITEM_RETURNVALUE(db_browser, ID2P(LANG_TAGCACHE), GO_TO_DBBROWSER,
298 NULL, Icon_Audio);
299 #endif
300 MENUITEM_RETURNVALUE(rocks_browser, ID2P(LANG_PLUGINS), GO_TO_BROWSEPLUGINS,
301 NULL, Icon_Plugin);
302 char *get_wps_item_name(int selected_item, void * data, char *buffer)
304 (void)selected_item; (void)data; (void)buffer;
305 if (audio_status())
306 return ID2P(LANG_NOW_PLAYING);
307 return ID2P(LANG_RESUME_PLAYBACK);
309 MENUITEM_RETURNVALUE_DYNTEXT(wps_item, GO_TO_WPS, NULL, get_wps_item_name,
310 NULL, Icon_Playback_menu);
311 #ifdef HAVE_RECORDING
312 MENUITEM_RETURNVALUE(rec, ID2P(LANG_RECORDING_MENU), GO_TO_RECSCREEN,
313 NULL, Icon_Recording);
314 #endif
315 #if CONFIG_TUNER
316 MENUITEM_RETURNVALUE(fm, ID2P(LANG_FM_RADIO), GO_TO_FM,
317 item_callback, Icon_Radio_screen);
318 #endif
319 MENUITEM_RETURNVALUE(menu_, ID2P(LANG_SETTINGS_MENU), GO_TO_MAINMENU,
320 NULL, Icon_Submenu_Entered);
321 MENUITEM_RETURNVALUE(bookmarks, ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS),
322 GO_TO_RECENTBMARKS, item_callback,
323 Icon_Bookmark);
324 #ifdef HAVE_LCD_CHARCELLS
325 static int do_shutdown(void)
327 sys_poweroff();
328 return 0;
330 MENUITEM_FUNCTION(do_shutdown_item, 0, ID2P(LANG_SHUTDOWN),
331 do_shutdown, NULL, 0, NULL, Icon_NOICON);
332 #endif
333 MAKE_MENU(root_menu_, ID2P(LANG_ROCKBOX_TITLE),
334 NULL, Icon_Rockbox,
335 &bookmarks, &file_browser,
336 #ifdef HAVE_TAGCACHE
337 &db_browser,
338 #endif
339 &wps_item, &menu_,
340 #ifdef HAVE_RECORDING
341 &rec,
342 #endif
343 #if CONFIG_TUNER
344 &fm,
345 #endif
346 &playlist_options, &rocks_browser, &info_menu
348 #ifdef HAVE_LCD_CHARCELLS
349 ,&do_shutdown_item
350 #endif
353 int item_callback(int action, const struct menu_item_ex *this_item)
355 switch (action)
357 case ACTION_REQUEST_MENUITEM:
358 #if CONFIG_TUNER
359 if (this_item == &fm)
361 if (radio_hardware_present() == 0)
362 return ACTION_EXIT_MENUITEM;
364 else
365 #endif
366 if (this_item == &bookmarks)
368 if (global_settings.usemrb == 0)
369 return ACTION_EXIT_MENUITEM;
371 break;
373 return action;
375 static int get_selection(int last_screen)
377 unsigned int i;
378 for(i=0; i< sizeof(root_menu__)/sizeof(*root_menu__); i++)
380 if ((root_menu__[i]->flags&MT_RETURN_VALUE) &&
381 (root_menu__[i]->value == last_screen))
383 return i;
386 return 0;
389 void root_menu(void)
391 int previous_browser = GO_TO_FILEBROWSER;
392 int previous_music = GO_TO_WPS;
393 int ret_val = GO_TO_ROOT;
394 int this_screen = GO_TO_ROOT;
395 int selected = 0;
397 if (global_settings.start_in_screen == 0)
398 ret_val = (int)global_status.last_screen;
399 else ret_val = global_settings.start_in_screen - 2;
401 #ifdef HAVE_RTC_ALARM
402 if ( rtc_check_alarm_started(true) )
404 rtc_enable_alarm(false);
405 ret_val = GO_TO_WPS;
406 #if CONFIG_TUNER
407 if (global_settings.alarm_wake_up_screen == ALARM_START_FM)
408 ret_val = GO_TO_FM;
409 #endif
410 #ifdef HAVE_RECORDING
411 if (global_settings.alarm_wake_up_screen == ALARM_START_REC)
413 recording_start_automatic = true;
414 ret_val = GO_TO_RECSCREEN;
416 #endif
418 #endif /* HAVE_RTC_ALARM */
420 #ifdef HAVE_HEADPHONE_DETECTION
421 if (ret_val == GO_TO_WPS &&
422 (global_settings.unplug_autoresume && !headphones_inserted() ))
423 ret_val = GO_TO_ROOT;
424 #endif
426 while (true)
428 switch (ret_val)
430 case GO_TO_ROOT:
431 if (last_screen != GO_TO_ROOT)
432 selected = get_selection(last_screen);
433 ret_val = do_menu(&root_menu_, &selected);
434 /* As long as MENU_ATTACHED_USB == GO_TO_ROOT this works */
435 if (ret_val <= GO_TO_ROOT)
437 if (ret_val == MENU_ATTACHED_USB)
438 check_boot();
439 else if (ret_val == GO_TO_PREVIOUS)
441 ret_val = last_screen;
442 last_screen = GO_TO_ROOT;
444 continue;
446 last_screen = GO_TO_ROOT;
447 break;
449 case GO_TO_PREVIOUS:
450 ret_val = last_screen;
451 continue;
452 break;
454 case GO_TO_PREVIOUS_BROWSER:
455 ret_val = previous_browser;
456 break;
458 case GO_TO_PREVIOUS_MUSIC:
459 ret_val = previous_music;
460 break;
462 this_screen = ret_val;
463 /* set the global_status.last_screen before entering,
464 if we dont we will always return to the wrong screen on boot */
465 global_status.last_screen = (char)this_screen;
466 if (this_screen == GO_TO_FILEBROWSER
467 #ifdef HAVE_TAGCACHE
468 || this_screen == GO_TO_DBBROWSER
469 #endif
471 previous_browser = this_screen;
472 if (this_screen == GO_TO_WPS
473 #ifdef CONFIG_TUNER
474 || this_screen == GO_TO_FM
475 #endif
477 previous_music = this_screen;
478 status_save();
479 action_signalscreenchange();
480 ret_val = items[this_screen].function(items[this_screen].param);
481 if (ret_val != GO_TO_PREVIOUS)
482 last_screen = this_screen;
484 return;