summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}