Add open_plugin to core

open_plugin allows arbitrary plugins to be called
in hotkey and start screen

replaces PictureFlow Integration
shortcuts menu plays plugins now too

rather than store paths and parameters in the settings
that reside in memory instead entries in a file are searched by hash.
after all, the plugin has to be loaded from disk anyways

----------------------------------------------------------------------------
shortcut_viewer.rock--  can now call plugins rather than taking you to them
in the browser
-----------------------------------------------------------------------------
Added a new option to menus:
 F_CB_ON_SELECT_ONLY
 instead of option callback every time a item is accessed
 F_CB_ON_SELECT_ONLY fires callback only when item is selected
-----------------------------------------------------------------------------
Added manual entries
-----------------------------------------------------------------------------

Change-Id: I078b57b1d2b4dd633c89212c1082fcbc1b516e6a
This commit is contained in:
William Wilgus 2020-07-31 22:45:10 -04:00
parent d553bb1149
commit 3550283442
25 changed files with 540 additions and 93 deletions

View File

@ -38,6 +38,7 @@ menus/sound_menu.c
menus/time_menu.c
#endif
misc.c
open_plugin.c
onplay.c
playlist.c
playlist_catalog.c

View File

@ -357,7 +357,8 @@ int ft_load(struct tree_context* c, const char* tempdir)
(*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) ||
(*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) ||
(*c->dirfilter == SHOW_PLUGINS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_ROCK &&
(dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA) ||
(dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA &&
(dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_OPX) ||
(callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c)))
{
continue;
@ -625,6 +626,7 @@ int ft_enter(struct tree_context* c)
/* plugin file */
case FILE_ATTR_ROCK:
case FILE_ATTR_LUA:
case FILE_ATTR_OPX:
{
char *plugin = buf, *argument = NULL, lua_path[MAX_PATH];
int ret;
@ -634,6 +636,11 @@ int ft_enter(struct tree_context* c)
plugin = lua_path;
argument = buf;
}
else if ((file_attr & FILE_ATTR_MASK) == FILE_ATTR_OPX) {
snprintf(lua_path, sizeof(lua_path)-1, "%s/open_plugins.rock", VIEWERS_DIR); /* Use a #define here ? */
plugin = lua_path;
argument = buf;
}
if (global_settings.party_mode && audio_status()) {
splash(HZ, ID2P(LANG_PARTY_MODE));
@ -645,6 +652,9 @@ int ft_enter(struct tree_context* c)
case PLUGIN_GOTO_WPS:
play = true;
break;
case PLUGIN_GOTO_PLUGIN:
rc = GO_TO_PLUGIN;
break;
case PLUGIN_USB_CONNECTED:
if(*c->dirfilter > NUM_FILTER_MODES)
/* leave sub-browsers after usb, doing
@ -690,6 +700,9 @@ int ft_enter(struct tree_context* c)
case PLUGIN_USB_CONNECTED:
rc = GO_TO_FILEBROWSER;
break;
case PLUGIN_GOTO_PLUGIN:
rc = GO_TO_PLUGIN;
break;
case PLUGIN_GOTO_WPS:
rc = GO_TO_WPS;
break;

View File

@ -125,6 +125,7 @@ static const struct filetype inbuilt_filetypes[] = {
{ "lng", FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE },
{ "rock",FILE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK },
{ "lua", FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK },
{ "opx", FILE_ATTR_OPX, Icon_Plugin, VOICE_EXT_ROCK },
{ "fnt", FILE_ATTR_FONT,Icon_Font, VOICE_EXT_FONT },
{ "kbd", FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD },
{ "bmark",FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK },

View File

@ -47,6 +47,7 @@
#define FILE_ATTR_LUA 0x1100 /* Lua rockbox plugin */
#define FILE_ATTR_FMS 0x1200 /* FM screen skin file */
#define FILE_ATTR_RFMS 0x1300 /* FM screen skin file */
#define FILE_ATTR_OPX 0x1400 /* open plugins shortcut */
#define FILE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */
struct filetype {

View File

@ -467,6 +467,8 @@ bool option_screen(const struct settings_list *setting,
int oldvalue, nb_items = 0, selected = 0, temp_var;
int *variable;
bool allow_wrap = setting->flags & F_NO_WRAP ? false : true;
bool cb_on_select_only =
((setting->flags & F_CB_ON_SELECT_ONLY) == F_CB_ON_SELECT_ONLY);
int var_type = setting->flags&F_T_MASK;
void (*function)(int) = NULL;
char *title;
@ -554,12 +556,15 @@ bool option_screen(const struct settings_list *setting,
}
settings_save();
done = true;
if (cb_on_select_only && function)
function(*variable);
}
else if(default_event_handler(action) == SYS_USB_CONNECTED)
return true;
/* callback */
if ( function )
if (function && !cb_on_select_only)
function(*variable);
/* if the volume is changing we need to let the skins know */
if (function == sound_get_fn(SOUND_VOLUME))
global_status.last_volume_change = current_tick;

View File

@ -687,10 +687,8 @@ long gui_wps_show(void)
return GO_TO_ROOT;
else if (retval == ONPLAY_PLAYLIST)
return GO_TO_PLAYLIST_VIEWER;
#ifdef HAVE_PICTUREFLOW_INTEGRATION
else if (retval == ONPLAY_PICTUREFLOW)
return GO_TO_PICTUREFLOW;
#endif
else if (retval == ONPLAY_PLUGIN)
return GO_TO_PLUGIN;
restore = true;
}
break;

View File

@ -16150,3 +16150,59 @@
hotkey: "Hold for settings"
</voice>
</phrase>
<phrase>
id: LANG_OPEN_PLUGIN
desc: onplay open plugin
user: core
<source>
*: "Open Plugin"
</source>
<dest>
*: "Open Plugin"
</dest>
<voice>
*: "Open Plugin"
</voice>
</phrase>
<phrase>
id: LANG_OPEN_PLUGIN_NOT_A_PLUGIN
desc: open plugin module
user: core
<source>
*: "Not a plugin: %s"
</source>
<dest>
*: "Not a plugin: %s"
</dest>
<voice>
*: "Not a plugin"
</voice>
</phrase>
<phrase>
id: LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN
desc: open plugin module
user: core
<source>
*: "Set Wps Context Plugin"
</source>
<dest>
*: "Set Wps Context Plugin"
</dest>
<voice>
*: "Set Wps Context Plugin"
</voice>
</phrase>
<phrase>
id: LANG_PARAMETER
desc:
user: core
<source>
*: "Parameter"
</source>
<dest>
*: "Parameter"
</dest>
<voice>
*: "Parameter"
</voice>
</phrase>

View File

@ -28,6 +28,7 @@
#include "action.h"
#include "settings.h"
#include "menu.h"
#include "open_plugin.h"
#include "keyboard.h"
#include "sound_menu.h"
#include "exported_menus.h"
@ -711,6 +712,18 @@ MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
/* VOICE MENU */
/***********************************/
/* WPS_CONTEXT_PLUGIN */
/***********************************/
static void wps_plugin_cb(void)
{
open_plugin_browse(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN));
}
MENUITEM_FUNCTION(wps_set_context_plugin, 0,
ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN),
wps_plugin_cb, NULL, NULL, Icon_Plugin);
/* WPS_CONTEXT_PLUGIN */
/***********************************/
/***********************************/
/* HOTKEY MENU */
@ -745,6 +758,7 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
&autoresume_menu,
#endif
&browse_langs, &voice_settings_menu,
&wps_set_context_plugin,
#ifdef HAVE_HOTKEY
&hotkey_menu,
#endif

View File

@ -43,6 +43,7 @@
#include "talk.h"
#include "onplay.h"
#include "filetypes.h"
#include "open_plugin.h"
#include "plugin.h"
#include "bookmark.h"
#include "action.h"
@ -1415,10 +1416,8 @@ MENUITEM_FUNCTION(rating_item, 0, ID2P(LANG_MENU_SET_RATING),
set_rating_inline, NULL,
ratingitem_callback, Icon_Questionmark);
#endif
#ifdef HAVE_PICTUREFLOW_INTEGRATION
MENUITEM_RETURNVALUE(pictureflow_item, ID2P(LANG_ONPLAY_PICTUREFLOW),
GO_TO_PICTUREFLOW, NULL, Icon_NOICON);
#endif
MENUITEM_RETURNVALUE(plugin_item, ID2P(LANG_OPEN_PLUGIN),
GO_TO_PLUGIN, NULL, Icon_Plugin);
static bool view_cue(void)
{
@ -1650,9 +1649,7 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
&rating_item,
#endif
&bookmark_menu,
#ifdef HAVE_PICTUREFLOW_INTEGRATION
&pictureflow_item,
#endif
&plugin_item,
&browse_id3_item, &list_viewers_item,
&delete_file_item, &view_cue_item,
#ifdef HAVE_PITCHCONTROL
@ -1732,6 +1729,11 @@ static int playlist_insert_shuffled(void)
return ONPLAY_RELOAD_DIR;
}
static void hotkey_run_plugin(void)
{
open_plugin_run(ID2P(LANG_HOTKEY_WPS));
}
struct hotkey_assignment {
int action; /* hotkey_action */
int lang_id; /* Language ID */
@ -1768,11 +1770,9 @@ static struct hotkey_assignment hotkey_items[] = {
{ HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
HOTKEY_FUNC(playlist_insert_shuffled, NULL),
ONPLAY_RELOAD_DIR },
#ifdef HAVE_PICTUREFLOW_INTEGRATION
{ HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW,
HOTKEY_FUNC(NULL, NULL),
ONPLAY_PICTUREFLOW },
#endif
{ HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
HOTKEY_FUNC(hotkey_run_plugin, NULL),
ONPLAY_OK },
{ HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
HOTKEY_FUNC(bookmark_create_menu, NULL),
ONPLAY_OK },
@ -1861,10 +1861,8 @@ int onplay(char* file, int attr, int from, bool hotkey)
return ONPLAY_MAINMENU;
case GO_TO_PLAYLIST_VIEWER:
return ONPLAY_PLAYLIST;
#ifdef HAVE_PICTUREFLOW_INTEGRATION
case GO_TO_PICTUREFLOW:
return ONPLAY_PICTUREFLOW;
#endif
case GO_TO_PLUGIN:
return ONPLAY_PLUGIN;
default:
return onplay_result;
}

View File

@ -29,7 +29,7 @@ enum {
ONPLAY_RELOAD_DIR,
ONPLAY_START_PLAY,
ONPLAY_PLAYLIST,
ONPLAY_PICTUREFLOW,
ONPLAY_PLUGIN,
};
#ifdef HAVE_HOTKEY
@ -44,7 +44,7 @@ enum hotkey_action {
HOTKEY_DELETE,
HOTKEY_INSERT,
HOTKEY_INSERT_SHUFFLED,
HOTKEY_PICTUREFLOW,
HOTKEY_PLUGIN,
HOTKEY_BOOKMARK,
};
#endif

204
apps/open_plugin.c Normal file
View File

@ -0,0 +1,204 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2020 by William Wilgus
*
* 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 __PCTOOL__
#include "plugin.h"
#include "open_plugin.h"
#include "pathfuncs.h"
#include "keyboard.h"
#include "splash.h"
#include "lang.h"
struct open_plugin_entry_t open_plugin_entry;
static const int op_entry_sz = sizeof(struct open_plugin_entry_t);
static void get_param(void)
{
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
strlcpy(tmp_buf, open_plugin_entry.param, OPEN_PLUGIN_BUFSZ);
if (kbd_input(tmp_buf, OPEN_PLUGIN_BUFSZ, NULL))
strlcpy(open_plugin_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
}
uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter)
{
int len;
uint32_t hash;
char *pos;
int fd = 0;
/*strlcpy(plug_entry.key, key, sizeof(plug_entry.key));*/
open_plugin_entry.lang_id = P2ID((unsigned char*)key);
key = P2STR((unsigned char *)key);
open_plugin_get_hash(key, &hash);
open_plugin_entry.hash = hash;
if (plugin)
{
/* name */
if (path_basename(plugin, (const char **)&pos) == 0)
pos = "\0";
len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ);
if(len > 5 && strcasecmp(&(pos[len-5]), ".rock") == 0)
{
fd = open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (!fd)
return 0;
/* path */
strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
if(parameter)
{
if (parameter[0] == '\0' &&
yesno_pop(ID2P(LANG_PARAMETER)))
{
get_param();
}
else
strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
}
write(fd, &open_plugin_entry, op_entry_sz);
}
else
{
if (open_plugin_entry.lang_id != LANG_SHORTCUTS)
splashf(HZ / 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos);
return 0;
}
}
int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY);
if (fd1)
{
while (read(fd1, &open_plugin_entry, op_entry_sz) == op_entry_sz)
{
if (open_plugin_entry.hash != hash)
write(fd, &open_plugin_entry, op_entry_sz);
}
close(fd1);
}
close(fd);
if(fd1)
{
remove(OPEN_PLUGIN_DAT);
rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
}
else
hash = 0;
return hash;
}
void open_plugin_browse(const char *key)
{
struct browse_context browse;
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
open_plugin_get_entry(key, &open_plugin_entry);
if (open_plugin_entry.path[0] == '\0')
strcpy(open_plugin_entry.path, PLUGIN_DIR"/");
browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "",
Icon_Plugin, open_plugin_entry.path, NULL);
browse.buf = tmp_buf;
browse.bufsize = OPEN_PLUGIN_BUFSZ;
if (rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
open_plugin_add_path(key, tmp_buf, NULL);
}
}
void open_plugin_remove(const char *key)
{
(void)key;
open_plugin_add_path(key, NULL, NULL);
}
static int open_plugin_hash_get_entry(uint32_t hash, struct open_plugin_entry_t *entry)
{
int ret = -1, record = -1;
if (entry)
{
int fd = open(OPEN_PLUGIN_DAT, O_RDONLY);
if (fd)
{
while (read(fd, entry, op_entry_sz) == op_entry_sz)
{
record++;
if (entry->hash == hash)
{
ret = record;
break;
}
}
close(fd);
}
if (ret < 0)
{
memset(entry, 0, op_entry_sz);
entry->lang_id = -1;
}
}
return ret;
}
int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry)
{
uint32_t hash;
key = P2STR((unsigned char *)key);
open_plugin_get_hash(key, &hash);
return open_plugin_hash_get_entry(hash, entry);
}
int open_plugin_run(const char *key)
{
int ret = 0;
const char *path;
const char *param;
open_plugin_get_entry(key, &open_plugin_entry);
path = open_plugin_entry.path;
param = open_plugin_entry.param;
if (param[0] == '\0')
param = NULL;
if (path)
ret = plugin_load(path, param);
return ret;
}
#endif /* ndef __PCTOOL__ */

66
apps/open_plugin.h Normal file
View File

@ -0,0 +1,66 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2020 by William Wilgus
*
* 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 OPEN_PLUGIN_H
#define OPEN_PLUGIN_H
/* Open_plugin module
* OP stores and retrieves plugin path and parameters by key
* from a dictionary file
*
* plugins can load other plugins
* return rb->plugin_open(path, parameter);
*/
#ifndef __PCTOOL__
/* open_plugin path lookup */
#define OPEN_PLUGIN_DAT PLUGIN_DIR "/plugin.dat"
#define OPEN_PLUGIN_BUFSZ MAX_PATH
#define OPEN_PLUGIN_NAMESZ 32
struct open_plugin_entry_t
{
uint32_t hash;
int32_t lang_id;
char name[OPEN_PLUGIN_NAMESZ+1];
/*char key[OPEN_PLUGIN_BUFSZ+1];*/
char path[OPEN_PLUGIN_BUFSZ+1];
char param[OPEN_PLUGIN_BUFSZ+1];
};
inline static void open_plugin_get_hash(const char *key, uint32_t *hash)
{
/* Calculate modified FNV1a hash of string */
const uint32_t p = 16777619;
*hash = 0x811C9DC5; //seed, 2166136261;
while(*key)
*hash = (*key++ ^ *hash) * p;
}
#ifndef PLUGIN
extern struct open_plugin_entry_t open_plugin_entry;
uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter);
int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry);
void open_plugin_browse(const char *key);
void open_plugin_remove(const char *key);
int open_plugin_run(const char *key);
#endif
#endif /*ndef __PCTOOL__ */
#endif /* OPEN_PLUGIN_H */

View File

@ -21,6 +21,7 @@
#define DIRFUNCTIONS_DEFINED
#define FILEFUNCTIONS_DEFINED
#include "plugin.h"
#include "open_plugin.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
@ -807,6 +808,7 @@ static const struct plugin_api rockbox_api = {
#ifdef HAVE_TAGCACHE
tagcache_get_stat,
#endif
plugin_open,
};
static int plugin_buffer_handle;
@ -1019,6 +1021,12 @@ static void plugin_tsr(bool (*exit_callback)(bool))
pfn_tsr_exit = exit_callback; /* remember the callback for later */
}
int plugin_open(char *plugin, char *parameter)
{
open_plugin_add_path(ID2P(LANG_OPEN_PLUGIN), plugin, parameter);
return PLUGIN_GOTO_PLUGIN;
}
char *plugin_get_current_filename(void)
{
return current_plugin;

View File

@ -49,6 +49,7 @@
char* strncpy(char *, const char *, size_t);
void* plugin_get_buffer(size_t *buffer_size);
int plugin_open(char *plugin, char *parameter);
#ifndef __PCTOOL__
#include "config.h"
@ -172,6 +173,7 @@ enum plugin_status {
PLUGIN_USB_CONNECTED = INTERNAL_PLUGIN_RETVAL_START,
PLUGIN_POWEROFF,
PLUGIN_GOTO_WPS,
PLUGIN_GOTO_PLUGIN,
PLUGIN_ERROR = -1,
};
@ -934,6 +936,7 @@ struct plugin_api {
#ifdef HAVE_TAGCACHE
struct tagcache_stat* (*tagcache_get_stat)(void);
#endif
int (*plugin_open)(char *path, char *parameter);
};

View File

@ -533,19 +533,28 @@ static void free_all_slide_prio(int prio);
static bool check_database(bool prompt)
{
bool needwarn = true;
int spin = 5;
struct tagcache_stat *stat = rb->tagcache_get_stat();
while ( !(stat->initialized && stat->ready) )
{
if (needwarn)
if (--spin > 0)
{
rb->sleep(HZ/5);
}
else if (needwarn)
{
needwarn = false;
rb->splash(0, ID2P(LANG_TAGCACHE_BUSY));
if (!prompt)
}
else if (!prompt)
return false;
else if (rb->action_userabort(HZ/5))
return false;
needwarn = false;
stat = rb->tagcache_get_stat();
rb->yield();
stat = rb->tagcache_get_stat();
}
return true;
}
@ -3841,7 +3850,7 @@ enum plugin_status plugin_start(const void *parameter)
void * buf;
size_t buf_size;
bool prompt = (parameter && ((char *) parameter)[0] == ACTIVITY_MAINMENU);
bool prompt = (parameter && (((char *) parameter)[0] == ACTIVITY_MAINMENU));
if (!check_database(prompt))
{

View File

@ -22,7 +22,7 @@
#include "shortcuts.h"
#define LOOP_EXIT 1
enum sc_list_action_type
{
@ -35,7 +35,6 @@ enum sc_list_action_type
static char *link_filename;
static bool user_file;
static bool usb_connected = false;
enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc);
@ -43,10 +42,10 @@ enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc);
static const char* build_sc_list(int selected_item, void *data,
char *buffer, size_t buffer_len);
/* Returns true iff we should leave the main loop */
bool list_sc(void);
/* Returns LOOP_EXIT iff we should leave the main loop */
int list_sc(void);
bool goto_entry(char *file_or_dir);
int goto_entry(char *file_or_dir);
bool ends_with(char *str, char *suffix);
@ -104,7 +103,7 @@ static const char* build_sc_list(int selected_item, void *data,
}
bool list_sc(void)
int list_sc(void)
{
int selected_item = 0;
enum sc_list_action_type action = SCLA_NONE;
@ -122,8 +121,7 @@ bool list_sc(void)
/* Draw the prepared widget to the LCD now */
action = draw_sc_list(&gui_sc);
if (action == SCLA_USB) {
usb_connected = true;
return true;
return PLUGIN_USB_CONNECTED;
}
/* which item do we action? */
@ -132,7 +130,7 @@ bool list_sc(void)
if (!is_valid_index(&sc_file, selected_item)) {
/* This should never happen */
rb->splash(HZ*2, "Bad entry selected!");
return true;
return PLUGIN_ERROR;
}
/* perform the following actions if the user "selected"
@ -145,13 +143,13 @@ bool list_sc(void)
rb->splashf(HZ, "Deleting %s", sc_file.entries[selected_item].disp);
remove_entry(&sc_file, selected_item);
dump_sc_file(&sc_file, link_filename);
return (sc_file.entry_cnt == 0);
return (sc_file.entry_cnt == 0)? LOOP_EXIT : PLUGIN_OK;
default:
return true;
return LOOP_EXIT;
}
}
#if 0
bool goto_entry(char *file_or_dir)
{
DEBUGF("Trying to go to '%s'...\n", file_or_dir);
@ -181,7 +179,46 @@ bool goto_entry(char *file_or_dir)
rb->set_current_file(file_or_dir);
return true;
}
#endif
int goto_entry(char *file_or_dir)
{
DEBUGF("Trying to go to '%s'...\n", file_or_dir);
bool is_dir = ends_with(file_or_dir, PATH_SEPARATOR);
bool exists;
char *what;
if (is_dir) {
what = "Directory";
exists = rb->dir_exists(file_or_dir);
} else {
what = "File";
exists = rb->file_exists(file_or_dir);
}
if (!exists) {
rb->splashf(HZ*2, "%s %s no longer exists on disk", what, file_or_dir);
return PLUGIN_ERROR;
}
int len = rb->strlen(file_or_dir);
if(!is_dir && len > 5 && rb->strcasecmp(&(file_or_dir[len-5]), ".rock") == 0)
{
return rb->plugin_open(file_or_dir, NULL);
}
else
{
/* Set the browsers dirfilter to the global setting
* This is required in case the plugin was launched
* from the plugins browser, in which case the
* dirfilter is set to only display .rock files */
rb->set_dirfilter(rb->global_settings->dirfilter);
/* Change directory to the entry selected by the user */
rb->set_current_file(file_or_dir);
}
return PLUGIN_OK;
}
bool ends_with(char *string, char *suffix)
{
@ -195,7 +232,7 @@ bool ends_with(char *string, char *suffix)
enum plugin_status plugin_start(const void* void_parameter)
{
bool leave_loop;
int ret;
/* This is a viewer, so a parameter must have been specified */
if (void_parameter == NULL) {
@ -219,8 +256,7 @@ enum plugin_status plugin_start(const void* void_parameter)
/* if there's only one entry in the user .link file,
* go straight to it without displaying the menu
* thus allowing 'quick links' */
goto_entry(sc_file.entries[0].path);
return PLUGIN_OK;
return goto_entry(sc_file.entries[0].path);
}
FOR_NB_SCREENS(i)
@ -228,11 +264,13 @@ enum plugin_status plugin_start(const void* void_parameter)
do {
/* Display a menu to choose between the entries */
leave_loop = list_sc();
} while (!leave_loop);
ret = list_sc();
} while (ret == PLUGIN_OK);
if (ret == LOOP_EXIT)
ret = PLUGIN_OK;
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_undo(i, false);
return usb_connected ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
return ret;
}

View File

@ -32,6 +32,7 @@
#include "kernel.h"
#include "debug.h"
#include "misc.h"
#include "open_plugin.h"
#include "rolo.h"
#include "powermgmt.h"
#include "power.h"
@ -347,6 +348,7 @@ static int miscscrn(void * param)
int result = do_menu(menu, NULL, NULL, false);
switch (result)
{
case GO_TO_PLUGIN:
case GO_TO_PLAYLIST_VIEWER:
case GO_TO_WPS:
return result;
@ -703,7 +705,6 @@ static int load_context_screen(int selection)
return retval;
}
#ifdef HAVE_PICTUREFLOW_INTEGRATION
static int load_plugin_screen(char *plug_path, void* plug_param)
{
int ret_val;
@ -717,6 +718,9 @@ static int load_plugin_screen(char *plug_path, void* plug_param)
case PLUGIN_GOTO_WPS:
ret_val = GO_TO_WPS;
break;
case PLUGIN_GOTO_PLUGIN:
ret_val = GO_TO_PLUGIN;
break;
case PLUGIN_OK:
ret_val = audio_status() ? GO_TO_PREVIOUS : GO_TO_ROOT;
break;
@ -729,7 +733,6 @@ static int load_plugin_screen(char *plug_path, void* plug_param)
last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous;
return ret_val;
}
#endif
void root_menu(void)
{
@ -807,21 +810,36 @@ void root_menu(void)
case GO_TO_ROOTITEM_CONTEXT:
next_screen = load_context_screen(selected);
break;
#ifdef HAVE_PICTUREFLOW_INTEGRATION
case GO_TO_PICTUREFLOW:
case GO_TO_PLUGIN:
{
char pf_path[MAX_PATH];
char activity[6];/* big enough to display int */
snprintf(activity, sizeof(activity), "%d", get_current_activity());
snprintf(pf_path, sizeof(pf_path),
"%s/pictureflow.rock",
PLUGIN_DEMOS_DIR);
next_screen = load_plugin_screen(pf_path, &activity);
previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PICTUREFLOW;
char *key;
switch (last_screen)
{
case GO_TO_ROOT:
key = ID2P(LANG_START_SCREEN);
break;
case GO_TO_WPS:
key = ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN);
break;
case GO_TO_SHORTCUTMENU:
key = ID2P(LANG_SHORTCUTS);
break;
default:
key = ID2P(LANG_OPEN_PLUGIN);
break;
}
open_plugin_get_entry(key, &open_plugin_entry);
char *path = open_plugin_entry.path;
char *param = open_plugin_entry.param;
if (param[0] == '\0')
param = NULL;
next_screen = load_plugin_screen(path, param);
previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PLUGIN;
break;
}
#endif
default:
#ifdef HAVE_TAGCACHE
/* With !HAVE_TAGCACHE previous_browser is always GO_TO_FILEBROWSER */

View File

@ -55,7 +55,7 @@ enum {
GO_TO_FM,
#endif
GO_TO_RECENTBMARKS,
GO_TO_PICTUREFLOW,
GO_TO_PLUGIN,
/* Do Not add any items above here unless you want it to be able to
be the "start screen" after a boot up. The setting in settings_list.c
will need editing if this is the case. */

View File

@ -38,6 +38,7 @@
#include "power.h"
#include "powermgmt.h"
#include "kernel.h"
#include "open_plugin.h"
#ifdef HAVE_REMOTE_LCD
#include "lcd-remote.h"
#endif
@ -680,6 +681,11 @@ static void tsc_set_default(void* setting, void* defaultval)
}
#endif
#ifdef HAVE_HOTKEY
static void hotkey_callback(int var)
{
if (get_hotkey_lang_id(var) == LANG_OPEN_PLUGIN)
open_plugin_browse(ID2P(LANG_HOTKEY_WPS));
}
static const char* hotkey_formatter(char* buffer, size_t buffer_size, int value,
const char* unit)
{
@ -695,6 +701,12 @@ static int32_t hotkey_getlang(int value, int unit)
}
#endif /* HAVE_HOTKEY */
static void start_in_callback(int var)
{
if (var - 2 == GO_TO_PLUGIN)
open_plugin_browse(ID2P(LANG_START_SCREEN));
}
/* volume limiter */
static void volume_limit_load_from_cfg(void* var, char*value)
{
@ -1872,7 +1884,7 @@ const struct settings_list settings[] = {
UNIT_SEC, formatter_time_unit_0_is_skip_track,
getlang_time_unit_0_is_skip_track, NULL,
25, timeout_sec_common),
CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1,
CHOICE_SETTING(F_CB_ON_SELECT_ONLY, start_in_screen, LANG_START_SCREEN, 1,
"start in screen", "previous,root,files,"
#ifdef HAVE_TAGCACHE
#define START_DB_COUNT 1
@ -1893,15 +1905,10 @@ const struct settings_list settings[] = {
#else
#define START_TUNER_COUNT 0
#endif
"bookmarks"
#ifdef HAVE_PICTUREFLOW_INTEGRATION
#define START_PF_COUNT 1
",pictureflow"
#else
#define START_PF_COUNT 0
#endif
, NULL,
(6 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT + START_PF_COUNT),
"bookmarks,"
"plugin"
, start_in_callback,
(7 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT),
ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU),
ID2P(LANG_DIR_BROWSER),
#ifdef HAVE_TAGCACHE
@ -1914,10 +1921,8 @@ const struct settings_list settings[] = {
#if CONFIG_TUNER
ID2P(LANG_FM_RADIO),
#endif
ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS)
#ifdef HAVE_PICTUREFLOW_INTEGRATION
,ID2P(LANG_ONPLAY_PICTUREFLOW)
#endif
ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS),
ID2P(LANG_OPEN_PLUGIN)
),
SYSTEM_SETTING(NVRAM(1),last_screen,-1),
#if defined(HAVE_RTC_ALARM) && \
@ -2098,25 +2103,12 @@ const struct settings_list settings[] = {
#endif
#ifdef HAVE_HOTKEY
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_wps,
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS | F_CB_ON_SELECT_ONLY, hotkey_wps,
LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps",
"off,view playlist,show track info,pitchscreen,open with,delete,bookmark"
#ifdef HAVE_PICTUREFLOW_INTEGRATION
",pictureflow"
#endif
,UNIT_INT, hotkey_formatter, hotkey_getlang, NULL,
#ifdef HAVE_PICTUREFLOW_INTEGRATION
8,
#else
7,
#endif
HOTKEY_OFF,
"off,view playlist,show track info,pitchscreen,open with,delete,bookmark,plugin"
,UNIT_INT, hotkey_formatter, hotkey_getlang, hotkey_callback,8, HOTKEY_OFF,
HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN,
HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK
#ifdef HAVE_PICTUREFLOW_INTEGRATION
, HOTKEY_PICTUREFLOW
#endif
),
HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK, HOTKEY_PLUGIN),
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree,
LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree",
"off,open with,delete,insert,insert shuffled",

View File

@ -100,6 +100,7 @@ struct table_setting {
};
#define F_TABLE_SETTING 0x2000
#define F_ALLOW_ARBITRARY_VALS 0x4000
#define F_CB_ON_SELECT_ONLY 0x20000
/* these use the _isfunc_type type for the function */
/* typedef int (*_isfunc_type)(void); */
#define F_MIN_ISFUNC 0x100000 /* min(above) is function pointer to above type */

View File

@ -36,6 +36,7 @@
#include "lang.h"
#include "menu.h"
#include "misc.h"
#include "open_plugin.h"
#include "tree.h"
#include "splash.h"
#include "pathfuncs.h"
@ -608,6 +609,12 @@ int do_shortcut_menu(void *ignored)
/* else fall through */
case SHORTCUT_BROWSER:
{
if(open_plugin_add_path(ID2P(LANG_SHORTCUTS), sc->u.path, NULL) != 0)
{
done = GO_TO_PLUGIN;
break;
}
struct browse_context browse;
browse_context_init(&browse, global_settings.dirfilter, 0,
NULL, NOICON, sc->u.path, NULL);

View File

@ -676,6 +676,8 @@ static int dirbrowse(void)
#endif
{
case GO_TO_FILEBROWSER: reload_dir = true; break;
case GO_TO_PLUGIN:
return GO_TO_PLUGIN;
case GO_TO_WPS:
return GO_TO_WPS;
#if CONFIG_TUNER

View File

@ -36,6 +36,12 @@ This configuration entry can only be created and edited with a text editor or
the Main Menu Config Plugin (see \reference{ref:main_menu_config}).
It is not possible to change this setting via the settings menu.
\subsection{\label{ref:OpenPlugins}Open Plugin Menu Items}
Rockbox allows you to choose a plugin to run for select menu options.
Simply choose the option in the setting menu and choose the plugin
you would like to run.
\opt{lcd_bitmap}{
\subsection{\label{ref:GettingExtras}Getting Extras}

View File

@ -21,6 +21,7 @@
}}
\input{configure_rockbox/language.tex}
\input{configure_rockbox/voice.tex}
\input{configure_rockbox/wps_context_plugin.tex}
\input{configure_rockbox/hotkey_settings.tex}
\chapter{Theme Settings}

View File

@ -0,0 +1,5 @@
\section{\label{ref:SetWPSContextPlugin}Set WPS Context Plugin}
\begin{description}
{This option will allow you to run a rockbox plugin from the WPS context menu}
\end{description}