summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2020-07-31 22:45:10 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2020-08-17 10:15:14 -0400
commit35502834423049b319fde41ff305b48de67d2d51 (patch)
tree00d638d9348cd38f15cf6d341e700bc36153b3f8
parentd553bb1149800daf16dcb92bc0608fe6248e1dab (diff)
downloadrockbox-35502834423049b319fde41ff305b48de67d2d51.tar.gz
rockbox-35502834423049b319fde41ff305b48de67d2d51.zip
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
-rw-r--r--apps/SOURCES1
-rw-r--r--apps/filetree.c15
-rw-r--r--apps/filetypes.c1
-rw-r--r--apps/filetypes.h1
-rw-r--r--apps/gui/option_select.c7
-rw-r--r--apps/gui/wps.c6
-rw-r--r--apps/lang/english.lang56
-rw-r--r--apps/menus/settings_menu.c14
-rw-r--r--apps/onplay.c30
-rw-r--r--apps/onplay.h4
-rw-r--r--apps/open_plugin.c204
-rw-r--r--apps/open_plugin.h66
-rw-r--r--apps/plugin.c8
-rw-r--r--apps/plugin.h3
-rw-r--r--apps/plugins/pictureflow/pictureflow.c19
-rw-r--r--apps/plugins/shortcuts/shortcuts_view.c74
-rw-r--r--apps/root_menu.c46
-rw-r--r--apps/root_menu.h2
-rw-r--r--apps/settings_list.c54
-rw-r--r--apps/settings_list.h1
-rw-r--r--apps/shortcuts.c7
-rw-r--r--apps/tree.c2
-rwxr-xr-xmanual/advanced_topics/main.tex6
-rw-r--r--manual/configure_rockbox/main.tex1
-rw-r--r--manual/configure_rockbox/wps_context_plugin.tex5
25 files changed, 540 insertions, 93 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 5335258f70..ba36bc3ef6 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -38,6 +38,7 @@ menus/sound_menu.c
38menus/time_menu.c 38menus/time_menu.c
39#endif 39#endif
40misc.c 40misc.c
41open_plugin.c
41onplay.c 42onplay.c
42playlist.c 43playlist.c
43playlist_catalog.c 44playlist_catalog.c
diff --git a/apps/filetree.c b/apps/filetree.c
index d645b7225c..cfa14f86b5 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -357,7 +357,8 @@ int ft_load(struct tree_context* c, const char* tempdir)
357 (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) || 357 (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) ||
358 (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) || 358 (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) ||
359 (*c->dirfilter == SHOW_PLUGINS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_ROCK && 359 (*c->dirfilter == SHOW_PLUGINS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_ROCK &&
360 (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA) || 360 (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA &&
361 (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_OPX) ||
361 (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c))) 362 (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c)))
362 { 363 {
363 continue; 364 continue;
@@ -625,6 +626,7 @@ int ft_enter(struct tree_context* c)
625 /* plugin file */ 626 /* plugin file */
626 case FILE_ATTR_ROCK: 627 case FILE_ATTR_ROCK:
627 case FILE_ATTR_LUA: 628 case FILE_ATTR_LUA:
629 case FILE_ATTR_OPX:
628 { 630 {
629 char *plugin = buf, *argument = NULL, lua_path[MAX_PATH]; 631 char *plugin = buf, *argument = NULL, lua_path[MAX_PATH];
630 int ret; 632 int ret;
@@ -634,6 +636,11 @@ int ft_enter(struct tree_context* c)
634 plugin = lua_path; 636 plugin = lua_path;
635 argument = buf; 637 argument = buf;
636 } 638 }
639 else if ((file_attr & FILE_ATTR_MASK) == FILE_ATTR_OPX) {
640 snprintf(lua_path, sizeof(lua_path)-1, "%s/open_plugins.rock", VIEWERS_DIR); /* Use a #define here ? */
641 plugin = lua_path;
642 argument = buf;
643 }
637 644
638 if (global_settings.party_mode && audio_status()) { 645 if (global_settings.party_mode && audio_status()) {
639 splash(HZ, ID2P(LANG_PARTY_MODE)); 646 splash(HZ, ID2P(LANG_PARTY_MODE));
@@ -645,6 +652,9 @@ int ft_enter(struct tree_context* c)
645 case PLUGIN_GOTO_WPS: 652 case PLUGIN_GOTO_WPS:
646 play = true; 653 play = true;
647 break; 654 break;
655 case PLUGIN_GOTO_PLUGIN:
656 rc = GO_TO_PLUGIN;
657 break;
648 case PLUGIN_USB_CONNECTED: 658 case PLUGIN_USB_CONNECTED:
649 if(*c->dirfilter > NUM_FILTER_MODES) 659 if(*c->dirfilter > NUM_FILTER_MODES)
650 /* leave sub-browsers after usb, doing 660 /* leave sub-browsers after usb, doing
@@ -690,6 +700,9 @@ int ft_enter(struct tree_context* c)
690 case PLUGIN_USB_CONNECTED: 700 case PLUGIN_USB_CONNECTED:
691 rc = GO_TO_FILEBROWSER; 701 rc = GO_TO_FILEBROWSER;
692 break; 702 break;
703 case PLUGIN_GOTO_PLUGIN:
704 rc = GO_TO_PLUGIN;
705 break;
693 case PLUGIN_GOTO_WPS: 706 case PLUGIN_GOTO_WPS:
694 rc = GO_TO_WPS; 707 rc = GO_TO_WPS;
695 break; 708 break;
diff --git a/apps/filetypes.c b/apps/filetypes.c
index 39fb2c5b32..391412b172 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -125,6 +125,7 @@ static const struct filetype inbuilt_filetypes[] = {
125 { "lng", FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE }, 125 { "lng", FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE },
126 { "rock",FILE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK }, 126 { "rock",FILE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK },
127 { "lua", FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK }, 127 { "lua", FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK },
128 { "opx", FILE_ATTR_OPX, Icon_Plugin, VOICE_EXT_ROCK },
128 { "fnt", FILE_ATTR_FONT,Icon_Font, VOICE_EXT_FONT }, 129 { "fnt", FILE_ATTR_FONT,Icon_Font, VOICE_EXT_FONT },
129 { "kbd", FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD }, 130 { "kbd", FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD },
130 { "bmark",FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK }, 131 { "bmark",FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK },
diff --git a/apps/filetypes.h b/apps/filetypes.h
index 8c9e9a5d93..23f259b3ca 100644
--- a/apps/filetypes.h
+++ b/apps/filetypes.h
@@ -47,6 +47,7 @@
47#define FILE_ATTR_LUA 0x1100 /* Lua rockbox plugin */ 47#define FILE_ATTR_LUA 0x1100 /* Lua rockbox plugin */
48#define FILE_ATTR_FMS 0x1200 /* FM screen skin file */ 48#define FILE_ATTR_FMS 0x1200 /* FM screen skin file */
49#define FILE_ATTR_RFMS 0x1300 /* FM screen skin file */ 49#define FILE_ATTR_RFMS 0x1300 /* FM screen skin file */
50#define FILE_ATTR_OPX 0x1400 /* open plugins shortcut */
50#define FILE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */ 51#define FILE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */
51 52
52struct filetype { 53struct filetype {
diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c
index ec8b474191..ff257a4925 100644
--- a/apps/gui/option_select.c
+++ b/apps/gui/option_select.c
@@ -467,6 +467,8 @@ bool option_screen(const struct settings_list *setting,
467 int oldvalue, nb_items = 0, selected = 0, temp_var; 467 int oldvalue, nb_items = 0, selected = 0, temp_var;
468 int *variable; 468 int *variable;
469 bool allow_wrap = setting->flags & F_NO_WRAP ? false : true; 469 bool allow_wrap = setting->flags & F_NO_WRAP ? false : true;
470 bool cb_on_select_only =
471 ((setting->flags & F_CB_ON_SELECT_ONLY) == F_CB_ON_SELECT_ONLY);
470 int var_type = setting->flags&F_T_MASK; 472 int var_type = setting->flags&F_T_MASK;
471 void (*function)(int) = NULL; 473 void (*function)(int) = NULL;
472 char *title; 474 char *title;
@@ -554,12 +556,15 @@ bool option_screen(const struct settings_list *setting,
554 } 556 }
555 settings_save(); 557 settings_save();
556 done = true; 558 done = true;
559 if (cb_on_select_only && function)
560 function(*variable);
557 } 561 }
558 else if(default_event_handler(action) == SYS_USB_CONNECTED) 562 else if(default_event_handler(action) == SYS_USB_CONNECTED)
559 return true; 563 return true;
560 /* callback */ 564 /* callback */
561 if ( function ) 565 if (function && !cb_on_select_only)
562 function(*variable); 566 function(*variable);
567
563 /* if the volume is changing we need to let the skins know */ 568 /* if the volume is changing we need to let the skins know */
564 if (function == sound_get_fn(SOUND_VOLUME)) 569 if (function == sound_get_fn(SOUND_VOLUME))
565 global_status.last_volume_change = current_tick; 570 global_status.last_volume_change = current_tick;
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index 8d0453385b..8a51d9b810 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -687,10 +687,8 @@ long gui_wps_show(void)
687 return GO_TO_ROOT; 687 return GO_TO_ROOT;
688 else if (retval == ONPLAY_PLAYLIST) 688 else if (retval == ONPLAY_PLAYLIST)
689 return GO_TO_PLAYLIST_VIEWER; 689 return GO_TO_PLAYLIST_VIEWER;
690#ifdef HAVE_PICTUREFLOW_INTEGRATION 690 else if (retval == ONPLAY_PLUGIN)
691 else if (retval == ONPLAY_PICTUREFLOW) 691 return GO_TO_PLUGIN;
692 return GO_TO_PICTUREFLOW;
693#endif
694 restore = true; 692 restore = true;
695 } 693 }
696 break; 694 break;
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 5937df64c0..8af6e55c5e 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16150,3 +16150,59 @@
16150 hotkey: "Hold for settings" 16150 hotkey: "Hold for settings"
16151 </voice> 16151 </voice>
16152</phrase> 16152</phrase>
16153<phrase>
16154 id: LANG_OPEN_PLUGIN
16155 desc: onplay open plugin
16156 user: core
16157 <source>
16158 *: "Open Plugin"
16159 </source>
16160 <dest>
16161 *: "Open Plugin"
16162 </dest>
16163 <voice>
16164 *: "Open Plugin"
16165 </voice>
16166</phrase>
16167<phrase>
16168 id: LANG_OPEN_PLUGIN_NOT_A_PLUGIN
16169 desc: open plugin module
16170 user: core
16171 <source>
16172 *: "Not a plugin: %s"
16173 </source>
16174 <dest>
16175 *: "Not a plugin: %s"
16176 </dest>
16177 <voice>
16178 *: "Not a plugin"
16179 </voice>
16180</phrase>
16181<phrase>
16182 id: LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN
16183 desc: open plugin module
16184 user: core
16185 <source>
16186 *: "Set Wps Context Plugin"
16187 </source>
16188 <dest>
16189 *: "Set Wps Context Plugin"
16190 </dest>
16191 <voice>
16192 *: "Set Wps Context Plugin"
16193 </voice>
16194</phrase>
16195<phrase>
16196 id: LANG_PARAMETER
16197 desc:
16198 user: core
16199 <source>
16200 *: "Parameter"
16201 </source>
16202 <dest>
16203 *: "Parameter"
16204 </dest>
16205 <voice>
16206 *: "Parameter"
16207 </voice>
16208</phrase>
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 431600bbe1..9275ff10d6 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -28,6 +28,7 @@
28#include "action.h" 28#include "action.h"
29#include "settings.h" 29#include "settings.h"
30#include "menu.h" 30#include "menu.h"
31#include "open_plugin.h"
31#include "keyboard.h" 32#include "keyboard.h"
32#include "sound_menu.h" 33#include "sound_menu.h"
33#include "exported_menus.h" 34#include "exported_menus.h"
@@ -711,6 +712,18 @@ MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
711/* VOICE MENU */ 712/* VOICE MENU */
712/***********************************/ 713/***********************************/
713 714
715/* WPS_CONTEXT_PLUGIN */
716/***********************************/
717static void wps_plugin_cb(void)
718{
719 open_plugin_browse(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN));
720}
721MENUITEM_FUNCTION(wps_set_context_plugin, 0,
722 ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN),
723 wps_plugin_cb, NULL, NULL, Icon_Plugin);
724
725/* WPS_CONTEXT_PLUGIN */
726/***********************************/
714 727
715/***********************************/ 728/***********************************/
716/* HOTKEY MENU */ 729/* HOTKEY MENU */
@@ -745,6 +758,7 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
745 &autoresume_menu, 758 &autoresume_menu,
746#endif 759#endif
747 &browse_langs, &voice_settings_menu, 760 &browse_langs, &voice_settings_menu,
761 &wps_set_context_plugin,
748#ifdef HAVE_HOTKEY 762#ifdef HAVE_HOTKEY
749 &hotkey_menu, 763 &hotkey_menu,
750#endif 764#endif
diff --git a/apps/onplay.c b/apps/onplay.c
index fd956167d3..f2ebd47630 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -43,6 +43,7 @@
43#include "talk.h" 43#include "talk.h"
44#include "onplay.h" 44#include "onplay.h"
45#include "filetypes.h" 45#include "filetypes.h"
46#include "open_plugin.h"
46#include "plugin.h" 47#include "plugin.h"
47#include "bookmark.h" 48#include "bookmark.h"
48#include "action.h" 49#include "action.h"
@@ -1415,10 +1416,8 @@ MENUITEM_FUNCTION(rating_item, 0, ID2P(LANG_MENU_SET_RATING),
1415 set_rating_inline, NULL, 1416 set_rating_inline, NULL,
1416 ratingitem_callback, Icon_Questionmark); 1417 ratingitem_callback, Icon_Questionmark);
1417#endif 1418#endif
1418#ifdef HAVE_PICTUREFLOW_INTEGRATION 1419MENUITEM_RETURNVALUE(plugin_item, ID2P(LANG_OPEN_PLUGIN),
1419MENUITEM_RETURNVALUE(pictureflow_item, ID2P(LANG_ONPLAY_PICTUREFLOW), 1420 GO_TO_PLUGIN, NULL, Icon_Plugin);
1420 GO_TO_PICTUREFLOW, NULL, Icon_NOICON);
1421#endif
1422 1421
1423static bool view_cue(void) 1422static bool view_cue(void)
1424{ 1423{
@@ -1650,9 +1649,7 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
1650 &rating_item, 1649 &rating_item,
1651#endif 1650#endif
1652 &bookmark_menu, 1651 &bookmark_menu,
1653#ifdef HAVE_PICTUREFLOW_INTEGRATION 1652 &plugin_item,
1654 &pictureflow_item,
1655#endif
1656 &browse_id3_item, &list_viewers_item, 1653 &browse_id3_item, &list_viewers_item,
1657 &delete_file_item, &view_cue_item, 1654 &delete_file_item, &view_cue_item,
1658#ifdef HAVE_PITCHCONTROL 1655#ifdef HAVE_PITCHCONTROL
@@ -1732,6 +1729,11 @@ static int playlist_insert_shuffled(void)
1732 return ONPLAY_RELOAD_DIR; 1729 return ONPLAY_RELOAD_DIR;
1733} 1730}
1734 1731
1732static void hotkey_run_plugin(void)
1733{
1734 open_plugin_run(ID2P(LANG_HOTKEY_WPS));
1735}
1736
1735struct hotkey_assignment { 1737struct hotkey_assignment {
1736 int action; /* hotkey_action */ 1738 int action; /* hotkey_action */
1737 int lang_id; /* Language ID */ 1739 int lang_id; /* Language ID */
@@ -1768,11 +1770,9 @@ static struct hotkey_assignment hotkey_items[] = {
1768 { HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED, 1770 { HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
1769 HOTKEY_FUNC(playlist_insert_shuffled, NULL), 1771 HOTKEY_FUNC(playlist_insert_shuffled, NULL),
1770 ONPLAY_RELOAD_DIR }, 1772 ONPLAY_RELOAD_DIR },
1771#ifdef HAVE_PICTUREFLOW_INTEGRATION 1773 { HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
1772 { HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW, 1774 HOTKEY_FUNC(hotkey_run_plugin, NULL),
1773 HOTKEY_FUNC(NULL, NULL), 1775 ONPLAY_OK },
1774 ONPLAY_PICTUREFLOW },
1775#endif
1776 { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE, 1776 { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
1777 HOTKEY_FUNC(bookmark_create_menu, NULL), 1777 HOTKEY_FUNC(bookmark_create_menu, NULL),
1778 ONPLAY_OK }, 1778 ONPLAY_OK },
@@ -1861,10 +1861,8 @@ int onplay(char* file, int attr, int from, bool hotkey)
1861 return ONPLAY_MAINMENU; 1861 return ONPLAY_MAINMENU;
1862 case GO_TO_PLAYLIST_VIEWER: 1862 case GO_TO_PLAYLIST_VIEWER:
1863 return ONPLAY_PLAYLIST; 1863 return ONPLAY_PLAYLIST;
1864#ifdef HAVE_PICTUREFLOW_INTEGRATION 1864 case GO_TO_PLUGIN:
1865 case GO_TO_PICTUREFLOW: 1865 return ONPLAY_PLUGIN;
1866 return ONPLAY_PICTUREFLOW;
1867#endif
1868 default: 1866 default:
1869 return onplay_result; 1867 return onplay_result;
1870 } 1868 }
diff --git a/apps/onplay.h b/apps/onplay.h
index 24637ac18c..27f0436403 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -29,7 +29,7 @@ enum {
29 ONPLAY_RELOAD_DIR, 29 ONPLAY_RELOAD_DIR,
30 ONPLAY_START_PLAY, 30 ONPLAY_START_PLAY,
31 ONPLAY_PLAYLIST, 31 ONPLAY_PLAYLIST,
32 ONPLAY_PICTUREFLOW, 32 ONPLAY_PLUGIN,
33}; 33};
34 34
35#ifdef HAVE_HOTKEY 35#ifdef HAVE_HOTKEY
@@ -44,7 +44,7 @@ enum hotkey_action {
44 HOTKEY_DELETE, 44 HOTKEY_DELETE,
45 HOTKEY_INSERT, 45 HOTKEY_INSERT,
46 HOTKEY_INSERT_SHUFFLED, 46 HOTKEY_INSERT_SHUFFLED,
47 HOTKEY_PICTUREFLOW, 47 HOTKEY_PLUGIN,
48 HOTKEY_BOOKMARK, 48 HOTKEY_BOOKMARK,
49}; 49};
50#endif 50#endif
diff --git a/apps/open_plugin.c b/apps/open_plugin.c
new file mode 100644
index 0000000000..0fb20403bc
--- /dev/null
+++ b/apps/open_plugin.c
@@ -0,0 +1,204 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2020 by William Wilgus
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __PCTOOL__
23
24#include "plugin.h"
25#include "open_plugin.h"
26#include "pathfuncs.h"
27#include "keyboard.h"
28#include "splash.h"
29#include "lang.h"
30
31struct open_plugin_entry_t open_plugin_entry;
32
33static const int op_entry_sz = sizeof(struct open_plugin_entry_t);
34
35static void get_param(void)
36{
37 char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
38 strlcpy(tmp_buf, open_plugin_entry.param, OPEN_PLUGIN_BUFSZ);
39 if (kbd_input(tmp_buf, OPEN_PLUGIN_BUFSZ, NULL))
40 strlcpy(open_plugin_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
41}
42
43uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter)
44{
45 int len;
46 uint32_t hash;
47 char *pos;
48 int fd = 0;
49
50 /*strlcpy(plug_entry.key, key, sizeof(plug_entry.key));*/
51 open_plugin_entry.lang_id = P2ID((unsigned char*)key);
52 key = P2STR((unsigned char *)key);
53
54 open_plugin_get_hash(key, &hash);
55 open_plugin_entry.hash = hash;
56
57 if (plugin)
58 {
59 /* name */
60 if (path_basename(plugin, (const char **)&pos) == 0)
61 pos = "\0";
62
63 len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ);
64
65 if(len > 5 && strcasecmp(&(pos[len-5]), ".rock") == 0)
66 {
67 fd = open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
68 if (!fd)
69 return 0;
70
71 /* path */
72 strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
73
74 if(parameter)
75 {
76 if (parameter[0] == '\0' &&
77 yesno_pop(ID2P(LANG_PARAMETER)))
78 {
79 get_param();
80 }
81 else
82 strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
83 }
84
85 write(fd, &open_plugin_entry, op_entry_sz);
86 }
87 else
88 {
89 if (open_plugin_entry.lang_id != LANG_SHORTCUTS)
90 splashf(HZ / 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos);
91 return 0;
92 }
93 }
94
95 int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY);
96 if (fd1)
97 {
98 while (read(fd1, &open_plugin_entry, op_entry_sz) == op_entry_sz)
99 {
100 if (open_plugin_entry.hash != hash)
101 write(fd, &open_plugin_entry, op_entry_sz);
102 }
103 close(fd1);
104 }
105 close(fd);
106
107 if(fd1)
108 {
109 remove(OPEN_PLUGIN_DAT);
110 rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
111 }
112 else
113 hash = 0;
114
115 return hash;
116}
117
118void open_plugin_browse(const char *key)
119{
120 struct browse_context browse;
121 char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
122 open_plugin_get_entry(key, &open_plugin_entry);
123
124 if (open_plugin_entry.path[0] == '\0')
125 strcpy(open_plugin_entry.path, PLUGIN_DIR"/");
126
127 browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "",
128 Icon_Plugin, open_plugin_entry.path, NULL);
129
130 browse.buf = tmp_buf;
131 browse.bufsize = OPEN_PLUGIN_BUFSZ;
132
133 if (rockbox_browse(&browse) == GO_TO_PREVIOUS)
134 {
135 open_plugin_add_path(key, tmp_buf, NULL);
136 }
137}
138
139void open_plugin_remove(const char *key)
140{
141 (void)key;
142 open_plugin_add_path(key, NULL, NULL);
143}
144
145static int open_plugin_hash_get_entry(uint32_t hash, struct open_plugin_entry_t *entry)
146{
147 int ret = -1, record = -1;
148
149 if (entry)
150 {
151 int fd = open(OPEN_PLUGIN_DAT, O_RDONLY);
152
153 if (fd)
154 {
155 while (read(fd, entry, op_entry_sz) == op_entry_sz)
156 {
157 record++;
158 if (entry->hash == hash)
159 {
160 ret = record;
161 break;
162 }
163 }
164 close(fd);
165 }
166 if (ret < 0)
167 {
168 memset(entry, 0, op_entry_sz);
169 entry->lang_id = -1;
170 }
171 }
172
173 return ret;
174}
175
176int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry)
177{
178 uint32_t hash;
179 key = P2STR((unsigned char *)key);
180
181 open_plugin_get_hash(key, &hash);
182 return open_plugin_hash_get_entry(hash, entry);
183}
184
185int open_plugin_run(const char *key)
186{
187 int ret = 0;
188 const char *path;
189 const char *param;
190
191 open_plugin_get_entry(key, &open_plugin_entry);
192
193 path = open_plugin_entry.path;
194 param = open_plugin_entry.param;
195 if (param[0] == '\0')
196 param = NULL;
197
198 if (path)
199 ret = plugin_load(path, param);
200
201 return ret;
202}
203
204#endif /* ndef __PCTOOL__ */
diff --git a/apps/open_plugin.h b/apps/open_plugin.h
new file mode 100644
index 0000000000..2d8a527073
--- /dev/null
+++ b/apps/open_plugin.h
@@ -0,0 +1,66 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2020 by William Wilgus
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef OPEN_PLUGIN_H
22#define OPEN_PLUGIN_H
23
24/* Open_plugin module
25 * OP stores and retrieves plugin path and parameters by key
26 * from a dictionary file
27 *
28 * plugins can load other plugins
29 * return rb->plugin_open(path, parameter);
30 */
31
32#ifndef __PCTOOL__
33/* open_plugin path lookup */
34#define OPEN_PLUGIN_DAT PLUGIN_DIR "/plugin.dat"
35#define OPEN_PLUGIN_BUFSZ MAX_PATH
36#define OPEN_PLUGIN_NAMESZ 32
37struct open_plugin_entry_t
38{
39 uint32_t hash;
40 int32_t lang_id;
41 char name[OPEN_PLUGIN_NAMESZ+1];
42 /*char key[OPEN_PLUGIN_BUFSZ+1];*/
43 char path[OPEN_PLUGIN_BUFSZ+1];
44 char param[OPEN_PLUGIN_BUFSZ+1];
45};
46
47inline static void open_plugin_get_hash(const char *key, uint32_t *hash)
48{
49 /* Calculate modified FNV1a hash of string */
50 const uint32_t p = 16777619;
51 *hash = 0x811C9DC5; //seed, 2166136261;
52 while(*key)
53 *hash = (*key++ ^ *hash) * p;
54}
55
56#ifndef PLUGIN
57extern struct open_plugin_entry_t open_plugin_entry;
58uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter);
59int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry);
60void open_plugin_browse(const char *key);
61void open_plugin_remove(const char *key);
62int open_plugin_run(const char *key);
63#endif
64
65#endif /*ndef __PCTOOL__ */
66#endif /* OPEN_PLUGIN_H */
diff --git a/apps/plugin.c b/apps/plugin.c
index 2066d3a108..749132cde8 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -21,6 +21,7 @@
21#define DIRFUNCTIONS_DEFINED 21#define DIRFUNCTIONS_DEFINED
22#define FILEFUNCTIONS_DEFINED 22#define FILEFUNCTIONS_DEFINED
23#include "plugin.h" 23#include "plugin.h"
24#include "open_plugin.h"
24#include <ctype.h> 25#include <ctype.h>
25#include <string.h> 26#include <string.h>
26#include <stdlib.h> 27#include <stdlib.h>
@@ -807,6 +808,7 @@ static const struct plugin_api rockbox_api = {
807#ifdef HAVE_TAGCACHE 808#ifdef HAVE_TAGCACHE
808 tagcache_get_stat, 809 tagcache_get_stat,
809#endif 810#endif
811 plugin_open,
810}; 812};
811 813
812static int plugin_buffer_handle; 814static int plugin_buffer_handle;
@@ -1019,6 +1021,12 @@ static void plugin_tsr(bool (*exit_callback)(bool))
1019 pfn_tsr_exit = exit_callback; /* remember the callback for later */ 1021 pfn_tsr_exit = exit_callback; /* remember the callback for later */
1020} 1022}
1021 1023
1024int plugin_open(char *plugin, char *parameter)
1025{
1026 open_plugin_add_path(ID2P(LANG_OPEN_PLUGIN), plugin, parameter);
1027 return PLUGIN_GOTO_PLUGIN;
1028}
1029
1022char *plugin_get_current_filename(void) 1030char *plugin_get_current_filename(void)
1023{ 1031{
1024 return current_plugin; 1032 return current_plugin;
diff --git a/apps/plugin.h b/apps/plugin.h
index 2585d17205..fc3da61c57 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -49,6 +49,7 @@
49 49
50char* strncpy(char *, const char *, size_t); 50char* strncpy(char *, const char *, size_t);
51void* plugin_get_buffer(size_t *buffer_size); 51void* plugin_get_buffer(size_t *buffer_size);
52int plugin_open(char *plugin, char *parameter);
52 53
53#ifndef __PCTOOL__ 54#ifndef __PCTOOL__
54#include "config.h" 55#include "config.h"
@@ -172,6 +173,7 @@ enum plugin_status {
172 PLUGIN_USB_CONNECTED = INTERNAL_PLUGIN_RETVAL_START, 173 PLUGIN_USB_CONNECTED = INTERNAL_PLUGIN_RETVAL_START,
173 PLUGIN_POWEROFF, 174 PLUGIN_POWEROFF,
174 PLUGIN_GOTO_WPS, 175 PLUGIN_GOTO_WPS,
176 PLUGIN_GOTO_PLUGIN,
175 PLUGIN_ERROR = -1, 177 PLUGIN_ERROR = -1,
176}; 178};
177 179
@@ -934,6 +936,7 @@ struct plugin_api {
934#ifdef HAVE_TAGCACHE 936#ifdef HAVE_TAGCACHE
935 struct tagcache_stat* (*tagcache_get_stat)(void); 937 struct tagcache_stat* (*tagcache_get_stat)(void);
936#endif 938#endif
939 int (*plugin_open)(char *path, char *parameter);
937 940
938}; 941};
939 942
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index d1da10ee09..91062f8f11 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -533,19 +533,28 @@ static void free_all_slide_prio(int prio);
533static bool check_database(bool prompt) 533static bool check_database(bool prompt)
534{ 534{
535 bool needwarn = true; 535 bool needwarn = true;
536 int spin = 5;
537
536 struct tagcache_stat *stat = rb->tagcache_get_stat(); 538 struct tagcache_stat *stat = rb->tagcache_get_stat();
539
537 while ( !(stat->initialized && stat->ready) ) 540 while ( !(stat->initialized && stat->ready) )
538 { 541 {
539 if (needwarn) 542 if (--spin > 0)
543 {
544 rb->sleep(HZ/5);
545 }
546 else if (needwarn)
547 {
548 needwarn = false;
540 rb->splash(0, ID2P(LANG_TAGCACHE_BUSY)); 549 rb->splash(0, ID2P(LANG_TAGCACHE_BUSY));
541 if (!prompt) 550 }
551 else if (!prompt)
542 return false; 552 return false;
543 else if (rb->action_userabort(HZ/5)) 553 else if (rb->action_userabort(HZ/5))
544 return false; 554 return false;
545 555
546 needwarn = false;
547 stat = rb->tagcache_get_stat();
548 rb->yield(); 556 rb->yield();
557 stat = rb->tagcache_get_stat();
549 } 558 }
550 return true; 559 return true;
551} 560}
@@ -3841,7 +3850,7 @@ enum plugin_status plugin_start(const void *parameter)
3841 3850
3842 void * buf; 3851 void * buf;
3843 size_t buf_size; 3852 size_t buf_size;
3844 bool prompt = (parameter && ((char *) parameter)[0] == ACTIVITY_MAINMENU); 3853 bool prompt = (parameter && (((char *) parameter)[0] == ACTIVITY_MAINMENU));
3845 3854
3846 if (!check_database(prompt)) 3855 if (!check_database(prompt))
3847 { 3856 {
diff --git a/apps/plugins/shortcuts/shortcuts_view.c b/apps/plugins/shortcuts/shortcuts_view.c
index cfc9d8d746..f4c4b58bc1 100644
--- a/apps/plugins/shortcuts/shortcuts_view.c
+++ b/apps/plugins/shortcuts/shortcuts_view.c
@@ -22,7 +22,7 @@
22 22
23#include "shortcuts.h" 23#include "shortcuts.h"
24 24
25 25#define LOOP_EXIT 1
26 26
27enum sc_list_action_type 27enum sc_list_action_type
28{ 28{
@@ -35,7 +35,6 @@ enum sc_list_action_type
35 35
36static char *link_filename; 36static char *link_filename;
37static bool user_file; 37static bool user_file;
38static bool usb_connected = false;
39 38
40enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc); 39enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc);
41 40
@@ -43,10 +42,10 @@ enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc);
43static const char* build_sc_list(int selected_item, void *data, 42static const char* build_sc_list(int selected_item, void *data,
44 char *buffer, size_t buffer_len); 43 char *buffer, size_t buffer_len);
45 44
46/* Returns true iff we should leave the main loop */ 45/* Returns LOOP_EXIT iff we should leave the main loop */
47bool list_sc(void); 46int list_sc(void);
48 47
49bool goto_entry(char *file_or_dir); 48int goto_entry(char *file_or_dir);
50bool ends_with(char *str, char *suffix); 49bool ends_with(char *str, char *suffix);
51 50
52 51
@@ -104,7 +103,7 @@ static const char* build_sc_list(int selected_item, void *data,
104} 103}
105 104
106 105
107bool list_sc(void) 106int list_sc(void)
108{ 107{
109 int selected_item = 0; 108 int selected_item = 0;
110 enum sc_list_action_type action = SCLA_NONE; 109 enum sc_list_action_type action = SCLA_NONE;
@@ -122,8 +121,7 @@ bool list_sc(void)
122 /* Draw the prepared widget to the LCD now */ 121 /* Draw the prepared widget to the LCD now */
123 action = draw_sc_list(&gui_sc); 122 action = draw_sc_list(&gui_sc);
124 if (action == SCLA_USB) { 123 if (action == SCLA_USB) {
125 usb_connected = true; 124 return PLUGIN_USB_CONNECTED;
126 return true;
127 } 125 }
128 126
129 /* which item do we action? */ 127 /* which item do we action? */
@@ -132,7 +130,7 @@ bool list_sc(void)
132 if (!is_valid_index(&sc_file, selected_item)) { 130 if (!is_valid_index(&sc_file, selected_item)) {
133 /* This should never happen */ 131 /* This should never happen */
134 rb->splash(HZ*2, "Bad entry selected!"); 132 rb->splash(HZ*2, "Bad entry selected!");
135 return true; 133 return PLUGIN_ERROR;
136 } 134 }
137 135
138 /* perform the following actions if the user "selected" 136 /* perform the following actions if the user "selected"
@@ -145,13 +143,13 @@ bool list_sc(void)
145 rb->splashf(HZ, "Deleting %s", sc_file.entries[selected_item].disp); 143 rb->splashf(HZ, "Deleting %s", sc_file.entries[selected_item].disp);
146 remove_entry(&sc_file, selected_item); 144 remove_entry(&sc_file, selected_item);
147 dump_sc_file(&sc_file, link_filename); 145 dump_sc_file(&sc_file, link_filename);
148 return (sc_file.entry_cnt == 0); 146 return (sc_file.entry_cnt == 0)? LOOP_EXIT : PLUGIN_OK;
149 default: 147 default:
150 return true; 148 return LOOP_EXIT;
151 } 149 }
152} 150}
153 151
154 152#if 0
155bool goto_entry(char *file_or_dir) 153bool goto_entry(char *file_or_dir)
156{ 154{
157 DEBUGF("Trying to go to '%s'...\n", file_or_dir); 155 DEBUGF("Trying to go to '%s'...\n", file_or_dir);
@@ -181,7 +179,46 @@ bool goto_entry(char *file_or_dir)
181 rb->set_current_file(file_or_dir); 179 rb->set_current_file(file_or_dir);
182 return true; 180 return true;
183} 181}
182#endif
183
184int goto_entry(char *file_or_dir)
185{
186 DEBUGF("Trying to go to '%s'...\n", file_or_dir);
187
188 bool is_dir = ends_with(file_or_dir, PATH_SEPARATOR);
189 bool exists;
190 char *what;
191 if (is_dir) {
192 what = "Directory";
193 exists = rb->dir_exists(file_or_dir);
194 } else {
195 what = "File";
196 exists = rb->file_exists(file_or_dir);
197 }
184 198
199 if (!exists) {
200 rb->splashf(HZ*2, "%s %s no longer exists on disk", what, file_or_dir);
201 return PLUGIN_ERROR;
202 }
203
204 int len = rb->strlen(file_or_dir);
205 if(!is_dir && len > 5 && rb->strcasecmp(&(file_or_dir[len-5]), ".rock") == 0)
206 {
207 return rb->plugin_open(file_or_dir, NULL);
208 }
209 else
210 {
211 /* Set the browsers dirfilter to the global setting
212 * This is required in case the plugin was launched
213 * from the plugins browser, in which case the
214 * dirfilter is set to only display .rock files */
215 rb->set_dirfilter(rb->global_settings->dirfilter);
216
217 /* Change directory to the entry selected by the user */
218 rb->set_current_file(file_or_dir);
219 }
220 return PLUGIN_OK;
221}
185 222
186bool ends_with(char *string, char *suffix) 223bool ends_with(char *string, char *suffix)
187{ 224{
@@ -195,7 +232,7 @@ bool ends_with(char *string, char *suffix)
195 232
196enum plugin_status plugin_start(const void* void_parameter) 233enum plugin_status plugin_start(const void* void_parameter)
197{ 234{
198 bool leave_loop; 235 int ret;
199 236
200 /* This is a viewer, so a parameter must have been specified */ 237 /* This is a viewer, so a parameter must have been specified */
201 if (void_parameter == NULL) { 238 if (void_parameter == NULL) {
@@ -219,8 +256,7 @@ enum plugin_status plugin_start(const void* void_parameter)
219 /* if there's only one entry in the user .link file, 256 /* if there's only one entry in the user .link file,
220 * go straight to it without displaying the menu 257 * go straight to it without displaying the menu
221 * thus allowing 'quick links' */ 258 * thus allowing 'quick links' */
222 goto_entry(sc_file.entries[0].path); 259 return goto_entry(sc_file.entries[0].path);
223 return PLUGIN_OK;
224 } 260 }
225 261
226 FOR_NB_SCREENS(i) 262 FOR_NB_SCREENS(i)
@@ -228,11 +264,13 @@ enum plugin_status plugin_start(const void* void_parameter)
228 264
229 do { 265 do {
230 /* Display a menu to choose between the entries */ 266 /* Display a menu to choose between the entries */
231 leave_loop = list_sc(); 267 ret = list_sc();
232 } while (!leave_loop); 268 } while (ret == PLUGIN_OK);
269 if (ret == LOOP_EXIT)
270 ret = PLUGIN_OK;
233 271
234 FOR_NB_SCREENS(i) 272 FOR_NB_SCREENS(i)
235 rb->viewportmanager_theme_undo(i, false); 273 rb->viewportmanager_theme_undo(i, false);
236 274
237 return usb_connected ? PLUGIN_USB_CONNECTED : PLUGIN_OK; 275 return ret;
238} 276}
diff --git a/apps/root_menu.c b/apps/root_menu.c
index c59c39fe88..2a8662a170 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -32,6 +32,7 @@
32#include "kernel.h" 32#include "kernel.h"
33#include "debug.h" 33#include "debug.h"
34#include "misc.h" 34#include "misc.h"
35#include "open_plugin.h"
35#include "rolo.h" 36#include "rolo.h"
36#include "powermgmt.h" 37#include "powermgmt.h"
37#include "power.h" 38#include "power.h"
@@ -347,6 +348,7 @@ static int miscscrn(void * param)
347 int result = do_menu(menu, NULL, NULL, false); 348 int result = do_menu(menu, NULL, NULL, false);
348 switch (result) 349 switch (result)
349 { 350 {
351 case GO_TO_PLUGIN:
350 case GO_TO_PLAYLIST_VIEWER: 352 case GO_TO_PLAYLIST_VIEWER:
351 case GO_TO_WPS: 353 case GO_TO_WPS:
352 return result; 354 return result;
@@ -703,7 +705,6 @@ static int load_context_screen(int selection)
703 return retval; 705 return retval;
704} 706}
705 707
706#ifdef HAVE_PICTUREFLOW_INTEGRATION
707static int load_plugin_screen(char *plug_path, void* plug_param) 708static int load_plugin_screen(char *plug_path, void* plug_param)
708{ 709{
709 int ret_val; 710 int ret_val;
@@ -717,6 +718,9 @@ static int load_plugin_screen(char *plug_path, void* plug_param)
717 case PLUGIN_GOTO_WPS: 718 case PLUGIN_GOTO_WPS:
718 ret_val = GO_TO_WPS; 719 ret_val = GO_TO_WPS;
719 break; 720 break;
721 case PLUGIN_GOTO_PLUGIN:
722 ret_val = GO_TO_PLUGIN;
723 break;
720 case PLUGIN_OK: 724 case PLUGIN_OK:
721 ret_val = audio_status() ? GO_TO_PREVIOUS : GO_TO_ROOT; 725 ret_val = audio_status() ? GO_TO_PREVIOUS : GO_TO_ROOT;
722 break; 726 break;
@@ -729,7 +733,6 @@ static int load_plugin_screen(char *plug_path, void* plug_param)
729 last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; 733 last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous;
730 return ret_val; 734 return ret_val;
731} 735}
732#endif
733 736
734void root_menu(void) 737void root_menu(void)
735{ 738{
@@ -807,21 +810,36 @@ void root_menu(void)
807 case GO_TO_ROOTITEM_CONTEXT: 810 case GO_TO_ROOTITEM_CONTEXT:
808 next_screen = load_context_screen(selected); 811 next_screen = load_context_screen(selected);
809 break; 812 break;
810#ifdef HAVE_PICTUREFLOW_INTEGRATION 813 case GO_TO_PLUGIN:
811 case GO_TO_PICTUREFLOW:
812 { 814 {
813 char pf_path[MAX_PATH]; 815 char *key;
814 char activity[6];/* big enough to display int */ 816 switch (last_screen)
815 snprintf(activity, sizeof(activity), "%d", get_current_activity()); 817 {
816 snprintf(pf_path, sizeof(pf_path), 818 case GO_TO_ROOT:
817 "%s/pictureflow.rock", 819 key = ID2P(LANG_START_SCREEN);
818 PLUGIN_DEMOS_DIR); 820 break;
819 821 case GO_TO_WPS:
820 next_screen = load_plugin_screen(pf_path, &activity); 822 key = ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN);
821 previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PICTUREFLOW; 823 break;
824 case GO_TO_SHORTCUTMENU:
825 key = ID2P(LANG_SHORTCUTS);
826 break;
827 default:
828 key = ID2P(LANG_OPEN_PLUGIN);
829 break;
830 }
831
832 open_plugin_get_entry(key, &open_plugin_entry);
833 char *path = open_plugin_entry.path;
834 char *param = open_plugin_entry.param;
835 if (param[0] == '\0')
836 param = NULL;
837
838 next_screen = load_plugin_screen(path, param);
839
840 previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PLUGIN;
822 break; 841 break;
823 } 842 }
824#endif
825 default: 843 default:
826#ifdef HAVE_TAGCACHE 844#ifdef HAVE_TAGCACHE
827/* With !HAVE_TAGCACHE previous_browser is always GO_TO_FILEBROWSER */ 845/* With !HAVE_TAGCACHE previous_browser is always GO_TO_FILEBROWSER */
diff --git a/apps/root_menu.h b/apps/root_menu.h
index 262b1d9a0c..55ea6c72d6 100644
--- a/apps/root_menu.h
+++ b/apps/root_menu.h
@@ -55,7 +55,7 @@ enum {
55 GO_TO_FM, 55 GO_TO_FM,
56#endif 56#endif
57 GO_TO_RECENTBMARKS, 57 GO_TO_RECENTBMARKS,
58 GO_TO_PICTUREFLOW, 58 GO_TO_PLUGIN,
59 /* Do Not add any items above here unless you want it to be able to 59 /* Do Not add any items above here unless you want it to be able to
60 be the "start screen" after a boot up. The setting in settings_list.c 60 be the "start screen" after a boot up. The setting in settings_list.c
61 will need editing if this is the case. */ 61 will need editing if this is the case. */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 1c33f3dc86..a38ebc639c 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -38,6 +38,7 @@
38#include "power.h" 38#include "power.h"
39#include "powermgmt.h" 39#include "powermgmt.h"
40#include "kernel.h" 40#include "kernel.h"
41#include "open_plugin.h"
41#ifdef HAVE_REMOTE_LCD 42#ifdef HAVE_REMOTE_LCD
42#include "lcd-remote.h" 43#include "lcd-remote.h"
43#endif 44#endif
@@ -680,6 +681,11 @@ static void tsc_set_default(void* setting, void* defaultval)
680} 681}
681#endif 682#endif
682#ifdef HAVE_HOTKEY 683#ifdef HAVE_HOTKEY
684static void hotkey_callback(int var)
685{
686 if (get_hotkey_lang_id(var) == LANG_OPEN_PLUGIN)
687 open_plugin_browse(ID2P(LANG_HOTKEY_WPS));
688}
683static const char* hotkey_formatter(char* buffer, size_t buffer_size, int value, 689static const char* hotkey_formatter(char* buffer, size_t buffer_size, int value,
684 const char* unit) 690 const char* unit)
685{ 691{
@@ -695,6 +701,12 @@ static int32_t hotkey_getlang(int value, int unit)
695} 701}
696#endif /* HAVE_HOTKEY */ 702#endif /* HAVE_HOTKEY */
697 703
704static void start_in_callback(int var)
705{
706 if (var - 2 == GO_TO_PLUGIN)
707 open_plugin_browse(ID2P(LANG_START_SCREEN));
708}
709
698/* volume limiter */ 710/* volume limiter */
699static void volume_limit_load_from_cfg(void* var, char*value) 711static void volume_limit_load_from_cfg(void* var, char*value)
700{ 712{
@@ -1872,7 +1884,7 @@ const struct settings_list settings[] = {
1872 UNIT_SEC, formatter_time_unit_0_is_skip_track, 1884 UNIT_SEC, formatter_time_unit_0_is_skip_track,
1873 getlang_time_unit_0_is_skip_track, NULL, 1885 getlang_time_unit_0_is_skip_track, NULL,
1874 25, timeout_sec_common), 1886 25, timeout_sec_common),
1875 CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1, 1887 CHOICE_SETTING(F_CB_ON_SELECT_ONLY, start_in_screen, LANG_START_SCREEN, 1,
1876 "start in screen", "previous,root,files," 1888 "start in screen", "previous,root,files,"
1877#ifdef HAVE_TAGCACHE 1889#ifdef HAVE_TAGCACHE
1878#define START_DB_COUNT 1 1890#define START_DB_COUNT 1
@@ -1893,15 +1905,10 @@ const struct settings_list settings[] = {
1893#else 1905#else
1894#define START_TUNER_COUNT 0 1906#define START_TUNER_COUNT 0
1895#endif 1907#endif
1896 "bookmarks" 1908 "bookmarks,"
1897#ifdef HAVE_PICTUREFLOW_INTEGRATION 1909 "plugin"
1898#define START_PF_COUNT 1 1910 , start_in_callback,
1899 ",pictureflow" 1911 (7 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT),
1900#else
1901#define START_PF_COUNT 0
1902#endif
1903 , NULL,
1904 (6 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT + START_PF_COUNT),
1905 ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU), 1912 ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU),
1906 ID2P(LANG_DIR_BROWSER), 1913 ID2P(LANG_DIR_BROWSER),
1907#ifdef HAVE_TAGCACHE 1914#ifdef HAVE_TAGCACHE
@@ -1914,10 +1921,8 @@ const struct settings_list settings[] = {
1914#if CONFIG_TUNER 1921#if CONFIG_TUNER
1915 ID2P(LANG_FM_RADIO), 1922 ID2P(LANG_FM_RADIO),
1916#endif 1923#endif
1917 ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS) 1924 ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS),
1918#ifdef HAVE_PICTUREFLOW_INTEGRATION 1925 ID2P(LANG_OPEN_PLUGIN)
1919 ,ID2P(LANG_ONPLAY_PICTUREFLOW)
1920#endif
1921 ), 1926 ),
1922 SYSTEM_SETTING(NVRAM(1),last_screen,-1), 1927 SYSTEM_SETTING(NVRAM(1),last_screen,-1),
1923#if defined(HAVE_RTC_ALARM) && \ 1928#if defined(HAVE_RTC_ALARM) && \
@@ -2098,25 +2103,12 @@ const struct settings_list settings[] = {
2098#endif 2103#endif
2099 2104
2100#ifdef HAVE_HOTKEY 2105#ifdef HAVE_HOTKEY
2101 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_wps, 2106 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS | F_CB_ON_SELECT_ONLY, hotkey_wps,
2102 LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps", 2107 LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps",
2103 "off,view playlist,show track info,pitchscreen,open with,delete,bookmark" 2108 "off,view playlist,show track info,pitchscreen,open with,delete,bookmark,plugin"
2104#ifdef HAVE_PICTUREFLOW_INTEGRATION 2109 ,UNIT_INT, hotkey_formatter, hotkey_getlang, hotkey_callback,8, HOTKEY_OFF,
2105 ",pictureflow"
2106#endif
2107 ,UNIT_INT, hotkey_formatter, hotkey_getlang, NULL,
2108#ifdef HAVE_PICTUREFLOW_INTEGRATION
2109 8,
2110#else
2111 7,
2112#endif
2113 HOTKEY_OFF,
2114 HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN, 2110 HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN,
2115 HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK 2111 HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK, HOTKEY_PLUGIN),
2116#ifdef HAVE_PICTUREFLOW_INTEGRATION
2117 , HOTKEY_PICTUREFLOW
2118#endif
2119 ),
2120 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree, 2112 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree,
2121 LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree", 2113 LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree",
2122 "off,open with,delete,insert,insert shuffled", 2114 "off,open with,delete,insert,insert shuffled",
diff --git a/apps/settings_list.h b/apps/settings_list.h
index 7f0ae6484f..36c4d8062f 100644
--- a/apps/settings_list.h
+++ b/apps/settings_list.h
@@ -100,6 +100,7 @@ struct table_setting {
100}; 100};
101#define F_TABLE_SETTING 0x2000 101#define F_TABLE_SETTING 0x2000
102#define F_ALLOW_ARBITRARY_VALS 0x4000 102#define F_ALLOW_ARBITRARY_VALS 0x4000
103#define F_CB_ON_SELECT_ONLY 0x20000
103/* these use the _isfunc_type type for the function */ 104/* these use the _isfunc_type type for the function */
104/* typedef int (*_isfunc_type)(void); */ 105/* typedef int (*_isfunc_type)(void); */
105#define F_MIN_ISFUNC 0x100000 /* min(above) is function pointer to above type */ 106#define F_MIN_ISFUNC 0x100000 /* min(above) is function pointer to above type */
diff --git a/apps/shortcuts.c b/apps/shortcuts.c
index c7e5755c1a..aa9a32bbb2 100644
--- a/apps/shortcuts.c
+++ b/apps/shortcuts.c
@@ -36,6 +36,7 @@
36#include "lang.h" 36#include "lang.h"
37#include "menu.h" 37#include "menu.h"
38#include "misc.h" 38#include "misc.h"
39#include "open_plugin.h"
39#include "tree.h" 40#include "tree.h"
40#include "splash.h" 41#include "splash.h"
41#include "pathfuncs.h" 42#include "pathfuncs.h"
@@ -608,6 +609,12 @@ int do_shortcut_menu(void *ignored)
608 /* else fall through */ 609 /* else fall through */
609 case SHORTCUT_BROWSER: 610 case SHORTCUT_BROWSER:
610 { 611 {
612
613 if(open_plugin_add_path(ID2P(LANG_SHORTCUTS), sc->u.path, NULL) != 0)
614 {
615 done = GO_TO_PLUGIN;
616 break;
617 }
611 struct browse_context browse; 618 struct browse_context browse;
612 browse_context_init(&browse, global_settings.dirfilter, 0, 619 browse_context_init(&browse, global_settings.dirfilter, 0,
613 NULL, NOICON, sc->u.path, NULL); 620 NULL, NOICON, sc->u.path, NULL);
diff --git a/apps/tree.c b/apps/tree.c
index 316139427d..48723c4f2e 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -676,6 +676,8 @@ static int dirbrowse(void)
676#endif 676#endif
677 { 677 {
678 case GO_TO_FILEBROWSER: reload_dir = true; break; 678 case GO_TO_FILEBROWSER: reload_dir = true; break;
679 case GO_TO_PLUGIN:
680 return GO_TO_PLUGIN;
679 case GO_TO_WPS: 681 case GO_TO_WPS:
680 return GO_TO_WPS; 682 return GO_TO_WPS;
681#if CONFIG_TUNER 683#if CONFIG_TUNER
diff --git a/manual/advanced_topics/main.tex b/manual/advanced_topics/main.tex
index 00b1688e11..997850a6fd 100755
--- a/manual/advanced_topics/main.tex
+++ b/manual/advanced_topics/main.tex
@@ -36,6 +36,12 @@ This configuration entry can only be created and edited with a text editor or
36the Main Menu Config Plugin (see \reference{ref:main_menu_config}). 36the Main Menu Config Plugin (see \reference{ref:main_menu_config}).
37It is not possible to change this setting via the settings menu. 37It is not possible to change this setting via the settings menu.
38 38
39\subsection{\label{ref:OpenPlugins}Open Plugin Menu Items}
40
41Rockbox allows you to choose a plugin to run for select menu options.
42Simply choose the option in the setting menu and choose the plugin
43you would like to run.
44
39\opt{lcd_bitmap}{ 45\opt{lcd_bitmap}{
40\subsection{\label{ref:GettingExtras}Getting Extras} 46\subsection{\label{ref:GettingExtras}Getting Extras}
41 47
diff --git a/manual/configure_rockbox/main.tex b/manual/configure_rockbox/main.tex
index 0eeea4e256..83089b6d4e 100644
--- a/manual/configure_rockbox/main.tex
+++ b/manual/configure_rockbox/main.tex
@@ -21,6 +21,7 @@
21}} 21}}
22 \input{configure_rockbox/language.tex} 22 \input{configure_rockbox/language.tex}
23 \input{configure_rockbox/voice.tex} 23 \input{configure_rockbox/voice.tex}
24 \input{configure_rockbox/wps_context_plugin.tex}
24 \input{configure_rockbox/hotkey_settings.tex} 25 \input{configure_rockbox/hotkey_settings.tex}
25 26
26\chapter{Theme Settings} 27\chapter{Theme Settings}
diff --git a/manual/configure_rockbox/wps_context_plugin.tex b/manual/configure_rockbox/wps_context_plugin.tex
new file mode 100644
index 0000000000..8d193d47d6
--- /dev/null
+++ b/manual/configure_rockbox/wps_context_plugin.tex
@@ -0,0 +1,5 @@
1\section{\label{ref:SetWPSContextPlugin}Set WPS Context Plugin}
2
3 \begin{description}
4 {This option will allow you to run a rockbox plugin from the WPS context menu}
5 \end{description}