diff options
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/debug_menu.c | 31 | ||||
-rw-r--r-- | apps/debug_menu.h | 1 | ||||
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/main.c | 3 | ||||
-rw-r--r-- | apps/menu.c | 38 | ||||
-rw-r--r-- | apps/menu.h | 3 | ||||
-rw-r--r-- | apps/misc.h | 3 | ||||
-rw-r--r-- | apps/onplay.c | 19 | ||||
-rw-r--r-- | apps/onplay.h | 2 | ||||
-rw-r--r-- | apps/root_menu.c | 6 | ||||
-rw-r--r-- | apps/root_menu.h | 1 | ||||
-rw-r--r-- | apps/shortcuts.c | 421 | ||||
-rw-r--r-- | apps/shortcuts.h | 43 | ||||
-rw-r--r-- | apps/tree.c | 5 | ||||
-rw-r--r-- | apps/tree.h | 2 | ||||
-rw-r--r-- | manual/main_menu/main.tex | 57 |
17 files changed, 628 insertions, 22 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index 0734d3475a..7ef81a10ee 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -52,6 +52,7 @@ root_menu.c | |||
52 | screens.c | 52 | screens.c |
53 | settings.c | 53 | settings.c |
54 | settings_list.c | 54 | settings_list.c |
55 | shortcuts.c | ||
55 | status.c | 56 | status.c |
56 | cuesheet.c | 57 | cuesheet.c |
57 | talk.c | 58 | talk.c |
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 442bc8b162..809644b3d2 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <stdbool.h> | 25 | #include <stdbool.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include "lcd.h" | 27 | #include "lcd.h" |
28 | #include "lang.h" | ||
28 | #include "menu.h" | 29 | #include "menu.h" |
29 | #include "debug_menu.h" | 30 | #include "debug_menu.h" |
30 | #include "kernel.h" | 31 | #include "kernel.h" |
@@ -45,6 +46,7 @@ | |||
45 | #include "screens.h" | 46 | #include "screens.h" |
46 | #include "misc.h" | 47 | #include "misc.h" |
47 | #include "splash.h" | 48 | #include "splash.h" |
49 | #include "shortcuts.h" | ||
48 | #include "dircache.h" | 50 | #include "dircache.h" |
49 | #include "viewport.h" | 51 | #include "viewport.h" |
50 | #ifdef HAVE_TAGCACHE | 52 | #ifdef HAVE_TAGCACHE |
@@ -2120,15 +2122,23 @@ static const struct the_menu_item menuitems[] = { | |||
2120 | }; | 2122 | }; |
2121 | static int menu_action_callback(int btn, struct gui_synclist *lists) | 2123 | static int menu_action_callback(int btn, struct gui_synclist *lists) |
2122 | { | 2124 | { |
2125 | int selection = gui_synclist_get_sel_pos(lists); | ||
2123 | if (btn == ACTION_STD_OK) | 2126 | if (btn == ACTION_STD_OK) |
2124 | { | 2127 | { |
2125 | FOR_NB_SCREENS(i) | 2128 | FOR_NB_SCREENS(i) |
2126 | viewportmanager_theme_enable(i, false, NULL); | 2129 | viewportmanager_theme_enable(i, false, NULL); |
2127 | menuitems[gui_synclist_get_sel_pos(lists)].function(); | 2130 | menuitems[selection].function(); |
2128 | btn = ACTION_REDRAW; | 2131 | btn = ACTION_REDRAW; |
2129 | FOR_NB_SCREENS(i) | 2132 | FOR_NB_SCREENS(i) |
2130 | viewportmanager_theme_undo(i, false); | 2133 | viewportmanager_theme_undo(i, false); |
2131 | } | 2134 | } |
2135 | else if (btn == ACTION_STD_CONTEXT) | ||
2136 | { | ||
2137 | MENUITEM_STRINGLIST(menu_items, "Debug Menu", NULL, ID2P(LANG_ADD_TO_FAVES)); | ||
2138 | if (do_menu(&menu_items, NULL, NULL, false) == 0) | ||
2139 | shortcuts_add(SHORTCUT_DEBUGITEM, menuitems[selection].desc); | ||
2140 | return ACTION_STD_CANCEL; | ||
2141 | } | ||
2132 | return btn; | 2142 | return btn; |
2133 | } | 2143 | } |
2134 | 2144 | ||
@@ -2148,3 +2158,22 @@ bool debug_menu(void) | |||
2148 | info.get_name = dbg_menu_getname; | 2158 | info.get_name = dbg_menu_getname; |
2149 | return simplelist_show_list(&info); | 2159 | return simplelist_show_list(&info); |
2150 | } | 2160 | } |
2161 | |||
2162 | bool run_debug_screen(char* screen) | ||
2163 | { | ||
2164 | unsigned i; | ||
2165 | for (i=0; i<ARRAYLEN(menuitems); i++) | ||
2166 | { | ||
2167 | if (!strcmp(screen, menuitems[i].desc)) | ||
2168 | { | ||
2169 | FOR_NB_SCREENS(j) | ||
2170 | viewportmanager_theme_enable(j, false, NULL); | ||
2171 | menuitems[i].function(); | ||
2172 | FOR_NB_SCREENS(j) | ||
2173 | viewportmanager_theme_undo(j, false); | ||
2174 | return true; | ||
2175 | } | ||
2176 | } | ||
2177 | return false; | ||
2178 | } | ||
2179 | |||
diff --git a/apps/debug_menu.h b/apps/debug_menu.h index ecb50c40ae..17a9c2e094 100644 --- a/apps/debug_menu.h +++ b/apps/debug_menu.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define _DEBUG_MENU_H | 22 | #define _DEBUG_MENU_H |
23 | 23 | ||
24 | bool debug_menu(void); | 24 | bool debug_menu(void); |
25 | bool run_debug_screen(char* screen); | ||
25 | 26 | ||
26 | #ifndef SIMULATOR | 27 | #ifndef SIMULATOR |
27 | extern bool dbg_ports(void); | 28 | extern bool dbg_ports(void); |
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 5a59473681..741f120023 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -12903,3 +12903,17 @@ | |||
12903 | *: "Cancel Sleep Timer" | 12903 | *: "Cancel Sleep Timer" |
12904 | </voice> | 12904 | </voice> |
12905 | </phrase> | 12905 | </phrase> |
12906 | <phrase> | ||
12907 | id: LANG_SHORTCUTS | ||
12908 | desc: Title in the shortcuts menu | ||
12909 | user: core | ||
12910 | <source> | ||
12911 | *: "Shortcuts" | ||
12912 | </source> | ||
12913 | <dest> | ||
12914 | *: "Shortcuts" | ||
12915 | </dest> | ||
12916 | <voice> | ||
12917 | *: "Shortcuts" | ||
12918 | </voice> | ||
12919 | </phrase> | ||
diff --git a/apps/main.c b/apps/main.c index c2dfc1a435..38de780c8d 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | 79 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) |
80 | #include "notification.h" | 80 | #include "notification.h" |
81 | #endif | 81 | #endif |
82 | #include "shortcuts.h" | ||
82 | 83 | ||
83 | #ifdef IPOD_ACCESSORY_PROTOCOL | 84 | #ifdef IPOD_ACCESSORY_PROTOCOL |
84 | #include "iap.h" | 85 | #include "iap.h" |
@@ -387,6 +388,7 @@ static void init(void) | |||
387 | filetype_init(); | 388 | filetype_init(); |
388 | playlist_init(); | 389 | playlist_init(); |
389 | theme_init_buffer(); | 390 | theme_init_buffer(); |
391 | shortcuts_init(); | ||
390 | 392 | ||
391 | #if CONFIG_CODEC != SWCODEC | 393 | #if CONFIG_CODEC != SWCODEC |
392 | mp3_init( global_settings.volume, | 394 | mp3_init( global_settings.volume, |
@@ -667,6 +669,7 @@ static void init(void) | |||
667 | filetype_init(); | 669 | filetype_init(); |
668 | scrobbler_init(); | 670 | scrobbler_init(); |
669 | theme_init_buffer(); | 671 | theme_init_buffer(); |
672 | shortcuts_init(); | ||
670 | 673 | ||
671 | #if CONFIG_CODEC != SWCODEC | 674 | #if CONFIG_CODEC != SWCODEC |
672 | /* No buffer allocation (see buffer.c) may take place after the call to | 675 | /* No buffer allocation (see buffer.c) may take place after the call to |
diff --git a/apps/menu.c b/apps/menu.c index b4be83fc26..a1e32f4625 100644 --- a/apps/menu.c +++ b/apps/menu.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "audio.h" | 52 | #include "audio.h" |
53 | #include "viewport.h" | 53 | #include "viewport.h" |
54 | #include "quickscreen.h" | 54 | #include "quickscreen.h" |
55 | #include "shortcuts.h" | ||
55 | 56 | ||
56 | #ifdef HAVE_LCD_BITMAP | 57 | #ifdef HAVE_LCD_BITMAP |
57 | #include "icons.h" | 58 | #include "icons.h" |
@@ -280,19 +281,10 @@ static int talk_menu_item(int selected_item, void *data) | |||
280 | return 0; | 281 | return 0; |
281 | } | 282 | } |
282 | 283 | ||
283 | void do_setting_from_menu(const struct menu_item_ex *temp, | 284 | void do_setting_screen(const struct settings_list *setting, const char * title, |
284 | struct viewport parent[NB_SCREENS]) | 285 | struct viewport parent[NB_SCREENS]) |
285 | { | 286 | { |
286 | int setting_id; | ||
287 | const struct settings_list *setting = | ||
288 | find_setting(temp->variable, &setting_id); | ||
289 | char *title; | ||
290 | char padded_title[MAX_PATH]; | 287 | char padded_title[MAX_PATH]; |
291 | if ((temp->flags&MENU_TYPE_MASK) == MT_SETTING_W_TEXT) | ||
292 | title = temp->callback_and_desc->desc; | ||
293 | else | ||
294 | title = ID2P(setting->lang_id); | ||
295 | |||
296 | /* Pad the title string by repeating it. This is needed | 288 | /* Pad the title string by repeating it. This is needed |
297 | so the scroll settings title can actually be used to | 289 | so the scroll settings title can actually be used to |
298 | test the setting */ | 290 | test the setting */ |
@@ -317,7 +309,22 @@ void do_setting_from_menu(const struct menu_item_ex *temp, | |||
317 | } | 309 | } |
318 | 310 | ||
319 | option_screen((struct settings_list *)setting, parent, | 311 | option_screen((struct settings_list *)setting, parent, |
320 | setting->flags&F_TEMPVAR, title); | 312 | setting->flags&F_TEMPVAR, (char*)title); |
313 | } | ||
314 | |||
315 | |||
316 | void do_setting_from_menu(const struct menu_item_ex *temp, | ||
317 | struct viewport parent[NB_SCREENS]) | ||
318 | { | ||
319 | char *title; | ||
320 | int setting_id; | ||
321 | const struct settings_list *setting = | ||
322 | find_setting(temp->variable, &setting_id); | ||
323 | if (temp && ((temp->flags&MENU_TYPE_MASK) == MT_SETTING_W_TEXT)) | ||
324 | title = temp->callback_and_desc->desc; | ||
325 | else | ||
326 | title = ID2P(setting->lang_id); | ||
327 | do_setting_screen(setting, title, parent); | ||
321 | } | 328 | } |
322 | 329 | ||
323 | /* display a menu */ | 330 | /* display a menu */ |
@@ -451,7 +458,8 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
451 | ID2P(LANG_TOP_QS_ITEM), | 458 | ID2P(LANG_TOP_QS_ITEM), |
452 | ID2P(LANG_LEFT_QS_ITEM), | 459 | ID2P(LANG_LEFT_QS_ITEM), |
453 | ID2P(LANG_BOTTOM_QS_ITEM), | 460 | ID2P(LANG_BOTTOM_QS_ITEM), |
454 | ID2P(LANG_RIGHT_QS_ITEM)); | 461 | ID2P(LANG_RIGHT_QS_ITEM), |
462 | ID2P(LANG_ADD_TO_FAVES)); | ||
455 | #endif | 463 | #endif |
456 | MENUITEM_STRINGLIST(notquickscreen_able_option, | 464 | MENUITEM_STRINGLIST(notquickscreen_able_option, |
457 | ID2P(LANG_ONPLAY_MENU_TITLE), NULL, | 465 | ID2P(LANG_ONPLAY_MENU_TITLE), NULL, |
@@ -486,6 +494,10 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
486 | case 4: /* set as right QS item */ | 494 | case 4: /* set as right QS item */ |
487 | set_as_qs_item(setting, QUICKSCREEN_RIGHT); | 495 | set_as_qs_item(setting, QUICKSCREEN_RIGHT); |
488 | break; | 496 | break; |
497 | case 5: /* Add to faves. Same limitation on which can be | ||
498 | added to the shortcuts menu as the quickscreen */ | ||
499 | shortcuts_add(SHORTCUT_SETTING, (void*)setting); | ||
500 | break; | ||
489 | #endif | 501 | #endif |
490 | } /* swicth(do_menu()) */ | 502 | } /* swicth(do_menu()) */ |
491 | redraw_lists = true; | 503 | redraw_lists = true; |
diff --git a/apps/menu.h b/apps/menu.h index 2251de243c..ee2d9e7f40 100644 --- a/apps/menu.h +++ b/apps/menu.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "icon.h" | 26 | #include "icon.h" |
27 | #include "icons.h" | 27 | #include "icons.h" |
28 | #include "root_menu.h" /* needed for MENU_* return codes */ | 28 | #include "root_menu.h" /* needed for MENU_* return codes */ |
29 | #include "settings_list.h" | ||
29 | 30 | ||
30 | 31 | ||
31 | enum menu_item_type { | 32 | enum menu_item_type { |
@@ -103,6 +104,8 @@ typedef int (*menu_callback_type)(int action, | |||
103 | const struct menu_item_ex *this_item); | 104 | const struct menu_item_ex *this_item); |
104 | void do_setting_from_menu(const struct menu_item_ex *temp, | 105 | void do_setting_from_menu(const struct menu_item_ex *temp, |
105 | struct viewport parent[NB_SCREENS]); | 106 | struct viewport parent[NB_SCREENS]); |
107 | void do_setting_screen(const struct settings_list *setting, const char * title, | ||
108 | struct viewport parent[NB_SCREENS]); | ||
106 | 109 | ||
107 | /* | 110 | /* |
108 | int do_menu(const struct menu_item_ex *menu, int *start_selected) | 111 | int do_menu(const struct menu_item_ex *menu, int *start_selected) |
diff --git a/apps/misc.h b/apps/misc.h index bfe6e5b449..4647898889 100644 --- a/apps/misc.h +++ b/apps/misc.h | |||
@@ -119,7 +119,8 @@ enum current_activity { | |||
119 | ACTIVITY_CONTEXTMENU, | 119 | ACTIVITY_CONTEXTMENU, |
120 | ACTIVITY_SYSTEMSCREEN, | 120 | ACTIVITY_SYSTEMSCREEN, |
121 | ACTIVITY_TIMEDATESCREEN, | 121 | ACTIVITY_TIMEDATESCREEN, |
122 | ACTIVITY_BOOKMARKSLIST | 122 | ACTIVITY_BOOKMARKSLIST, |
123 | ACTIVITY_SHORTCUTSMENU | ||
123 | }; | 124 | }; |
124 | 125 | ||
125 | #if CONFIG_CODEC == SWCODEC | 126 | #if CONFIG_CODEC == SWCODEC |
diff --git a/apps/onplay.c b/apps/onplay.c index aab023c846..629de93886 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include "pitchscreen.h" | 63 | #include "pitchscreen.h" |
64 | #include "viewport.h" | 64 | #include "viewport.h" |
65 | #include "filefuncs.h" | 65 | #include "filefuncs.h" |
66 | #include "shortcuts.h" | ||
66 | 67 | ||
67 | static int context; | 68 | static int context; |
68 | static char* selected_file = NULL; | 69 | static char* selected_file = NULL; |
@@ -382,10 +383,13 @@ static int treeplaylist_callback(int action, | |||
382 | return action; | 383 | return action; |
383 | } | 384 | } |
384 | 385 | ||
385 | void onplay_show_playlist_menu(char* track_name) | 386 | void onplay_show_playlist_menu(char* path) |
386 | { | 387 | { |
387 | selected_file = track_name; | 388 | selected_file = path; |
388 | selected_file_attr = FILE_ATTR_AUDIO; | 389 | if (dir_exists(path)) |
390 | selected_file_attr = ATTR_DIRECTORY; | ||
391 | else | ||
392 | selected_file_attr = filetype_get_attr(path); | ||
389 | do_menu(&tree_playlist_menu, NULL, NULL, false); | 393 | do_menu(&tree_playlist_menu, NULL, NULL, false); |
390 | } | 394 | } |
391 | 395 | ||
@@ -1032,8 +1036,13 @@ MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH), | |||
1032 | MENUITEM_FUNCTION(properties_item, MENU_FUNC_USEPARAM, ID2P(LANG_PROPERTIES), | 1036 | MENUITEM_FUNCTION(properties_item, MENU_FUNC_USEPARAM, ID2P(LANG_PROPERTIES), |
1033 | onplay_load_plugin, (void *)"properties", | 1037 | onplay_load_plugin, (void *)"properties", |
1034 | clipboard_callback, Icon_NOICON); | 1038 | clipboard_callback, Icon_NOICON); |
1035 | MENUITEM_FUNCTION(add_to_faves_item, MENU_FUNC_USEPARAM, ID2P(LANG_ADD_TO_FAVES), | 1039 | static bool onplay_add_to_shortcuts(void) |
1036 | onplay_load_plugin, (void *)"shortcuts_append", | 1040 | { |
1041 | shortcuts_add(SHORTCUT_BROWSER, selected_file); | ||
1042 | return false; | ||
1043 | } | ||
1044 | MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES), | ||
1045 | onplay_add_to_shortcuts, NULL, | ||
1037 | clipboard_callback, Icon_NOICON); | 1046 | clipboard_callback, Icon_NOICON); |
1038 | 1047 | ||
1039 | #if LCD_DEPTH > 1 | 1048 | #if LCD_DEPTH > 1 |
diff --git a/apps/onplay.h b/apps/onplay.h index 921303cf57..d24bf567b1 100644 --- a/apps/onplay.h +++ b/apps/onplay.h | |||
@@ -50,6 +50,6 @@ enum hotkey_action { | |||
50 | 50 | ||
51 | /* needed for the playlist viewer.. eventually clean this up */ | 51 | /* needed for the playlist viewer.. eventually clean this up */ |
52 | void onplay_show_playlist_cat_menu(char* track_name); | 52 | void onplay_show_playlist_cat_menu(char* track_name); |
53 | void onplay_show_playlist_menu(char* track_name); | 53 | void onplay_show_playlist_menu(char* path); |
54 | 54 | ||
55 | #endif | 55 | #endif |
diff --git a/apps/root_menu.c b/apps/root_menu.c index 1e9924fb44..e78c02759b 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "power.h" | 37 | #include "power.h" |
38 | #include "talk.h" | 38 | #include "talk.h" |
39 | #include "audio.h" | 39 | #include "audio.h" |
40 | #include "shortcuts.h" | ||
40 | 41 | ||
41 | #ifdef HAVE_HOTSWAP | 42 | #ifdef HAVE_HOTSWAP |
42 | #include "storage.h" | 43 | #include "storage.h" |
@@ -415,12 +416,16 @@ static const struct root_items items[] = { | |||
415 | &playlist_options }, | 416 | &playlist_options }, |
416 | [GO_TO_PLAYLIST_VIEWER] = { playlist_view, NULL, &playlist_options }, | 417 | [GO_TO_PLAYLIST_VIEWER] = { playlist_view, NULL, &playlist_options }, |
417 | [GO_TO_SYSTEM_SCREEN] = { miscscrn, &info_menu, &system_menu }, | 418 | [GO_TO_SYSTEM_SCREEN] = { miscscrn, &info_menu, &system_menu }, |
419 | [GO_TO_SHORTCUTMENU] = { do_shortcut_menu, NULL, NULL }, | ||
418 | 420 | ||
419 | }; | 421 | }; |
420 | static const int nb_items = sizeof(items)/sizeof(*items); | 422 | static const int nb_items = sizeof(items)/sizeof(*items); |
421 | 423 | ||
422 | static int item_callback(int action, const struct menu_item_ex *this_item) ; | 424 | static int item_callback(int action, const struct menu_item_ex *this_item) ; |
423 | 425 | ||
426 | MENUITEM_RETURNVALUE(shortcut_menu, ID2P(LANG_SHORTCUTS), GO_TO_SHORTCUTMENU, | ||
427 | NULL, Icon_Bookmark); | ||
428 | |||
424 | MENUITEM_RETURNVALUE(file_browser, ID2P(LANG_DIR_BROWSER), GO_TO_FILEBROWSER, | 429 | MENUITEM_RETURNVALUE(file_browser, ID2P(LANG_DIR_BROWSER), GO_TO_FILEBROWSER, |
425 | NULL, Icon_file_view_menu); | 430 | NULL, Icon_file_view_menu); |
426 | #ifdef HAVE_TAGCACHE | 431 | #ifdef HAVE_TAGCACHE |
@@ -492,6 +497,7 @@ MAKE_MENU(root_menu_, ID2P(LANG_ROCKBOX_TITLE), | |||
492 | #if CONFIG_KEYPAD == PLAYER_PAD | 497 | #if CONFIG_KEYPAD == PLAYER_PAD |
493 | ,&do_shutdown_item | 498 | ,&do_shutdown_item |
494 | #endif | 499 | #endif |
500 | ,&shortcut_menu | ||
495 | ); | 501 | ); |
496 | 502 | ||
497 | static int item_callback(int action, const struct menu_item_ex *this_item) | 503 | static int item_callback(int action, const struct menu_item_ex *this_item) |
diff --git a/apps/root_menu.h b/apps/root_menu.h index 2ffdcedda1..8d11d9b338 100644 --- a/apps/root_menu.h +++ b/apps/root_menu.h | |||
@@ -58,6 +58,7 @@ enum { | |||
58 | GO_TO_PLAYLISTS_SCREEN, | 58 | GO_TO_PLAYLISTS_SCREEN, |
59 | GO_TO_PLAYLIST_VIEWER, | 59 | GO_TO_PLAYLIST_VIEWER, |
60 | GO_TO_SYSTEM_SCREEN, | 60 | GO_TO_SYSTEM_SCREEN, |
61 | GO_TO_SHORTCUTMENU | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | extern const struct menu_item_ex root_menu_; | 64 | extern const struct menu_item_ex root_menu_; |
diff --git a/apps/shortcuts.c b/apps/shortcuts.c new file mode 100644 index 0000000000..3992068807 --- /dev/null +++ b/apps/shortcuts.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * __________ __ ___. | ||
4 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | * \/ \/ \/ \/ \/ | ||
9 | * $Id$ | ||
10 | * | ||
11 | * Copyright (C) 2011 Jonathan Gordon | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include <stdbool.h> | ||
24 | #include <stdlib.h> | ||
25 | #include "config.h" | ||
26 | #include "system.h" | ||
27 | #include "action.h" | ||
28 | #include "ata_idle_notify.h" | ||
29 | #include "debug_menu.h" | ||
30 | #include "core_alloc.h" | ||
31 | #include "list.h" | ||
32 | #include "settings.h" | ||
33 | #include "settings_list.h" | ||
34 | #include "lang.h" | ||
35 | #include "menu.h" | ||
36 | #include "misc.h" | ||
37 | #include "tree.h" | ||
38 | #include "splash.h" | ||
39 | #include "filefuncs.h" | ||
40 | #include "filetypes.h" | ||
41 | #include "shortcuts.h" | ||
42 | #include "onplay.h" | ||
43 | |||
44 | |||
45 | |||
46 | #define MAX_SHORTCUT_NAME 32 | ||
47 | #define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt" | ||
48 | char *type_strings[SHORTCUT_TYPE_COUNT] = { | ||
49 | [SHORTCUT_SETTING] = "setting", | ||
50 | [SHORTCUT_FILE] = "file", | ||
51 | [SHORTCUT_DEBUGITEM] = "debug", | ||
52 | [SHORTCUT_BROWSER] = "browse", | ||
53 | [SHORTCUT_PLAYLISTMENU] = "playlist menu", | ||
54 | [SHORTCUT_SEPARATOR] = "separator", | ||
55 | }; | ||
56 | |||
57 | |||
58 | struct shortcut { | ||
59 | enum shortcut_type type; | ||
60 | char name[MAX_SHORTCUT_NAME]; | ||
61 | int icon; | ||
62 | union { | ||
63 | char path[MAX_PATH]; | ||
64 | const struct settings_list *setting; | ||
65 | } u; | ||
66 | }; | ||
67 | #define SHORTCUTS_PER_HANDLE 32 | ||
68 | struct shortcut_handle { | ||
69 | struct shortcut shortcuts[SHORTCUTS_PER_HANDLE]; | ||
70 | int next_handle; | ||
71 | }; | ||
72 | static int first_handle = 0; | ||
73 | static int shortcut_count = 0; | ||
74 | |||
75 | static void reset_shortcuts(void) | ||
76 | { | ||
77 | int current_handle = first_handle; | ||
78 | struct shortcut_handle *h = NULL; | ||
79 | while (current_handle > 0) | ||
80 | { | ||
81 | int next; | ||
82 | h = core_get_data(current_handle); | ||
83 | next = h->next_handle; | ||
84 | core_free(current_handle); | ||
85 | current_handle = next; | ||
86 | } | ||
87 | first_handle = 0; | ||
88 | shortcut_count = 0; | ||
89 | } | ||
90 | |||
91 | static struct shortcut* get_shortcut(int index) | ||
92 | { | ||
93 | int handle_count, handle_index; | ||
94 | int current_handle = first_handle; | ||
95 | struct shortcut_handle *h = NULL; | ||
96 | |||
97 | if (first_handle == 0) | ||
98 | { | ||
99 | first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle)); | ||
100 | if (first_handle <= 0) | ||
101 | return NULL; | ||
102 | h = core_get_data(first_handle); | ||
103 | h->next_handle = 0; | ||
104 | current_handle = first_handle; | ||
105 | } | ||
106 | |||
107 | handle_count = index/SHORTCUTS_PER_HANDLE + 1; | ||
108 | handle_index = index%SHORTCUTS_PER_HANDLE; | ||
109 | do { | ||
110 | h = core_get_data(current_handle); | ||
111 | current_handle = h->next_handle; | ||
112 | handle_count--; | ||
113 | } while (handle_count > 0 && current_handle > 0); | ||
114 | if (handle_count > 0 && handle_index == 0) | ||
115 | { | ||
116 | char buf[32]; | ||
117 | snprintf(buf, sizeof buf, "shortcuts_%d", index/SHORTCUTS_PER_HANDLE); | ||
118 | h->next_handle = core_alloc(buf, sizeof(struct shortcut_handle)); | ||
119 | if (h->next_handle <= 0) | ||
120 | return NULL; | ||
121 | h = core_get_data(h->next_handle); | ||
122 | h->next_handle = 0; | ||
123 | } | ||
124 | return &h->shortcuts[handle_index]; | ||
125 | } | ||
126 | |||
127 | bool verify_shortcut(struct shortcut* sc) | ||
128 | { | ||
129 | switch (sc->type) | ||
130 | { | ||
131 | case SHORTCUT_UNDEFINED: | ||
132 | return false; | ||
133 | case SHORTCUT_BROWSER: | ||
134 | case SHORTCUT_FILE: | ||
135 | case SHORTCUT_PLAYLISTMENU: | ||
136 | if (sc->u.path[0] == '\0') | ||
137 | return false; | ||
138 | break; | ||
139 | case SHORTCUT_SETTING: | ||
140 | return sc->u.setting != NULL; | ||
141 | case SHORTCUT_DEBUGITEM: | ||
142 | case SHORTCUT_SEPARATOR: | ||
143 | default: | ||
144 | break; | ||
145 | } | ||
146 | return true; | ||
147 | } | ||
148 | |||
149 | static void init_shortcut(struct shortcut* sc) | ||
150 | { | ||
151 | sc->type = SHORTCUT_UNDEFINED; | ||
152 | sc->name[0] = '\0'; | ||
153 | sc->u.path[0] = '\0'; | ||
154 | sc->icon = Icon_NOICON; | ||
155 | } | ||
156 | static int first_idx_to_writeback = -1; | ||
157 | void shortcuts_ata_idle_callback(void* data) | ||
158 | { | ||
159 | (void)data; | ||
160 | int fd; | ||
161 | char buf[MAX_PATH]; | ||
162 | int current_idx = first_idx_to_writeback; | ||
163 | if (first_idx_to_writeback < 0) | ||
164 | return; | ||
165 | fd = open(SHORTCUTS_FILENAME, O_APPEND|O_RDWR|O_CREAT, 0644); | ||
166 | if (fd < 0) | ||
167 | return; | ||
168 | while (current_idx < shortcut_count) | ||
169 | { | ||
170 | struct shortcut* sc = get_shortcut(current_idx++); | ||
171 | char *type; | ||
172 | int len; | ||
173 | if (!sc) | ||
174 | break; | ||
175 | type = type_strings[sc->type]; | ||
176 | len = snprintf(buf, MAX_PATH, "[shortcut]\ntype: %s\ndata: ", type); | ||
177 | write(fd, buf, len); | ||
178 | if (sc->type == SHORTCUT_SETTING) | ||
179 | write(fd, sc->u.setting->cfg_name, strlen(sc->u.setting->cfg_name)); | ||
180 | else | ||
181 | write(fd, sc->u.path, strlen(sc->u.path)); | ||
182 | write(fd, "\n\n", 2); | ||
183 | } | ||
184 | close(fd); | ||
185 | if (first_idx_to_writeback == 0) | ||
186 | { | ||
187 | /* reload all shortcuts because we appended to the shortcuts file which | ||
188 | * has not been read yet. | ||
189 | */ | ||
190 | reset_shortcuts(); | ||
191 | shortcuts_init(); | ||
192 | } | ||
193 | first_idx_to_writeback = -1; | ||
194 | } | ||
195 | void shortcuts_add(enum shortcut_type type, char* value) | ||
196 | { | ||
197 | struct shortcut* sc = get_shortcut(shortcut_count++); | ||
198 | if (!sc) | ||
199 | return; | ||
200 | init_shortcut(sc); | ||
201 | sc->type = type; | ||
202 | if (type == SHORTCUT_SETTING) | ||
203 | sc->u.setting = (void*)value; | ||
204 | else | ||
205 | strlcpy(sc->u.path, value, MAX_PATH); | ||
206 | if (first_idx_to_writeback < 0) | ||
207 | first_idx_to_writeback = shortcut_count - 1; | ||
208 | register_storage_idle_func(shortcuts_ata_idle_callback); | ||
209 | } | ||
210 | |||
211 | |||
212 | int readline_cb(int n, char *buf, void *parameters) | ||
213 | { | ||
214 | (void)n; | ||
215 | (void)parameters; | ||
216 | struct shortcut **param = (struct shortcut**)parameters; | ||
217 | struct shortcut* sc = *param; | ||
218 | char *name, *value; | ||
219 | |||
220 | if (!strcasecmp(skip_whitespace(buf), "[shortcut]")) | ||
221 | { | ||
222 | if (sc && verify_shortcut(sc)) | ||
223 | shortcut_count++; | ||
224 | sc = get_shortcut(shortcut_count); | ||
225 | if (!sc) | ||
226 | return 1; | ||
227 | init_shortcut(sc); | ||
228 | *param = sc; | ||
229 | } | ||
230 | else if (sc && settings_parseline(buf, &name, &value)) | ||
231 | { | ||
232 | if (!strcmp(name, "type")) | ||
233 | { | ||
234 | int t = 0; | ||
235 | for (t=0; t<SHORTCUT_TYPE_COUNT && sc->type == SHORTCUT_UNDEFINED; t++) | ||
236 | if (!strcmp(value, type_strings[t])) | ||
237 | sc->type = t; | ||
238 | } | ||
239 | else if (!strcmp(name, "name")) | ||
240 | { | ||
241 | strlcpy(sc->name, value, MAX_SHORTCUT_NAME); | ||
242 | } | ||
243 | else if (!strcmp(name, "data")) | ||
244 | { | ||
245 | switch (sc->type) | ||
246 | { | ||
247 | case SHORTCUT_UNDEFINED: | ||
248 | case SHORTCUT_TYPE_COUNT: | ||
249 | *param = NULL; | ||
250 | break; | ||
251 | case SHORTCUT_BROWSER: | ||
252 | case SHORTCUT_FILE: | ||
253 | case SHORTCUT_DEBUGITEM: | ||
254 | case SHORTCUT_PLAYLISTMENU: | ||
255 | strlcpy(sc->u.path, value, MAX_PATH); | ||
256 | break; | ||
257 | case SHORTCUT_SETTING: | ||
258 | sc->u.setting = find_setting_by_cfgname(value, NULL); | ||
259 | break; | ||
260 | case SHORTCUT_SEPARATOR: | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | else if (!strcmp(name, "icon")) | ||
265 | { | ||
266 | if (!strcmp(value, "filetype") && sc->type != SHORTCUT_SETTING && sc->u.path[0]) | ||
267 | { | ||
268 | sc->icon = filetype_get_icon(filetype_get_attr(sc->u.path)); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | sc->icon = atoi(value); | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | void shortcuts_init(void) | ||
279 | { | ||
280 | int fd; | ||
281 | char buf[512]; | ||
282 | struct shortcut *param = NULL; | ||
283 | struct shortcut_handle *h; | ||
284 | shortcut_count = 0; | ||
285 | fd = open_utf8(SHORTCUTS_FILENAME, O_RDONLY); | ||
286 | if (fd < 0) | ||
287 | return; | ||
288 | first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle)); | ||
289 | if (first_handle <= 0) | ||
290 | return; | ||
291 | h = core_get_data(first_handle); | ||
292 | h->next_handle = 0; | ||
293 | fast_readline(fd, buf, sizeof buf, ¶m, readline_cb); | ||
294 | close(fd); | ||
295 | if (param && verify_shortcut(param)) | ||
296 | shortcut_count++; | ||
297 | } | ||
298 | |||
299 | const char * shortcut_menu_get_name(int selected_item, void * data, | ||
300 | char * buffer, size_t buffer_len) | ||
301 | { | ||
302 | (void)data; | ||
303 | (void)buffer; | ||
304 | (void)buffer_len; | ||
305 | struct shortcut *sc = get_shortcut(selected_item); | ||
306 | if (!sc) | ||
307 | return ""; | ||
308 | if (sc->type == SHORTCUT_SETTING) | ||
309 | return sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)); | ||
310 | else if (sc->type == SHORTCUT_SEPARATOR) | ||
311 | return sc->name; | ||
312 | return sc->name[0] ? sc->name : sc->u.path; | ||
313 | } | ||
314 | |||
315 | int shortcut_menu_get_action(int action, struct gui_synclist *lists) | ||
316 | { | ||
317 | (void)lists; | ||
318 | if (action == ACTION_STD_OK) | ||
319 | return ACTION_STD_CANCEL; | ||
320 | return action; | ||
321 | } | ||
322 | enum themable_icons shortcut_menu_get_icon(int selected_item, void * data) | ||
323 | { | ||
324 | (void)data; | ||
325 | struct shortcut *sc = get_shortcut(selected_item); | ||
326 | if (!sc) | ||
327 | return Icon_NOICON; | ||
328 | if (sc->icon == Icon_NOICON) | ||
329 | { | ||
330 | switch (sc->type) | ||
331 | { | ||
332 | case SHORTCUT_FILE: | ||
333 | return filetype_get_icon(filetype_get_attr(sc->u.path)); | ||
334 | case SHORTCUT_BROWSER: | ||
335 | return Icon_Folder; | ||
336 | case SHORTCUT_SETTING: | ||
337 | return Icon_Menu_setting; | ||
338 | case SHORTCUT_DEBUGITEM: | ||
339 | return Icon_Menu_functioncall; | ||
340 | case SHORTCUT_PLAYLISTMENU: | ||
341 | return Icon_Playlist; | ||
342 | default: | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | return sc->icon; | ||
347 | } | ||
348 | |||
349 | int do_shortcut_menu(void *ignored) | ||
350 | { | ||
351 | (void)ignored; | ||
352 | struct simplelist_info list; | ||
353 | struct shortcut *sc; | ||
354 | int done = GO_TO_PREVIOUS; | ||
355 | if (first_handle == 0) | ||
356 | shortcuts_init(); | ||
357 | simplelist_info_init(&list, P2STR(ID2P(LANG_SHORTCUTS)), shortcut_count, NULL); | ||
358 | list.get_name = shortcut_menu_get_name; | ||
359 | list.action_callback = shortcut_menu_get_action; | ||
360 | list.get_icon = shortcut_menu_get_icon; | ||
361 | list.title_icon = Icon_Bookmark; | ||
362 | |||
363 | push_current_activity(ACTIVITY_SHORTCUTSMENU); | ||
364 | |||
365 | while (done == GO_TO_PREVIOUS) | ||
366 | { | ||
367 | if (simplelist_show_list(&list)) | ||
368 | break; /* some error happened?! */ | ||
369 | if (list.selection == -1) | ||
370 | break; | ||
371 | else | ||
372 | { | ||
373 | sc = get_shortcut(list.selection); | ||
374 | if (!sc) | ||
375 | continue; | ||
376 | switch (sc->type) | ||
377 | { | ||
378 | case SHORTCUT_PLAYLISTMENU: | ||
379 | if (!file_exists(sc->u.path)) | ||
380 | { | ||
381 | splash(HZ, ID2P(LANG_NO_FILES)); | ||
382 | break; | ||
383 | } | ||
384 | else | ||
385 | { | ||
386 | onplay_show_playlist_menu(sc->u.path); | ||
387 | } | ||
388 | break; | ||
389 | case SHORTCUT_FILE: | ||
390 | if (!file_exists(sc->u.path)) | ||
391 | { | ||
392 | splash(HZ, ID2P(LANG_NO_FILES)); | ||
393 | break; | ||
394 | } | ||
395 | /* else fall through */ | ||
396 | case SHORTCUT_BROWSER: | ||
397 | { | ||
398 | struct browse_context browse; | ||
399 | browse_context_init(&browse, global_settings.dirfilter, 0, | ||
400 | NULL, NOICON, sc->u.path, NULL); | ||
401 | if (sc->type == SHORTCUT_FILE) | ||
402 | browse.flags |= BROWSE_RUNFILE; | ||
403 | done = rockbox_browse(&browse); | ||
404 | } | ||
405 | break; | ||
406 | case SHORTCUT_SETTING: | ||
407 | do_setting_screen(sc->u.setting, | ||
408 | sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)),NULL); | ||
409 | break; | ||
410 | case SHORTCUT_DEBUGITEM: | ||
411 | run_debug_screen(sc->u.path); | ||
412 | break; | ||
413 | case SHORTCUT_UNDEFINED: | ||
414 | default: | ||
415 | break; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | pop_current_activity(); | ||
420 | return done; | ||
421 | } | ||
diff --git a/apps/shortcuts.h b/apps/shortcuts.h new file mode 100644 index 0000000000..b794a3a2f4 --- /dev/null +++ b/apps/shortcuts.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * __________ __ ___. | ||
4 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | * \/ \/ \/ \/ \/ | ||
9 | * $Id$ | ||
10 | * | ||
11 | * Copyright (C) 2011 Jonathan Gordon | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #ifndef __SHORTCUTS_H__ | ||
23 | #define __SHORTCUTS_H__ | ||
24 | #include <stdbool.h> | ||
25 | #include <stdlib.h> | ||
26 | |||
27 | enum shortcut_type { | ||
28 | SHORTCUT_UNDEFINED = -1, | ||
29 | SHORTCUT_SETTING = 0, | ||
30 | SHORTCUT_FILE, | ||
31 | SHORTCUT_DEBUGITEM, | ||
32 | SHORTCUT_BROWSER, | ||
33 | SHORTCUT_PLAYLISTMENU, | ||
34 | SHORTCUT_SEPARATOR, | ||
35 | |||
36 | SHORTCUT_TYPE_COUNT | ||
37 | }; | ||
38 | |||
39 | void shortcuts_add(enum shortcut_type type, char* value); | ||
40 | void shortcuts_init(void); | ||
41 | int do_shortcut_menu(void*ignored); | ||
42 | |||
43 | #endif | ||
diff --git a/apps/tree.c b/apps/tree.c index eb7783d4ee..3ba54bdfc6 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -1000,7 +1000,10 @@ int rockbox_browse(struct browse_context *browse) | |||
1000 | tc.browse = browse; | 1000 | tc.browse = browse; |
1001 | strcpy(current, browse->root); | 1001 | strcpy(current, browse->root); |
1002 | set_current_file(current); | 1002 | set_current_file(current); |
1003 | ret_val = dirbrowse(); | 1003 | if (browse->flags&BROWSE_RUNFILE) |
1004 | ret_val = ft_enter(&tc); | ||
1005 | else | ||
1006 | ret_val = dirbrowse(); | ||
1004 | } | 1007 | } |
1005 | backup_count--; | 1008 | backup_count--; |
1006 | if (backup_count >= 0) | 1009 | if (backup_count >= 0) |
diff --git a/apps/tree.h b/apps/tree.h index 2b296050d3..a12045cae4 100644 --- a/apps/tree.h +++ b/apps/tree.h | |||
@@ -36,8 +36,10 @@ struct entry { | |||
36 | 36 | ||
37 | #define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */ | 37 | #define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */ |
38 | #define BROWSE_NO_CONTEXT_MENU 0x0002 /* disable context menu */ | 38 | #define BROWSE_NO_CONTEXT_MENU 0x0002 /* disable context menu */ |
39 | #define BROWSE_RUNFILE 0x0004 /* do ft_open() on the file instead of browsing */ | ||
39 | #define BROWSE_SELECTED 0x0100 /* this bit is set if user selected item */ | 40 | #define BROWSE_SELECTED 0x0100 /* this bit is set if user selected item */ |
40 | 41 | ||
42 | |||
41 | struct tree_context; | 43 | struct tree_context; |
42 | 44 | ||
43 | struct tree_cache { | 45 | struct tree_cache { |
diff --git a/manual/main_menu/main.tex b/manual/main_menu/main.tex index 139d85f958..3d5a2be69f 100644 --- a/manual/main_menu/main.tex +++ b/manual/main_menu/main.tex | |||
@@ -265,3 +265,60 @@ pages of information.} | |||
265 | quickscreen, then pressing up and down will cycle through this setting in | 265 | quickscreen, then pressing up and down will cycle through this setting in |
266 | opposite directions. | 266 | opposite directions. |
267 | } | 267 | } |
268 | |||
269 | \section{\label{ref:MainMenuShortcuts}Shortcuts} | ||
270 | |||
271 | This menu item is a container for user defined shortcuts to files, folders or | ||
272 | settings. The following are valid shortcuts: | ||
273 | \begin{itemize} | ||
274 | \item A file can be ``run'' (i.e. a music file played, plugin started or | ||
275 | a \fname{.cfg} loaded) | ||
276 | \item The file browser can be opened with the cursor positioned at | ||
277 | the specified file or folder | ||
278 | \item A file's or folder's ``Current Playlist'' context menu item can | ||
279 | be displayed | ||
280 | \item Most settings can be configured (any which can be added to the | ||
281 | \setting{Quick Screen}) | ||
282 | \item Any debug menu item (useful for developers mostly) | ||
283 | \end{itemize} | ||
284 | |||
285 | \note{Shortcuts into the database are not possible} | ||
286 | |||
287 | Shortcuts are loaded from the file \fname{/.rockbox/shortcuts.txt} which lists | ||
288 | each item to be displayed. Each shortcut looks like the following: | ||
289 | |||
290 | \begin{example} | ||
291 | [shortcut] | ||
292 | type: <specify the shortcut type/action> | ||
293 | data: <what the shortcut actually links to> | ||
294 | name: <what you want the shortcut to be displayed as> | ||
295 | icon: <number of the theme icon to use (see http://www.rockbox.org/wiki/CustomIcons)> | ||
296 | \end{example} | ||
297 | |||
298 | Only ``type'' and ``data'' are required (except if type is ``separator'' in which case | ||
299 | ``data'' is also not required). | ||
300 | |||
301 | Available types are: | ||
302 | \begin{description} | ||
303 | \item[file] \config{data} is the filename to run | ||
304 | \item[browse] \config{data} is the file or the folder to open the file browser at | ||
305 | \item[playlist menu] \config{data} is the file or the folder to open the | ||
306 | ``Current Playlist'' context menu item on | ||
307 | \item[setting] \config{data} is the config name of the setting you want to change | ||
308 | \item[debug] \config{data} is the name of the debug menu item to display | ||
309 | \item[separator] \config{data} is ignored; name can be used to display text, | ||
310 | or left blank to make the list more accessible with visual gaps | ||
311 | \end{description} | ||
312 | |||
313 | |||
314 | If the name/icon items are not specified a sensible default will be used. | ||
315 | |||
316 | \note{For the ``browse'' type, if you want the file browser to start \emph{inside} | ||
317 | a folder, make sure the data has the trailing slash (i.e \fname{/Music/} instead of | ||
318 | \fname {/Music}). Without the trailing slash, it will cause the file broser to open | ||
319 | with \fname{/Music} selected instead.} | ||
320 | |||
321 | The file \fname{shortcuts.txt} can be edited with any text editor. Most items can | ||
322 | also be added to it through their context menu item ``Add to shortcuts''. | ||
323 | A reboot is needed for manual changes to \fname{shortcuts.txt} to be applied. | ||
324 | |||