FS#12251 - User shortcuts in the main menu.

Custom shortcuts which give the user fast access to regularly used files/folders/settings/whatever.
Thanks to Alexander Levin for the manual part of the patch

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30990 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2011-11-15 13:22:02 +00:00
parent e7e4b131d0
commit 101693fd30
17 changed files with 628 additions and 22 deletions

View File

@ -52,6 +52,7 @@ root_menu.c
screens.c
settings.c
settings_list.c
shortcuts.c
status.c
cuesheet.c
talk.c

View File

@ -25,6 +25,7 @@
#include <stdbool.h>
#include <string.h>
#include "lcd.h"
#include "lang.h"
#include "menu.h"
#include "debug_menu.h"
#include "kernel.h"
@ -45,6 +46,7 @@
#include "screens.h"
#include "misc.h"
#include "splash.h"
#include "shortcuts.h"
#include "dircache.h"
#include "viewport.h"
#ifdef HAVE_TAGCACHE
@ -2120,15 +2122,23 @@ static const struct the_menu_item menuitems[] = {
};
static int menu_action_callback(int btn, struct gui_synclist *lists)
{
int selection = gui_synclist_get_sel_pos(lists);
if (btn == ACTION_STD_OK)
{
FOR_NB_SCREENS(i)
viewportmanager_theme_enable(i, false, NULL);
menuitems[gui_synclist_get_sel_pos(lists)].function();
menuitems[selection].function();
btn = ACTION_REDRAW;
FOR_NB_SCREENS(i)
viewportmanager_theme_undo(i, false);
}
else if (btn == ACTION_STD_CONTEXT)
{
MENUITEM_STRINGLIST(menu_items, "Debug Menu", NULL, ID2P(LANG_ADD_TO_FAVES));
if (do_menu(&menu_items, NULL, NULL, false) == 0)
shortcuts_add(SHORTCUT_DEBUGITEM, menuitems[selection].desc);
return ACTION_STD_CANCEL;
}
return btn;
}
@ -2148,3 +2158,22 @@ bool debug_menu(void)
info.get_name = dbg_menu_getname;
return simplelist_show_list(&info);
}
bool run_debug_screen(char* screen)
{
unsigned i;
for (i=0; i<ARRAYLEN(menuitems); i++)
{
if (!strcmp(screen, menuitems[i].desc))
{
FOR_NB_SCREENS(j)
viewportmanager_theme_enable(j, false, NULL);
menuitems[i].function();
FOR_NB_SCREENS(j)
viewportmanager_theme_undo(j, false);
return true;
}
}
return false;
}

View File

@ -22,6 +22,7 @@
#define _DEBUG_MENU_H
bool debug_menu(void);
bool run_debug_screen(char* screen);
#ifndef SIMULATOR
extern bool dbg_ports(void);

View File

@ -12903,3 +12903,17 @@
*: "Cancel Sleep Timer"
</voice>
</phrase>
<phrase>
id: LANG_SHORTCUTS
desc: Title in the shortcuts menu
user: core
<source>
*: "Shortcuts"
</source>
<dest>
*: "Shortcuts"
</dest>
<voice>
*: "Shortcuts"
</voice>
</phrase>

View File

@ -79,6 +79,7 @@
#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
#include "notification.h"
#endif
#include "shortcuts.h"
#ifdef IPOD_ACCESSORY_PROTOCOL
#include "iap.h"
@ -387,6 +388,7 @@ static void init(void)
filetype_init();
playlist_init();
theme_init_buffer();
shortcuts_init();
#if CONFIG_CODEC != SWCODEC
mp3_init( global_settings.volume,
@ -667,6 +669,7 @@ static void init(void)
filetype_init();
scrobbler_init();
theme_init_buffer();
shortcuts_init();
#if CONFIG_CODEC != SWCODEC
/* No buffer allocation (see buffer.c) may take place after the call to

View File

@ -52,6 +52,7 @@
#include "audio.h"
#include "viewport.h"
#include "quickscreen.h"
#include "shortcuts.h"
#ifdef HAVE_LCD_BITMAP
#include "icons.h"
@ -280,19 +281,10 @@ static int talk_menu_item(int selected_item, void *data)
return 0;
}
void do_setting_from_menu(const struct menu_item_ex *temp,
struct viewport parent[NB_SCREENS])
void do_setting_screen(const struct settings_list *setting, const char * title,
struct viewport parent[NB_SCREENS])
{
int setting_id;
const struct settings_list *setting =
find_setting(temp->variable, &setting_id);
char *title;
char padded_title[MAX_PATH];
if ((temp->flags&MENU_TYPE_MASK) == MT_SETTING_W_TEXT)
title = temp->callback_and_desc->desc;
else
title = ID2P(setting->lang_id);
/* Pad the title string by repeating it. This is needed
so the scroll settings title can actually be used to
test the setting */
@ -317,7 +309,22 @@ void do_setting_from_menu(const struct menu_item_ex *temp,
}
option_screen((struct settings_list *)setting, parent,
setting->flags&F_TEMPVAR, title);
setting->flags&F_TEMPVAR, (char*)title);
}
void do_setting_from_menu(const struct menu_item_ex *temp,
struct viewport parent[NB_SCREENS])
{
char *title;
int setting_id;
const struct settings_list *setting =
find_setting(temp->variable, &setting_id);
if (temp && ((temp->flags&MENU_TYPE_MASK) == MT_SETTING_W_TEXT))
title = temp->callback_and_desc->desc;
else
title = ID2P(setting->lang_id);
do_setting_screen(setting, title, parent);
}
/* display a menu */
@ -451,7 +458,8 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected,
ID2P(LANG_TOP_QS_ITEM),
ID2P(LANG_LEFT_QS_ITEM),
ID2P(LANG_BOTTOM_QS_ITEM),
ID2P(LANG_RIGHT_QS_ITEM));
ID2P(LANG_RIGHT_QS_ITEM),
ID2P(LANG_ADD_TO_FAVES));
#endif
MENUITEM_STRINGLIST(notquickscreen_able_option,
ID2P(LANG_ONPLAY_MENU_TITLE), NULL,
@ -486,6 +494,10 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected,
case 4: /* set as right QS item */
set_as_qs_item(setting, QUICKSCREEN_RIGHT);
break;
case 5: /* Add to faves. Same limitation on which can be
added to the shortcuts menu as the quickscreen */
shortcuts_add(SHORTCUT_SETTING, (void*)setting);
break;
#endif
} /* swicth(do_menu()) */
redraw_lists = true;

View File

@ -26,6 +26,7 @@
#include "icon.h"
#include "icons.h"
#include "root_menu.h" /* needed for MENU_* return codes */
#include "settings_list.h"
enum menu_item_type {
@ -103,6 +104,8 @@ typedef int (*menu_callback_type)(int action,
const struct menu_item_ex *this_item);
void do_setting_from_menu(const struct menu_item_ex *temp,
struct viewport parent[NB_SCREENS]);
void do_setting_screen(const struct settings_list *setting, const char * title,
struct viewport parent[NB_SCREENS]);
/*
int do_menu(const struct menu_item_ex *menu, int *start_selected)

View File

@ -119,7 +119,8 @@ enum current_activity {
ACTIVITY_CONTEXTMENU,
ACTIVITY_SYSTEMSCREEN,
ACTIVITY_TIMEDATESCREEN,
ACTIVITY_BOOKMARKSLIST
ACTIVITY_BOOKMARKSLIST,
ACTIVITY_SHORTCUTSMENU
};
#if CONFIG_CODEC == SWCODEC

View File

@ -63,6 +63,7 @@
#include "pitchscreen.h"
#include "viewport.h"
#include "filefuncs.h"
#include "shortcuts.h"
static int context;
static char* selected_file = NULL;
@ -382,10 +383,13 @@ static int treeplaylist_callback(int action,
return action;
}
void onplay_show_playlist_menu(char* track_name)
void onplay_show_playlist_menu(char* path)
{
selected_file = track_name;
selected_file_attr = FILE_ATTR_AUDIO;
selected_file = path;
if (dir_exists(path))
selected_file_attr = ATTR_DIRECTORY;
else
selected_file_attr = filetype_get_attr(path);
do_menu(&tree_playlist_menu, NULL, NULL, false);
}
@ -1032,8 +1036,13 @@ MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH),
MENUITEM_FUNCTION(properties_item, MENU_FUNC_USEPARAM, ID2P(LANG_PROPERTIES),
onplay_load_plugin, (void *)"properties",
clipboard_callback, Icon_NOICON);
MENUITEM_FUNCTION(add_to_faves_item, MENU_FUNC_USEPARAM, ID2P(LANG_ADD_TO_FAVES),
onplay_load_plugin, (void *)"shortcuts_append",
static bool onplay_add_to_shortcuts(void)
{
shortcuts_add(SHORTCUT_BROWSER, selected_file);
return false;
}
MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
onplay_add_to_shortcuts, NULL,
clipboard_callback, Icon_NOICON);
#if LCD_DEPTH > 1

View File

@ -50,6 +50,6 @@ enum hotkey_action {
/* needed for the playlist viewer.. eventually clean this up */
void onplay_show_playlist_cat_menu(char* track_name);
void onplay_show_playlist_menu(char* track_name);
void onplay_show_playlist_menu(char* path);
#endif

View File

@ -37,6 +37,7 @@
#include "power.h"
#include "talk.h"
#include "audio.h"
#include "shortcuts.h"
#ifdef HAVE_HOTSWAP
#include "storage.h"
@ -415,12 +416,16 @@ static const struct root_items items[] = {
&playlist_options },
[GO_TO_PLAYLIST_VIEWER] = { playlist_view, NULL, &playlist_options },
[GO_TO_SYSTEM_SCREEN] = { miscscrn, &info_menu, &system_menu },
[GO_TO_SHORTCUTMENU] = { do_shortcut_menu, NULL, NULL },
};
static const int nb_items = sizeof(items)/sizeof(*items);
static int item_callback(int action, const struct menu_item_ex *this_item) ;
MENUITEM_RETURNVALUE(shortcut_menu, ID2P(LANG_SHORTCUTS), GO_TO_SHORTCUTMENU,
NULL, Icon_Bookmark);
MENUITEM_RETURNVALUE(file_browser, ID2P(LANG_DIR_BROWSER), GO_TO_FILEBROWSER,
NULL, Icon_file_view_menu);
#ifdef HAVE_TAGCACHE
@ -492,6 +497,7 @@ MAKE_MENU(root_menu_, ID2P(LANG_ROCKBOX_TITLE),
#if CONFIG_KEYPAD == PLAYER_PAD
,&do_shutdown_item
#endif
,&shortcut_menu
);
static int item_callback(int action, const struct menu_item_ex *this_item)

View File

@ -58,6 +58,7 @@ enum {
GO_TO_PLAYLISTS_SCREEN,
GO_TO_PLAYLIST_VIEWER,
GO_TO_SYSTEM_SCREEN,
GO_TO_SHORTCUTMENU
};
extern const struct menu_item_ex root_menu_;

421
apps/shortcuts.c Normal file
View File

@ -0,0 +1,421 @@
/***************************************************************************
*
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Jonathan Gordon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdbool.h>
#include <stdlib.h>
#include "config.h"
#include "system.h"
#include "action.h"
#include "ata_idle_notify.h"
#include "debug_menu.h"
#include "core_alloc.h"
#include "list.h"
#include "settings.h"
#include "settings_list.h"
#include "lang.h"
#include "menu.h"
#include "misc.h"
#include "tree.h"
#include "splash.h"
#include "filefuncs.h"
#include "filetypes.h"
#include "shortcuts.h"
#include "onplay.h"
#define MAX_SHORTCUT_NAME 32
#define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt"
char *type_strings[SHORTCUT_TYPE_COUNT] = {
[SHORTCUT_SETTING] = "setting",
[SHORTCUT_FILE] = "file",
[SHORTCUT_DEBUGITEM] = "debug",
[SHORTCUT_BROWSER] = "browse",
[SHORTCUT_PLAYLISTMENU] = "playlist menu",
[SHORTCUT_SEPARATOR] = "separator",
};
struct shortcut {
enum shortcut_type type;
char name[MAX_SHORTCUT_NAME];
int icon;
union {
char path[MAX_PATH];
const struct settings_list *setting;
} u;
};
#define SHORTCUTS_PER_HANDLE 32
struct shortcut_handle {
struct shortcut shortcuts[SHORTCUTS_PER_HANDLE];
int next_handle;
};
static int first_handle = 0;
static int shortcut_count = 0;
static void reset_shortcuts(void)
{
int current_handle = first_handle;
struct shortcut_handle *h = NULL;
while (current_handle > 0)
{
int next;
h = core_get_data(current_handle);
next = h->next_handle;
core_free(current_handle);
current_handle = next;
}
first_handle = 0;
shortcut_count = 0;
}
static struct shortcut* get_shortcut(int index)
{
int handle_count, handle_index;
int current_handle = first_handle;
struct shortcut_handle *h = NULL;
if (first_handle == 0)
{
first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle));
if (first_handle <= 0)
return NULL;
h = core_get_data(first_handle);
h->next_handle = 0;
current_handle = first_handle;
}
handle_count = index/SHORTCUTS_PER_HANDLE + 1;
handle_index = index%SHORTCUTS_PER_HANDLE;
do {
h = core_get_data(current_handle);
current_handle = h->next_handle;
handle_count--;
} while (handle_count > 0 && current_handle > 0);
if (handle_count > 0 && handle_index == 0)
{
char buf[32];
snprintf(buf, sizeof buf, "shortcuts_%d", index/SHORTCUTS_PER_HANDLE);
h->next_handle = core_alloc(buf, sizeof(struct shortcut_handle));
if (h->next_handle <= 0)
return NULL;
h = core_get_data(h->next_handle);
h->next_handle = 0;
}
return &h->shortcuts[handle_index];
}
bool verify_shortcut(struct shortcut* sc)
{
switch (sc->type)
{
case SHORTCUT_UNDEFINED:
return false;
case SHORTCUT_BROWSER:
case SHORTCUT_FILE:
case SHORTCUT_PLAYLISTMENU:
if (sc->u.path[0] == '\0')
return false;
break;
case SHORTCUT_SETTING:
return sc->u.setting != NULL;
case SHORTCUT_DEBUGITEM:
case SHORTCUT_SEPARATOR:
default:
break;
}
return true;
}
static void init_shortcut(struct shortcut* sc)
{
sc->type = SHORTCUT_UNDEFINED;
sc->name[0] = '\0';
sc->u.path[0] = '\0';
sc->icon = Icon_NOICON;
}
static int first_idx_to_writeback = -1;
void shortcuts_ata_idle_callback(void* data)
{
(void)data;
int fd;
char buf[MAX_PATH];
int current_idx = first_idx_to_writeback;
if (first_idx_to_writeback < 0)
return;
fd = open(SHORTCUTS_FILENAME, O_APPEND|O_RDWR|O_CREAT, 0644);
if (fd < 0)
return;
while (current_idx < shortcut_count)
{
struct shortcut* sc = get_shortcut(current_idx++);
char *type;
int len;
if (!sc)
break;
type = type_strings[sc->type];
len = snprintf(buf, MAX_PATH, "[shortcut]\ntype: %s\ndata: ", type);
write(fd, buf, len);
if (sc->type == SHORTCUT_SETTING)
write(fd, sc->u.setting->cfg_name, strlen(sc->u.setting->cfg_name));
else
write(fd, sc->u.path, strlen(sc->u.path));
write(fd, "\n\n", 2);
}
close(fd);
if (first_idx_to_writeback == 0)
{
/* reload all shortcuts because we appended to the shortcuts file which
* has not been read yet.
*/
reset_shortcuts();
shortcuts_init();
}
first_idx_to_writeback = -1;
}
void shortcuts_add(enum shortcut_type type, char* value)
{
struct shortcut* sc = get_shortcut(shortcut_count++);
if (!sc)
return;
init_shortcut(sc);
sc->type = type;
if (type == SHORTCUT_SETTING)
sc->u.setting = (void*)value;
else
strlcpy(sc->u.path, value, MAX_PATH);
if (first_idx_to_writeback < 0)
first_idx_to_writeback = shortcut_count - 1;
register_storage_idle_func(shortcuts_ata_idle_callback);
}
int readline_cb(int n, char *buf, void *parameters)
{
(void)n;
(void)parameters;
struct shortcut **param = (struct shortcut**)parameters;
struct shortcut* sc = *param;
char *name, *value;
if (!strcasecmp(skip_whitespace(buf), "[shortcut]"))
{
if (sc && verify_shortcut(sc))
shortcut_count++;
sc = get_shortcut(shortcut_count);
if (!sc)
return 1;
init_shortcut(sc);
*param = sc;
}
else if (sc && settings_parseline(buf, &name, &value))
{
if (!strcmp(name, "type"))
{
int t = 0;
for (t=0; t<SHORTCUT_TYPE_COUNT && sc->type == SHORTCUT_UNDEFINED; t++)
if (!strcmp(value, type_strings[t]))
sc->type = t;
}
else if (!strcmp(name, "name"))
{
strlcpy(sc->name, value, MAX_SHORTCUT_NAME);
}
else if (!strcmp(name, "data"))
{
switch (sc->type)
{
case SHORTCUT_UNDEFINED:
case SHORTCUT_TYPE_COUNT:
*param = NULL;
break;
case SHORTCUT_BROWSER:
case SHORTCUT_FILE:
case SHORTCUT_DEBUGITEM:
case SHORTCUT_PLAYLISTMENU:
strlcpy(sc->u.path, value, MAX_PATH);
break;
case SHORTCUT_SETTING:
sc->u.setting = find_setting_by_cfgname(value, NULL);
break;
case SHORTCUT_SEPARATOR:
break;
}
}
else if (!strcmp(name, "icon"))
{
if (!strcmp(value, "filetype") && sc->type != SHORTCUT_SETTING && sc->u.path[0])
{
sc->icon = filetype_get_icon(filetype_get_attr(sc->u.path));
}
else
{
sc->icon = atoi(value);
}
}
}
return 0;
}
void shortcuts_init(void)
{
int fd;
char buf[512];
struct shortcut *param = NULL;
struct shortcut_handle *h;
shortcut_count = 0;
fd = open_utf8(SHORTCUTS_FILENAME, O_RDONLY);
if (fd < 0)
return;
first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle));
if (first_handle <= 0)
return;
h = core_get_data(first_handle);
h->next_handle = 0;
fast_readline(fd, buf, sizeof buf, &param, readline_cb);
close(fd);
if (param && verify_shortcut(param))
shortcut_count++;
}
const char * shortcut_menu_get_name(int selected_item, void * data,
char * buffer, size_t buffer_len)
{
(void)data;
(void)buffer;
(void)buffer_len;
struct shortcut *sc = get_shortcut(selected_item);
if (!sc)
return "";
if (sc->type == SHORTCUT_SETTING)
return sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id));
else if (sc->type == SHORTCUT_SEPARATOR)
return sc->name;
return sc->name[0] ? sc->name : sc->u.path;
}
int shortcut_menu_get_action(int action, struct gui_synclist *lists)
{
(void)lists;
if (action == ACTION_STD_OK)
return ACTION_STD_CANCEL;
return action;
}
enum themable_icons shortcut_menu_get_icon(int selected_item, void * data)
{
(void)data;
struct shortcut *sc = get_shortcut(selected_item);
if (!sc)
return Icon_NOICON;
if (sc->icon == Icon_NOICON)
{
switch (sc->type)
{
case SHORTCUT_FILE:
return filetype_get_icon(filetype_get_attr(sc->u.path));
case SHORTCUT_BROWSER:
return Icon_Folder;
case SHORTCUT_SETTING:
return Icon_Menu_setting;
case SHORTCUT_DEBUGITEM:
return Icon_Menu_functioncall;
case SHORTCUT_PLAYLISTMENU:
return Icon_Playlist;
default:
break;
}
}
return sc->icon;
}
int do_shortcut_menu(void *ignored)
{
(void)ignored;
struct simplelist_info list;
struct shortcut *sc;
int done = GO_TO_PREVIOUS;
if (first_handle == 0)
shortcuts_init();
simplelist_info_init(&list, P2STR(ID2P(LANG_SHORTCUTS)), shortcut_count, NULL);
list.get_name = shortcut_menu_get_name;
list.action_callback = shortcut_menu_get_action;
list.get_icon = shortcut_menu_get_icon;
list.title_icon = Icon_Bookmark;
push_current_activity(ACTIVITY_SHORTCUTSMENU);
while (done == GO_TO_PREVIOUS)
{
if (simplelist_show_list(&list))
break; /* some error happened?! */
if (list.selection == -1)
break;
else
{
sc = get_shortcut(list.selection);
if (!sc)
continue;
switch (sc->type)
{
case SHORTCUT_PLAYLISTMENU:
if (!file_exists(sc->u.path))
{
splash(HZ, ID2P(LANG_NO_FILES));
break;
}
else
{
onplay_show_playlist_menu(sc->u.path);
}
break;
case SHORTCUT_FILE:
if (!file_exists(sc->u.path))
{
splash(HZ, ID2P(LANG_NO_FILES));
break;
}
/* else fall through */
case SHORTCUT_BROWSER:
{
struct browse_context browse;
browse_context_init(&browse, global_settings.dirfilter, 0,
NULL, NOICON, sc->u.path, NULL);
if (sc->type == SHORTCUT_FILE)
browse.flags |= BROWSE_RUNFILE;
done = rockbox_browse(&browse);
}
break;
case SHORTCUT_SETTING:
do_setting_screen(sc->u.setting,
sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)),NULL);
break;
case SHORTCUT_DEBUGITEM:
run_debug_screen(sc->u.path);
break;
case SHORTCUT_UNDEFINED:
default:
break;
}
}
}
pop_current_activity();
return done;
}

43
apps/shortcuts.h Normal file
View File

@ -0,0 +1,43 @@
/***************************************************************************
*
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Jonathan Gordon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __SHORTCUTS_H__
#define __SHORTCUTS_H__
#include <stdbool.h>
#include <stdlib.h>
enum shortcut_type {
SHORTCUT_UNDEFINED = -1,
SHORTCUT_SETTING = 0,
SHORTCUT_FILE,
SHORTCUT_DEBUGITEM,
SHORTCUT_BROWSER,
SHORTCUT_PLAYLISTMENU,
SHORTCUT_SEPARATOR,
SHORTCUT_TYPE_COUNT
};
void shortcuts_add(enum shortcut_type type, char* value);
void shortcuts_init(void);
int do_shortcut_menu(void*ignored);
#endif

View File

@ -1000,7 +1000,10 @@ int rockbox_browse(struct browse_context *browse)
tc.browse = browse;
strcpy(current, browse->root);
set_current_file(current);
ret_val = dirbrowse();
if (browse->flags&BROWSE_RUNFILE)
ret_val = ft_enter(&tc);
else
ret_val = dirbrowse();
}
backup_count--;
if (backup_count >= 0)

View File

@ -36,8 +36,10 @@ struct entry {
#define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */
#define BROWSE_NO_CONTEXT_MENU 0x0002 /* disable context menu */
#define BROWSE_RUNFILE 0x0004 /* do ft_open() on the file instead of browsing */
#define BROWSE_SELECTED 0x0100 /* this bit is set if user selected item */
struct tree_context;
struct tree_cache {

View File

@ -265,3 +265,60 @@ pages of information.}
quickscreen, then pressing up and down will cycle through this setting in
opposite directions.
}
\section{\label{ref:MainMenuShortcuts}Shortcuts}
This menu item is a container for user defined shortcuts to files, folders or
settings. The following are valid shortcuts:
\begin{itemize}
\item A file can be ``run'' (i.e. a music file played, plugin started or
a \fname{.cfg} loaded)
\item The file browser can be opened with the cursor positioned at
the specified file or folder
\item A file's or folder's ``Current Playlist'' context menu item can
be displayed
\item Most settings can be configured (any which can be added to the
\setting{Quick Screen})
\item Any debug menu item (useful for developers mostly)
\end{itemize}
\note{Shortcuts into the database are not possible}
Shortcuts are loaded from the file \fname{/.rockbox/shortcuts.txt} which lists
each item to be displayed. Each shortcut looks like the following:
\begin{example}
[shortcut]
type: <specify the shortcut type/action>
data: <what the shortcut actually links to>
name: <what you want the shortcut to be displayed as>
icon: <number of the theme icon to use (see http://www.rockbox.org/wiki/CustomIcons)>
\end{example}
Only ``type'' and ``data'' are required (except if type is ``separator'' in which case
``data'' is also not required).
Available types are:
\begin{description}
\item[file] \config{data} is the filename to run
\item[browse] \config{data} is the file or the folder to open the file browser at
\item[playlist menu] \config{data} is the file or the folder to open the
``Current Playlist'' context menu item on
\item[setting] \config{data} is the config name of the setting you want to change
\item[debug] \config{data} is the name of the debug menu item to display
\item[separator] \config{data} is ignored; name can be used to display text,
or left blank to make the list more accessible with visual gaps
\end{description}
If the name/icon items are not specified a sensible default will be used.
\note{For the ``browse'' type, if you want the file browser to start \emph{inside}
a folder, make sure the data has the trailing slash (i.e \fname{/Music/} instead of
\fname {/Music}). Without the trailing slash, it will cause the file broser to open
with \fname{/Music} selected instead.}
The file \fname{shortcuts.txt} can be edited with any text editor. Most items can
also be added to it through their context menu item ``Add to shortcuts''.
A reboot is needed for manual changes to \fname{shortcuts.txt} to be applied.