Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+540 -93
+1
apps/SOURCES
··· 38 38 menus/time_menu.c 39 39 #endif 40 40 misc.c 41 + open_plugin.c 41 42 onplay.c 42 43 playlist.c 43 44 playlist_catalog.c
+14 -1
apps/filetree.c
··· 357 357 (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) || 358 358 (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) || 359 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 362 (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c))) 362 363 { 363 364 continue; ··· 625 626 /* plugin file */ 626 627 case FILE_ATTR_ROCK: 627 628 case FILE_ATTR_LUA: 629 + case FILE_ATTR_OPX: 628 630 { 629 631 char *plugin = buf, *argument = NULL, lua_path[MAX_PATH]; 630 632 int ret; ··· 634 636 plugin = lua_path; 635 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 645 if (global_settings.party_mode && audio_status()) { 639 646 splash(HZ, ID2P(LANG_PARTY_MODE)); ··· 644 651 { 645 652 case PLUGIN_GOTO_WPS: 646 653 play = true; 654 + break; 655 + case PLUGIN_GOTO_PLUGIN: 656 + rc = GO_TO_PLUGIN; 647 657 break; 648 658 case PLUGIN_USB_CONNECTED: 649 659 if(*c->dirfilter > NUM_FILTER_MODES) ··· 689 699 { 690 700 case PLUGIN_USB_CONNECTED: 691 701 rc = GO_TO_FILEBROWSER; 702 + break; 703 + case PLUGIN_GOTO_PLUGIN: 704 + rc = GO_TO_PLUGIN; 692 705 break; 693 706 case PLUGIN_GOTO_WPS: 694 707 rc = GO_TO_WPS;
+1
apps/filetypes.c
··· 125 125 { "lng", FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE }, 126 126 { "rock",FILE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK }, 127 127 { "lua", FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK }, 128 + { "opx", FILE_ATTR_OPX, Icon_Plugin, VOICE_EXT_ROCK }, 128 129 { "fnt", FILE_ATTR_FONT,Icon_Font, VOICE_EXT_FONT }, 129 130 { "kbd", FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD }, 130 131 { "bmark",FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK },
+1
apps/filetypes.h
··· 47 47 #define FILE_ATTR_LUA 0x1100 /* Lua rockbox plugin */ 48 48 #define FILE_ATTR_FMS 0x1200 /* FM screen skin file */ 49 49 #define FILE_ATTR_RFMS 0x1300 /* FM screen skin file */ 50 + #define FILE_ATTR_OPX 0x1400 /* open plugins shortcut */ 50 51 #define FILE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */ 51 52 52 53 struct filetype {
+6 -1
apps/gui/option_select.c
··· 467 467 int oldvalue, nb_items = 0, selected = 0, temp_var; 468 468 int *variable; 469 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 472 int var_type = setting->flags&F_T_MASK; 471 473 void (*function)(int) = NULL; 472 474 char *title; ··· 554 556 } 555 557 settings_save(); 556 558 done = true; 559 + if (cb_on_select_only && function) 560 + function(*variable); 557 561 } 558 562 else if(default_event_handler(action) == SYS_USB_CONNECTED) 559 563 return true; 560 564 /* callback */ 561 - if ( function ) 565 + if (function && !cb_on_select_only) 562 566 function(*variable); 567 + 563 568 /* if the volume is changing we need to let the skins know */ 564 569 if (function == sound_get_fn(SOUND_VOLUME)) 565 570 global_status.last_volume_change = current_tick;
+2 -4
apps/gui/wps.c
··· 687 687 return GO_TO_ROOT; 688 688 else if (retval == ONPLAY_PLAYLIST) 689 689 return GO_TO_PLAYLIST_VIEWER; 690 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 691 - else if (retval == ONPLAY_PICTUREFLOW) 692 - return GO_TO_PICTUREFLOW; 693 - #endif 690 + else if (retval == ONPLAY_PLUGIN) 691 + return GO_TO_PLUGIN; 694 692 restore = true; 695 693 } 696 694 break;
+56
apps/lang/english.lang
··· 16150 16150 hotkey: "Hold for settings" 16151 16151 </voice> 16152 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>
+14
apps/menus/settings_menu.c
··· 28 28 #include "action.h" 29 29 #include "settings.h" 30 30 #include "menu.h" 31 + #include "open_plugin.h" 31 32 #include "keyboard.h" 32 33 #include "sound_menu.h" 33 34 #include "exported_menus.h" ··· 711 712 /* VOICE MENU */ 712 713 /***********************************/ 713 714 715 + /* WPS_CONTEXT_PLUGIN */ 716 + /***********************************/ 717 + static void wps_plugin_cb(void) 718 + { 719 + open_plugin_browse(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN)); 720 + } 721 + MENUITEM_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 729 /* HOTKEY MENU */ ··· 745 758 &autoresume_menu, 746 759 #endif 747 760 &browse_langs, &voice_settings_menu, 761 + &wps_set_context_plugin, 748 762 #ifdef HAVE_HOTKEY 749 763 &hotkey_menu, 750 764 #endif
+14 -16
apps/onplay.c
··· 43 43 #include "talk.h" 44 44 #include "onplay.h" 45 45 #include "filetypes.h" 46 + #include "open_plugin.h" 46 47 #include "plugin.h" 47 48 #include "bookmark.h" 48 49 #include "action.h" ··· 1415 1416 set_rating_inline, NULL, 1416 1417 ratingitem_callback, Icon_Questionmark); 1417 1418 #endif 1418 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1419 - MENUITEM_RETURNVALUE(pictureflow_item, ID2P(LANG_ONPLAY_PICTUREFLOW), 1420 - GO_TO_PICTUREFLOW, NULL, Icon_NOICON); 1421 - #endif 1419 + MENUITEM_RETURNVALUE(plugin_item, ID2P(LANG_OPEN_PLUGIN), 1420 + GO_TO_PLUGIN, NULL, Icon_Plugin); 1422 1421 1423 1422 static bool view_cue(void) 1424 1423 { ··· 1650 1649 &rating_item, 1651 1650 #endif 1652 1651 &bookmark_menu, 1653 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1654 - &pictureflow_item, 1655 - #endif 1652 + &plugin_item, 1656 1653 &browse_id3_item, &list_viewers_item, 1657 1654 &delete_file_item, &view_cue_item, 1658 1655 #ifdef HAVE_PITCHCONTROL ··· 1732 1729 return ONPLAY_RELOAD_DIR; 1733 1730 } 1734 1731 1732 + static void hotkey_run_plugin(void) 1733 + { 1734 + open_plugin_run(ID2P(LANG_HOTKEY_WPS)); 1735 + } 1736 + 1735 1737 struct hotkey_assignment { 1736 1738 int action; /* hotkey_action */ 1737 1739 int lang_id; /* Language ID */ ··· 1768 1770 { HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED, 1769 1771 HOTKEY_FUNC(playlist_insert_shuffled, NULL), 1770 1772 ONPLAY_RELOAD_DIR }, 1771 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1772 - { HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW, 1773 - HOTKEY_FUNC(NULL, NULL), 1774 - ONPLAY_PICTUREFLOW }, 1775 - #endif 1773 + { HOTKEY_PLUGIN, LANG_OPEN_PLUGIN, 1774 + HOTKEY_FUNC(hotkey_run_plugin, NULL), 1775 + ONPLAY_OK }, 1776 1776 { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE, 1777 1777 HOTKEY_FUNC(bookmark_create_menu, NULL), 1778 1778 ONPLAY_OK }, ··· 1861 1861 return ONPLAY_MAINMENU; 1862 1862 case GO_TO_PLAYLIST_VIEWER: 1863 1863 return ONPLAY_PLAYLIST; 1864 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1865 - case GO_TO_PICTUREFLOW: 1866 - return ONPLAY_PICTUREFLOW; 1867 - #endif 1864 + case GO_TO_PLUGIN: 1865 + return ONPLAY_PLUGIN; 1868 1866 default: 1869 1867 return onplay_result; 1870 1868 }
+2 -2
apps/onplay.h
··· 29 29 ONPLAY_RELOAD_DIR, 30 30 ONPLAY_START_PLAY, 31 31 ONPLAY_PLAYLIST, 32 - ONPLAY_PICTUREFLOW, 32 + ONPLAY_PLUGIN, 33 33 }; 34 34 35 35 #ifdef HAVE_HOTKEY ··· 44 44 HOTKEY_DELETE, 45 45 HOTKEY_INSERT, 46 46 HOTKEY_INSERT_SHUFFLED, 47 - HOTKEY_PICTUREFLOW, 47 + HOTKEY_PLUGIN, 48 48 HOTKEY_BOOKMARK, 49 49 }; 50 50 #endif
+204
apps/open_plugin.c
··· 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 + 31 + struct open_plugin_entry_t open_plugin_entry; 32 + 33 + static const int op_entry_sz = sizeof(struct open_plugin_entry_t); 34 + 35 + static 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 + 43 + uint32_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 + 118 + void 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 + 139 + void open_plugin_remove(const char *key) 140 + { 141 + (void)key; 142 + open_plugin_add_path(key, NULL, NULL); 143 + } 144 + 145 + static 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 + 176 + int 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 + 185 + int 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__ */
+66
apps/open_plugin.h
··· 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 37 + struct 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 + 47 + inline 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 57 + extern struct open_plugin_entry_t open_plugin_entry; 58 + uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter); 59 + int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry); 60 + void open_plugin_browse(const char *key); 61 + void open_plugin_remove(const char *key); 62 + int open_plugin_run(const char *key); 63 + #endif 64 + 65 + #endif /*ndef __PCTOOL__ */ 66 + #endif /* OPEN_PLUGIN_H */
+8
apps/plugin.c
··· 21 21 #define DIRFUNCTIONS_DEFINED 22 22 #define FILEFUNCTIONS_DEFINED 23 23 #include "plugin.h" 24 + #include "open_plugin.h" 24 25 #include <ctype.h> 25 26 #include <string.h> 26 27 #include <stdlib.h> ··· 807 808 #ifdef HAVE_TAGCACHE 808 809 tagcache_get_stat, 809 810 #endif 811 + plugin_open, 810 812 }; 811 813 812 814 static int plugin_buffer_handle; ··· 1017 1019 static void plugin_tsr(bool (*exit_callback)(bool)) 1018 1020 { 1019 1021 pfn_tsr_exit = exit_callback; /* remember the callback for later */ 1022 + } 1023 + 1024 + int plugin_open(char *plugin, char *parameter) 1025 + { 1026 + open_plugin_add_path(ID2P(LANG_OPEN_PLUGIN), plugin, parameter); 1027 + return PLUGIN_GOTO_PLUGIN; 1020 1028 } 1021 1029 1022 1030 char *plugin_get_current_filename(void)
+3
apps/plugin.h
··· 49 49 50 50 char* strncpy(char *, const char *, size_t); 51 51 void* plugin_get_buffer(size_t *buffer_size); 52 + int plugin_open(char *plugin, char *parameter); 52 53 53 54 #ifndef __PCTOOL__ 54 55 #include "config.h" ··· 172 173 PLUGIN_USB_CONNECTED = INTERNAL_PLUGIN_RETVAL_START, 173 174 PLUGIN_POWEROFF, 174 175 PLUGIN_GOTO_WPS, 176 + PLUGIN_GOTO_PLUGIN, 175 177 PLUGIN_ERROR = -1, 176 178 }; 177 179 ··· 934 936 #ifdef HAVE_TAGCACHE 935 937 struct tagcache_stat* (*tagcache_get_stat)(void); 936 938 #endif 939 + int (*plugin_open)(char *path, char *parameter); 937 940 938 941 }; 939 942
+14 -5
apps/plugins/pictureflow/pictureflow.c
··· 533 533 static bool check_database(bool prompt) 534 534 { 535 535 bool needwarn = true; 536 + int spin = 5; 537 + 536 538 struct tagcache_stat *stat = rb->tagcache_get_stat(); 539 + 537 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 549 rb->splash(0, ID2P(LANG_TAGCACHE_BUSY)); 541 - if (!prompt) 550 + } 551 + else if (!prompt) 542 552 return false; 543 553 else if (rb->action_userabort(HZ/5)) 544 554 return false; 545 555 546 - needwarn = false; 556 + rb->yield(); 547 557 stat = rb->tagcache_get_stat(); 548 - rb->yield(); 549 558 } 550 559 return true; 551 560 } ··· 3841 3850 3842 3851 void * buf; 3843 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 3855 if (!check_database(prompt)) 3847 3856 {
+56 -18
apps/plugins/shortcuts/shortcuts_view.c
··· 22 22 23 23 #include "shortcuts.h" 24 24 25 - 25 + #define LOOP_EXIT 1 26 26 27 27 enum sc_list_action_type 28 28 { ··· 35 35 36 36 static char *link_filename; 37 37 static bool user_file; 38 - static bool usb_connected = false; 39 38 40 39 enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc); 41 40 ··· 43 42 static const char* build_sc_list(int selected_item, void *data, 44 43 char *buffer, size_t buffer_len); 45 44 46 - /* Returns true iff we should leave the main loop */ 47 - bool list_sc(void); 45 + /* Returns LOOP_EXIT iff we should leave the main loop */ 46 + int list_sc(void); 48 47 49 - bool goto_entry(char *file_or_dir); 48 + int goto_entry(char *file_or_dir); 50 49 bool ends_with(char *str, char *suffix); 51 50 52 51 ··· 104 103 } 105 104 106 105 107 - bool list_sc(void) 106 + int list_sc(void) 108 107 { 109 108 int selected_item = 0; 110 109 enum sc_list_action_type action = SCLA_NONE; ··· 122 121 /* Draw the prepared widget to the LCD now */ 123 122 action = draw_sc_list(&gui_sc); 124 123 if (action == SCLA_USB) { 125 - usb_connected = true; 126 - return true; 124 + return PLUGIN_USB_CONNECTED; 127 125 } 128 126 129 127 /* which item do we action? */ ··· 132 130 if (!is_valid_index(&sc_file, selected_item)) { 133 131 /* This should never happen */ 134 132 rb->splash(HZ*2, "Bad entry selected!"); 135 - return true; 133 + return PLUGIN_ERROR; 136 134 } 137 135 138 136 /* perform the following actions if the user "selected" ··· 145 143 rb->splashf(HZ, "Deleting %s", sc_file.entries[selected_item].disp); 146 144 remove_entry(&sc_file, selected_item); 147 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 147 default: 150 - return true; 148 + return LOOP_EXIT; 151 149 } 152 150 } 153 151 154 - 152 + #if 0 155 153 bool goto_entry(char *file_or_dir) 156 154 { 157 155 DEBUGF("Trying to go to '%s'...\n", file_or_dir); ··· 181 179 rb->set_current_file(file_or_dir); 182 180 return true; 183 181 } 182 + #endif 184 183 184 + int 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 + } 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 186 223 bool ends_with(char *string, char *suffix) 187 224 { ··· 195 232 196 233 enum plugin_status plugin_start(const void* void_parameter) 197 234 { 198 - bool leave_loop; 235 + int ret; 199 236 200 237 /* This is a viewer, so a parameter must have been specified */ 201 238 if (void_parameter == NULL) { ··· 219 256 /* if there's only one entry in the user .link file, 220 257 * go straight to it without displaying the menu 221 258 * thus allowing 'quick links' */ 222 - goto_entry(sc_file.entries[0].path); 223 - return PLUGIN_OK; 259 + return goto_entry(sc_file.entries[0].path); 224 260 } 225 261 226 262 FOR_NB_SCREENS(i) ··· 228 264 229 265 do { 230 266 /* Display a menu to choose between the entries */ 231 - leave_loop = list_sc(); 232 - } while (!leave_loop); 267 + ret = list_sc(); 268 + } while (ret == PLUGIN_OK); 269 + if (ret == LOOP_EXIT) 270 + ret = PLUGIN_OK; 233 271 234 272 FOR_NB_SCREENS(i) 235 273 rb->viewportmanager_theme_undo(i, false); 236 274 237 - return usb_connected ? PLUGIN_USB_CONNECTED : PLUGIN_OK; 275 + return ret; 238 276 }
+32 -14
apps/root_menu.c
··· 32 32 #include "kernel.h" 33 33 #include "debug.h" 34 34 #include "misc.h" 35 + #include "open_plugin.h" 35 36 #include "rolo.h" 36 37 #include "powermgmt.h" 37 38 #include "power.h" ··· 347 348 int result = do_menu(menu, NULL, NULL, false); 348 349 switch (result) 349 350 { 351 + case GO_TO_PLUGIN: 350 352 case GO_TO_PLAYLIST_VIEWER: 351 353 case GO_TO_WPS: 352 354 return result; ··· 703 705 return retval; 704 706 } 705 707 706 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 707 708 static int load_plugin_screen(char *plug_path, void* plug_param) 708 709 { 709 710 int ret_val; ··· 716 717 { 717 718 case PLUGIN_GOTO_WPS: 718 719 ret_val = GO_TO_WPS; 720 + break; 721 + case PLUGIN_GOTO_PLUGIN: 722 + ret_val = GO_TO_PLUGIN; 719 723 break; 720 724 case PLUGIN_OK: 721 725 ret_val = audio_status() ? GO_TO_PREVIOUS : GO_TO_ROOT; ··· 729 733 last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; 730 734 return ret_val; 731 735 } 732 - #endif 733 736 734 737 void root_menu(void) 735 738 { ··· 807 810 case GO_TO_ROOTITEM_CONTEXT: 808 811 next_screen = load_context_screen(selected); 809 812 break; 810 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 811 - case GO_TO_PICTUREFLOW: 813 + case GO_TO_PLUGIN: 812 814 { 813 - char pf_path[MAX_PATH]; 814 - char activity[6];/* big enough to display int */ 815 - snprintf(activity, sizeof(activity), "%d", get_current_activity()); 816 - snprintf(pf_path, sizeof(pf_path), 817 - "%s/pictureflow.rock", 818 - PLUGIN_DEMOS_DIR); 819 - 820 - next_screen = load_plugin_screen(pf_path, &activity); 821 - previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PICTUREFLOW; 815 + char *key; 816 + switch (last_screen) 817 + { 818 + case GO_TO_ROOT: 819 + key = ID2P(LANG_START_SCREEN); 820 + break; 821 + case GO_TO_WPS: 822 + key = ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN); 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 841 break; 823 842 } 824 - #endif 825 843 default: 826 844 #ifdef HAVE_TAGCACHE 827 845 /* With !HAVE_TAGCACHE previous_browser is always GO_TO_FILEBROWSER */
+1 -1
apps/root_menu.h
··· 55 55 GO_TO_FM, 56 56 #endif 57 57 GO_TO_RECENTBMARKS, 58 - GO_TO_PICTUREFLOW, 58 + GO_TO_PLUGIN, 59 59 /* Do Not add any items above here unless you want it to be able to 60 60 be the "start screen" after a boot up. The setting in settings_list.c 61 61 will need editing if this is the case. */
+23 -31
apps/settings_list.c
··· 38 38 #include "power.h" 39 39 #include "powermgmt.h" 40 40 #include "kernel.h" 41 + #include "open_plugin.h" 41 42 #ifdef HAVE_REMOTE_LCD 42 43 #include "lcd-remote.h" 43 44 #endif ··· 680 681 } 681 682 #endif 682 683 #ifdef HAVE_HOTKEY 684 + static 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 + } 683 689 static const char* hotkey_formatter(char* buffer, size_t buffer_size, int value, 684 690 const char* unit) 685 691 { ··· 694 700 return get_hotkey_lang_id(value); 695 701 } 696 702 #endif /* HAVE_HOTKEY */ 703 + 704 + static void start_in_callback(int var) 705 + { 706 + if (var - 2 == GO_TO_PLUGIN) 707 + open_plugin_browse(ID2P(LANG_START_SCREEN)); 708 + } 697 709 698 710 /* volume limiter */ 699 711 static void volume_limit_load_from_cfg(void* var, char*value) ··· 1872 1884 UNIT_SEC, formatter_time_unit_0_is_skip_track, 1873 1885 getlang_time_unit_0_is_skip_track, NULL, 1874 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 1888 "start in screen", "previous,root,files," 1877 1889 #ifdef HAVE_TAGCACHE 1878 1890 #define START_DB_COUNT 1 ··· 1893 1905 #else 1894 1906 #define START_TUNER_COUNT 0 1895 1907 #endif 1896 - "bookmarks" 1897 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1898 - #define START_PF_COUNT 1 1899 - ",pictureflow" 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), 1908 + "bookmarks," 1909 + "plugin" 1910 + , start_in_callback, 1911 + (7 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT), 1905 1912 ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU), 1906 1913 ID2P(LANG_DIR_BROWSER), 1907 1914 #ifdef HAVE_TAGCACHE ··· 1914 1921 #if CONFIG_TUNER 1915 1922 ID2P(LANG_FM_RADIO), 1916 1923 #endif 1917 - ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS) 1918 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 1919 - ,ID2P(LANG_ONPLAY_PICTUREFLOW) 1920 - #endif 1924 + ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS), 1925 + ID2P(LANG_OPEN_PLUGIN) 1921 1926 ), 1922 1927 SYSTEM_SETTING(NVRAM(1),last_screen,-1), 1923 1928 #if defined(HAVE_RTC_ALARM) && \ ··· 2098 2103 #endif 2099 2104 2100 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 2107 LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps", 2103 - "off,view playlist,show track info,pitchscreen,open with,delete,bookmark" 2104 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 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, 2108 + "off,view playlist,show track info,pitchscreen,open with,delete,bookmark,plugin" 2109 + ,UNIT_INT, hotkey_formatter, hotkey_getlang, hotkey_callback,8, HOTKEY_OFF, 2114 2110 HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN, 2115 - HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK 2116 - #ifdef HAVE_PICTUREFLOW_INTEGRATION 2117 - , HOTKEY_PICTUREFLOW 2118 - #endif 2119 - ), 2111 + HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK, HOTKEY_PLUGIN), 2120 2112 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree, 2121 2113 LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree", 2122 2114 "off,open with,delete,insert,insert shuffled",
+1
apps/settings_list.h
··· 100 100 }; 101 101 #define F_TABLE_SETTING 0x2000 102 102 #define F_ALLOW_ARBITRARY_VALS 0x4000 103 + #define F_CB_ON_SELECT_ONLY 0x20000 103 104 /* these use the _isfunc_type type for the function */ 104 105 /* typedef int (*_isfunc_type)(void); */ 105 106 #define F_MIN_ISFUNC 0x100000 /* min(above) is function pointer to above type */
+7
apps/shortcuts.c
··· 36 36 #include "lang.h" 37 37 #include "menu.h" 38 38 #include "misc.h" 39 + #include "open_plugin.h" 39 40 #include "tree.h" 40 41 #include "splash.h" 41 42 #include "pathfuncs.h" ··· 608 609 /* else fall through */ 609 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 618 struct browse_context browse; 612 619 browse_context_init(&browse, global_settings.dirfilter, 0, 613 620 NULL, NOICON, sc->u.path, NULL);
+2
apps/tree.c
··· 676 676 #endif 677 677 { 678 678 case GO_TO_FILEBROWSER: reload_dir = true; break; 679 + case GO_TO_PLUGIN: 680 + return GO_TO_PLUGIN; 679 681 case GO_TO_WPS: 680 682 return GO_TO_WPS; 681 683 #if CONFIG_TUNER
+6
manual/advanced_topics/main.tex
··· 36 36 the Main Menu Config Plugin (see \reference{ref:main_menu_config}). 37 37 It is not possible to change this setting via the settings menu. 38 38 39 + \subsection{\label{ref:OpenPlugins}Open Plugin Menu Items} 40 + 41 + Rockbox allows you to choose a plugin to run for select menu options. 42 + Simply choose the option in the setting menu and choose the plugin 43 + you would like to run. 44 + 39 45 \opt{lcd_bitmap}{ 40 46 \subsection{\label{ref:GettingExtras}Getting Extras} 41 47
+1
manual/configure_rockbox/main.tex
··· 21 21 }} 22 22 \input{configure_rockbox/language.tex} 23 23 \input{configure_rockbox/voice.tex} 24 + \input{configure_rockbox/wps_context_plugin.tex} 24 25 \input{configure_rockbox/hotkey_settings.tex} 25 26 26 27 \chapter{Theme Settings}
+5
manual/configure_rockbox/wps_context_plugin.tex
··· 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}