1
0
Fork 0
forked from len0rd/rockbox

WIP open_plugins.rock viewer

OP allows you to use Open With.. to call plugins with parameters
called directly it  acts as a shortcut list for plugins

  open_plugins.rock interfaces with the open_plugin core

  When opened directly it acts as a viewer for the plugin.dat file
  this allows you to edit the paths and parameters for
  core shortcuts as well as your added plugins

  If a plugin is supplied to the viewer it is added to the dat file

  If instead the plugin has previously been added then it is run
  with the parameters you previously supplied

-----------------------------------------------------------------------------
Added export to .opx files
this allows shortcuts to plugins with parameters to be called from
 the file browser

Change-Id: Ib8b05a60b049fb1d5881031ca09a07e3307d375a
This commit is contained in:
William Wilgus 2020-08-17 11:05:26 -04:00
parent 96e1bb6556
commit 889bcc0f76
7 changed files with 936 additions and 0 deletions

View file

@ -16206,3 +16206,101 @@
*: "Parameter"
</voice>
</phrase>
<phrase>
id: LANG_NAME
desc:
user: core
<source>
*: "Name"
</source>
<dest>
*: "Name"
</dest>
<voice>
*: "Name"
</voice>
</phrase>
<phrase>
id: LANG_ADD
desc:
user: core
<source>
*: "Add"
</source>
<dest>
*: "Add"
</dest>
<voice>
*: "Add"
</voice>
</phrase>
<phrase>
id: LANG_BACK
desc:
user: core
<source>
*: "Back"
</source>
<dest>
*: "Back"
</dest>
<voice>
*: "Back"
</voice>
</phrase>
<phrase>
id: LANG_EDIT
desc:
user: core
<source>
*: "Edit"
</source>
<dest>
*: "Edit"
</dest>
<voice>
*: "Edit"
</voice>
</phrase>
<phrase>
id: LANG_RUN
desc:
user: core
<source>
*: "Run"
</source>
<dest>
*: "Run"
</dest>
<voice>
*: "Run"
</voice>
</phrase>
<phrase>
id: LANG_EXPORT
desc:
user: core
<source>
*: "Export"
</source>
<dest>
*: "Export"
</dest>
<voice>
*: "Export"
</voice>
</phrase>
<phrase>
id: LANG_BROWSE
desc:
user: core
<source>
*: "Browse"
</source>
<dest>
*: "Browse"
</dest>
<voice>
*: "Browse"
</voice>
</phrase>

View file

@ -67,6 +67,7 @@ mosaique,demos
mp3_encoder,apps
mpegplayer,viewers
nim,games
open_plugins,viewers
oscilloscope,demos
otp,apps
pacbox,games

View file

@ -137,6 +137,7 @@ chopper.c
demystify.c
jewels.c
minesweeper.c
open_plugins.c
oscilloscope.c
pegbox.c
periodic_table.c

823
apps/plugins/open_plugins.c Normal file
View file

@ -0,0 +1,823 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
* Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2020 William Wilgus
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
/* open_plugins.rock interfaces with the open_plugin core
*
* When opened directly it acts as a viewer for the plugin.dat file
* this allows you to edit the paths and parameters for
* core shortcuts as well as your added plugins
*
* If a plugin is supplied to the viewer it is added to the dat file
*
* If instead the plugin has previously been added then it is run
* with the parameters previously supplied
*/
#include "plugin.h"
#include "lang_enum.h"
#include "../open_plugin.h"
#define ROCK_EXT "rock"
#define OP_EXT "opx"
#define OP_PLUGIN_RESTART (PLUGIN_GOTO_PLUGIN | 0x8000)
#define MENU_ID_MAIN "0"
#define MENU_ID_EDIT "1"
static int fd_dat;
static struct gui_synclist lists;
struct open_plugin_entry_t op_entry;
const off_t op_entry_sz = sizeof(struct open_plugin_entry_t);
/* we only need the names for the first menu so don't bother reading paths yet */
const off_t op_name_sz = OPEN_PLUGIN_NAMESZ + (op_entry.name - (char*)&op_entry);
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter);
static bool _yesno_pop(const char* text)
{
const char *lines[]={text};
const struct text_message message={lines, 1};
bool ret = (rb->gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
FOR_NB_SCREENS(i)
rb->screens[i]->clear_viewport();
return ret;
}
static size_t pathbasename(const char *name, const char **nameptr)
{
const char *p = name;
const char *q = p;
const char *r = q;
while (*(p = GOBBLE_PATH_SEPCH(p)))
{
q = p;
p = GOBBLE_PATH_COMP(++p);
r = p;
}
if (r == name && p > name)
q = p, r = q--; /* root - return last slash */
/* else path is an empty string */
*nameptr = q;
return r - q;
}
static bool op_entry_read(int fd, int selected_item, off_t data_sz)
{
rb->memset(&op_entry, 0, op_entry_sz);
op_entry.lang_id = -1;
return ((selected_item >= 0) &&
(rb->lseek(fd, selected_item * op_entry_sz, SEEK_SET) >= 0) &&
(rb->read(fd, &op_entry, data_sz) == data_sz));
}
static bool op_entry_read_name(int fd, int selected_item)
{
return op_entry_read(fd, selected_item, op_name_sz);
}
static void op_entry_export(int selection)
{
int len;
int fd = -1;
char filename [MAX_PATH + 1];
if (!op_entry_read(fd_dat, selection, op_entry_sz))
goto failure;
rb->snprintf(filename, MAX_PATH, "%s/%s", PLUGIN_APPS_DIR, op_entry.name);
if( !rb->kbd_input( filename, MAX_PATH, NULL ) )
{
len = rb->strlen(filename);
if(len > 4 && filename[len] != PATH_SEPCH &&
rb->strcasecmp(&((filename)[len-4]), "." OP_EXT) != 0)
{
rb->strcat(filename, "." OP_EXT);
}
fd = rb->open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd >= 0 && rb->write(fd, &op_entry, op_entry_sz) == op_entry_sz)
{
rb->close(fd);
rb->splashf( 1*HZ, "File Saved (%s)", filename );
return;
}
rb->close(fd);
}
failure:
rb->splashf( 2*HZ, "Save Failed (%s)", filename );
}
static void op_entry_set_name(void)
{
char tmp_buf[OPEN_PLUGIN_NAMESZ+1];
rb->strlcpy(tmp_buf, op_entry.name, OPEN_PLUGIN_NAMESZ);
if (rb->kbd_input(tmp_buf, OPEN_PLUGIN_NAMESZ, NULL) >= 0)
rb->strlcpy(op_entry.name, tmp_buf, OPEN_PLUGIN_NAMESZ);
}
static int op_entry_set_path(void)
{
int ret = 0;
struct browse_context browse;
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
if (op_entry.path[0] == '\0')
rb->strcpy(op_entry.path, PLUGIN_DIR"/");
rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "",
Icon_Plugin, op_entry.path, NULL);
browse.buf = tmp_buf;
browse.bufsize = OPEN_PLUGIN_BUFSZ;
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
ret = rb->strlcpy(op_entry.path, tmp_buf, OPEN_PLUGIN_BUFSZ);
if (ret > OPEN_PLUGIN_BUFSZ)
ret = 0;
}
return ret;
}
static int op_entry_set_param_path(void)
{
int ret = 0;
struct browse_context browse;
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
if (op_entry.param[0] == '\0')
rb->strcpy(tmp_buf, "/");
else
rb->strcpy(tmp_buf, op_entry.param);
rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "",
Icon_Plugin, tmp_buf, NULL);
browse.buf = tmp_buf;
browse.bufsize = OPEN_PLUGIN_BUFSZ;
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
ret = rb->strlcpy(op_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
if (ret > OPEN_PLUGIN_BUFSZ)
ret = 0;
}
return ret;
}
static void op_entry_set_param(void)
{
if (_yesno_pop(ID2P(LANG_BROWSE)))
op_entry_set_param_path();
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
rb->strlcpy(tmp_buf, op_entry.param, OPEN_PLUGIN_BUFSZ);
if (rb->kbd_input(tmp_buf, OPEN_PLUGIN_BUFSZ, NULL) >= 0)
rb->strlcpy(op_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
}
static int op_et_exclude_hash(struct open_plugin_entry_t *op_entry, int item, void *data)
{
(void)item;
if (op_entry->hash == 0 || op_entry->name[0] == '\0')
return 0;
if (data)
{
uint32_t *hash = data;
if (op_entry->hash != *hash)
return 1;
}
return 0;
}
static int op_et_exclude_builtin(struct open_plugin_entry_t *op_entry, int item, void *data)
{
(void)item;
(void)data;
if (op_entry->lang_id >= 0)
return 0;
else if(op_entry->hash == 0 || op_entry->name[0] == '\0')
return 0;
return 1;
}
static int op_et_exclude_user(struct open_plugin_entry_t *op_entry, int item, void *data)
{
(void)item;
(void)data;
if (op_entry->lang_id < 0)
return 0;
else if (op_entry->hash == 0 || op_entry->name[0] == '\0')
return 0;
return 1;
}
static int op_entry_transfer(int fd, int fd_tmp,
int(*compfn)(struct open_plugin_entry_t*, int, void*),
void *data)
{
int entries = -1;
if (fd_tmp && fd && rb->lseek(fd, 0, SEEK_SET) == 0)
{
entries = 0;
while (rb->read(fd, &op_entry, op_entry_sz) == op_entry_sz)
{
if (compfn && compfn(&op_entry, entries, data) > 0)
{
rb->write(fd_tmp, &op_entry, op_entry_sz);
entries++;
}
}
}
return entries + 1;
}
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter)
{
int len;
uint32_t hash;
char *pos = "";;
int fd_tmp = -1;
if (key)
{
open_plugin_get_hash(key, &hash);
op_entry.hash = hash;
}
else if (op_entry.lang_id < 0 && plugin)
{
/* need to keep the old hash so we can remove the old entry */
hash = op_entry.hash;
open_plugin_get_hash(plugin, &op_entry.hash);
}
else
hash = op_entry.hash;
if (plugin)
{
/* name */
if (pathbasename(plugin, (const char **)&pos) == 0)
pos = "\0";
if (op_entry.name[0] == '\0' || op_entry.lang_id >= 0)
rb->strlcpy(op_entry.name, pos, OPEN_PLUGIN_NAMESZ);
len = rb->strlen(pos);
if(len > 5 && rb->strcasecmp(&(pos[len-5]), "." ROCK_EXT) == 0)
{
fd_tmp = rb->open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd_tmp < 0)
return 0;
/* path */
if (plugin != op_entry.path)
rb->strlcpy(op_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
if(parameter)
{
if (parameter[0] == '\0' &&
_yesno_pop(ID2P(LANG_PARAMETER)))
{
op_entry_set_param();
}
else
rb->strlcpy(op_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
}
rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */
}
else
{
if (op_entry.lang_id != LANG_SHORTCUTS)
rb->splashf(HZ / 2, rb->str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos);
return 0;
}
}
if (op_entry_transfer(fd_dat, fd_tmp, op_et_exclude_hash, &hash) > 0)
{
rb->close(fd_tmp);
rb->close(fd_dat);
rb->remove(OPEN_PLUGIN_DAT);
rb->rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
}
else
{
rb->close(fd_tmp);
rb->remove(OPEN_PLUGIN_DAT ".tmp");
hash = 0;
}
return hash;
}
void op_entry_browse_add(int selection)
{
char* key;
op_entry_read(fd_dat, selection, op_entry_sz);
if (op_entry_set_path() > 0)
{
if (op_entry.lang_id >= 0)
key = rb->str(op_entry.lang_id);
else
key = op_entry.path;
op_entry_add_path(key, op_entry.path, NULL);
}
}
static void op_entry_remove(int selection)
{
int entries = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
int32_t hash = 0;
int lang_id = -1;
if (entries > 0 && _yesno_pop(ID2P(LANG_REMOVE)))
{
op_entry_read(fd_dat, selection, op_entry_sz);
if (rb->lseek(fd_dat, selection * op_entry_sz, SEEK_SET) >= 0)
{
if (op_entry.lang_id >= 0)
{
lang_id = op_entry.lang_id;
hash = op_entry.hash;
}
rb->memset(&op_entry, 0, op_entry_sz);
op_entry.lang_id = lang_id;
op_entry.hash = hash;
rb->write(fd_dat, &op_entry, op_entry_sz);
}
}
}
static void op_entry_remove_empty(void)
{
bool resave = false;
if (fd_dat && rb->lseek(fd_dat, 0, SEEK_SET) == 0)
{
while (resave == false &&
rb->read(fd_dat, &op_entry, op_entry_sz) == op_entry_sz)
{
if (op_entry.hash == 0)
resave = true;
}
}
if (resave)
{
int fd_tmp = rb->open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd_tmp < 0)
return;
if ((op_entry_transfer(fd_dat, fd_tmp, &op_et_exclude_builtin, NULL)
+ op_entry_transfer(fd_dat, fd_tmp, &op_et_exclude_user, NULL)) > 0)
{
rb->close(fd_tmp);
rb->close(fd_dat);
rb->remove(OPEN_PLUGIN_DAT);
rb->rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
}
else
{
rb->close(fd_tmp);
rb->remove(OPEN_PLUGIN_DAT ".tmp");
}
}
}
static int op_entry_run(void)
{
int ret = PLUGIN_ERROR;
char* path;
char* param;
if (op_entry.hash != 0 && op_entry.path[0] != '\0')
{
rb->splash(1, ID2P(LANG_OPEN_PLUGIN));
path = op_entry.path;
param = op_entry.param;
if (param[0] == '\0')
param = NULL;
ret = rb->plugin_open(path, param);
}
return ret;
}
static const char* list_get_name_cb(int selected_item, void* data,
char* buf, size_t buf_len)
{
/*TODO memoize names so we don't keep reading the disk when not necessary */
if (data == &MENU_ID_MAIN)
{
if (op_entry_read_name(fd_dat, selected_item))
{
if (op_entry.lang_id >= 0)
rb->snprintf(buf, buf_len, "%s [%s] ",
rb->str(op_entry.lang_id), op_entry.name);
else if (rb->strlcpy(buf, op_entry.name, buf_len) >= buf_len)
rb->strcpy(&buf[buf_len-10], " ...");
}
else
return "?";
}
else /* op_entry should already be loaded */
{
switch(selected_item)
{
case 0:
return ID2P(LANG_NAME);
case 1:
if (op_entry.lang_id >= 0)
rb->snprintf(buf, buf_len, "%s [%s] ",
rb->str(op_entry.lang_id), op_entry.name);
else if (rb->strlcpy(buf, op_entry.name, buf_len) >= buf_len)
rb->strcpy(&buf[buf_len-10], " ...");
break;
case 2:
return ID2P(LANG_DISPLAY_FULL_PATH);
case 3:
if (rb->strlcpy(buf, op_entry.path, buf_len) >= buf_len)
rb->strcpy(&buf[buf_len-10], " ...");
break;
case 4:
return ID2P(LANG_PARAMETER);
case 5:
if (op_entry.param[0] == '\0')
return "[NULL]";
else if (rb->strlcpy(buf, op_entry.param, buf_len) >= buf_len)
rb->strcpy(&buf[buf_len-10], " ...");
break;
case 6:
return "";
case 7:
return ID2P(LANG_BACK);
default:
return "?";
}
}
return buf;
}
static int list_voice_cb(int list_index, void* data)
{
if (data == &MENU_ID_MAIN)
{
if (op_entry_read_name(fd_dat, list_index))
{
if (op_entry.lang_id >= 0)
{
rb->talk_id(op_entry.lang_id, false);
rb->talk_id(VOICE_PAUSE, true);
rb->talk_force_enqueue_next();
}
return rb->talk_spell(op_entry.name, false);
}
}
else
{
switch(list_index)
{
case 0:
rb->talk_id(LANG_NAME, false);
rb->talk_id(VOICE_PAUSE, true);
if (op_entry.lang_id >= 0)
{
rb->talk_id(op_entry.lang_id, true);
rb->talk_id(VOICE_PAUSE, true);
rb->talk_force_enqueue_next();
}
return rb->talk_spell(op_entry.name, false);
case 2:
return rb->talk_id(LANG_DISPLAY_FULL_PATH, false);
case 4:
return rb->talk_id(LANG_PARAMETER, false);
case 6:
return rb->talk_id(LANG_BACK, false);
default:
return 0;
}
}
return 0;
}
static void synclist_set(char* menu_id, int selection, int items, int sel_size)
{
if (selection < 0)
selection = 0;
rb->gui_synclist_init(&lists,list_get_name_cb,
menu_id, false, sel_size, NULL);
rb->gui_synclist_set_icon_callback(&lists,NULL);
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
rb->gui_synclist_set_nb_items(&lists,items);
rb->gui_synclist_limit_scroll(&lists,true);
rb->gui_synclist_select_item(&lists, selection);
list_voice_cb(selection, menu_id);
}
static int context_menu_cb(int action,
const struct menu_item_ex *this_item,
struct gui_synclist *this_list)
{
(void)this_item;
int selection = rb->gui_synclist_get_sel_pos(this_list);
if(action == ACTION_ENTER_MENUITEM)
{
if (selection == 0 &&
op_entry.lang_id >= 0 && op_entry.lang_id != LANG_OPEN_PLUGIN)
{
rb->gui_synclist_set_title(this_list,
rb->str(op_entry.lang_id), 0);
}
}
else if ((action == ACTION_STD_OK))
{
/*Run, Edit, Remove, Export, Blank, Import, Add, Back*/
switch(selection)
{
case 0:case 1:case 2:case 3:case 5:
return ACTION_STD_OK;
case 4: /*blank*/
break;
default:
return ACTION_STD_CANCEL;
}
rb->gui_synclist_draw(this_list); /* redraw */
return 0;
}
return action;
}
static void edit_menu(int selection)
{
int selected_item;
bool exit = false;
int action = 0;
if (!op_entry_read(fd_dat, selection, op_entry_sz))
return;
uint32_t crc = rb->crc_32(&op_entry, op_entry_sz, 0xffffffff);
synclist_set(MENU_ID_EDIT, 2, 8, 2);
rb->gui_synclist_draw(&lists);
while (!exit)
{
action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
continue;
selected_item = rb->gui_synclist_get_sel_pos(&lists);
switch (action)
{
case ACTION_STD_OK:
if (selected_item == 0)
op_entry_set_name();
else if (selected_item == 2)
op_entry_set_path();
else if (selected_item == 4)
op_entry_set_param();
else
exit = true;
rb->gui_synclist_draw(&lists);
break;
case ACTION_STD_CANCEL:
exit = true;
break;
}
}
if (crc != rb->crc_32(&op_entry, op_entry_sz, 0xffffffff) &&
_yesno_pop(ID2P(LANG_SAVE)) == true)
{
char *param = op_entry.param;
if (param[0] == '\0')
param = NULL;
op_entry_add_path(NULL, op_entry.path, param);
fd_dat = rb->open(OPEN_PLUGIN_DAT, O_RDWR, 0666);
}
}
static int context_menu(int selection)
{
int selected_item;
if (op_entry_read(fd_dat, selection, op_entry_sz))
{
MENUITEM_STRINGLIST(menu, op_entry.name, context_menu_cb,
ID2P(LANG_RUN), ID2P(LANG_EDIT), ID2P(LANG_REMOVE), ID2P(LANG_EXPORT),
ID2P(VOICE_BLANK), ID2P(LANG_ADD), ID2P(LANG_BACK));
selected_item = rb->do_menu(&menu, 0, NULL, false);
switch (selected_item)
{
case 0: /*run*/
return PLUGIN_GOTO_PLUGIN;
case 1: /*edit*/
edit_menu(selection);
break;
case 2: /*remove*/
op_entry_remove(selection);
break;
case 3: /*export*/
op_entry_export(selection);
break;
case 4: /*blank*/
break;
case 5: /*add*/
op_entry_browse_add(-1);
rb->plugin_open(rb->plugin_get_current_filename(), "\0");
return OP_PLUGIN_RESTART;
default:
break;
}
return PLUGIN_OK;
}
return PLUGIN_ERROR;
}
enum plugin_status plugin_start(const void* parameter)
{
int ret = PLUGIN_OK;
uint32_t hash = 0;
int item = -1;
int selection = -1;
int action;
int items;
int len;
int fd_opx;
off_t filesize;
char *path;
bool exit = false;
const int creat_flags = O_RDWR | O_CREAT;
fd_dat = rb->open(OPEN_PLUGIN_DAT, creat_flags, 0666);
if (!fd_dat)
exit = true;
items = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
if (items == 0 && !parameter)
{
rb->plugin_open(rb->plugin_get_current_filename(), NULL);
rb->close(fd_dat);
return PLUGIN_GOTO_PLUGIN;
}
if (parameter)
{
path = (char*)parameter;
len = rb->strlen(path);
if(len > 4 && rb->strcasecmp(&((path)[len-4]), "." OP_EXT) == 0)
{
fd_opx = rb->open(path, O_RDONLY, 0666);
if (fd_opx)
{
filesize = rb->filesize(fd_opx);
if (filesize == op_entry_sz)
{
if (op_entry_read(fd_opx, 0, op_entry_sz))
{
exit = true;
ret = op_entry_run();
}
else
rb->splashf(HZ, rb->str(LANG_READ_FAILED), path);
}
else if (filesize != 0)
rb->splashf(2 * HZ, rb->str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), path);
rb->close(fd_opx);
}
}
else
{
open_plugin_get_hash(parameter, &hash);
rb->lseek(fd_dat, 0, SEEK_SET);
while (rb->read(fd_dat, &op_entry, op_entry_sz) == op_entry_sz)
{
item++;
if (op_entry.hash == hash)
{
selection = item;
break;
}
}
if (selection >= 0)
{
if (op_entry_read(fd_dat, selection, op_entry_sz))
{
if (op_entry_run() == PLUGIN_GOTO_PLUGIN)
return PLUGIN_GOTO_PLUGIN;
}
}
else
{
op_entry_read(fd_dat, selection, op_entry_sz);
op_entry_add_path(parameter, parameter, "\0");
selection = 0;
items++;
fd_dat = rb->open(OPEN_PLUGIN_DAT, creat_flags, 0666);
if (!fd_dat)
exit = true;
}
}/* OP_EXT */
}
if (!exit)
{
synclist_set(MENU_ID_MAIN, selection, items, 1);
rb->gui_synclist_draw(&lists);
while (!exit)
{
action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
continue;
selection = rb->gui_synclist_get_sel_pos(&lists);
switch (action)
{
case ACTION_STD_CONTEXT:
ret = context_menu(selection);
if (ret == OP_PLUGIN_RESTART)
{
ret = PLUGIN_GOTO_PLUGIN;
exit = true;
break;
}
else if (ret != PLUGIN_GOTO_PLUGIN)
{
synclist_set(MENU_ID_MAIN, selection, items, 1);
rb->gui_synclist_draw(&lists);
break;
}
case ACTION_STD_OK:
if (op_entry_read(fd_dat, selection, op_entry_sz))
{
ret = op_entry_run();
exit = true;
}
break;
case ACTION_STD_CANCEL:
{
selection = -2;
exit = true;
break;
}
}
}
op_entry_remove_empty();
}
rb->close(fd_dat);
if (ret != PLUGIN_OK)
return ret;
else
return PLUGIN_OK;
}

View file

@ -86,6 +86,11 @@ $(OVERLAYREF_LDS): $(PLUGIN_LDS)
$(BUILDDIR)/credits.raw credits.raw: $(DOCSDIR)/CREDITS
$(call PRINTS,Create credits.raw)perl $(APPSDIR)/plugins/credits.pl < $< > $(BUILDDIR)/$(@F)
$(BUILDDIR)/apps/plugins/open_plugins.opx:
$(call PRINTS,MK open_plugins.opx) touch $< $(BUILDDIR)/apps/plugins/open_plugins.opx
$(BUILDDIR)/apps/plugins/open_plugins.rock: $(BUILDDIR)/apps/plugins/open_plugins.opx
# special dependencies
$(BUILDDIR)/apps/plugins/wav2wv.rock: $(RBCODEC_BLD)/codecs/libwavpack.a $(PLUGIN_LIBS)

View file

@ -77,6 +77,8 @@ mpv,viewers/mpegplayer,4
m2v,viewers/mpegplayer,4
iriver,viewers/iriver_flash,3
tap,viewers/zxbox,12
opx,viewers/open_plugins,-
rock,viewers/open_plugins,-
sna,viewers/zxbox,12
tzx,viewers/zxbox,12
z80,viewers/zxbox,12

View file

@ -518,6 +518,12 @@ sub buildzip {
copy("$ROOT/apps/tagnavi.config", "$temp_dir/");
copy("$ROOT/apps/plugins/disktidy.config", "$temp_dir/rocks/apps/");
if(-e "$temp_dir/rocks/viewers/open_plugins.rock") {
my $cwd = getcwd();
copy("$cwd/apps/plugins/open_plugins.opx", "$temp_dir/rocks/apps/open_plugins.opx") or
print STDERR "Copy failed: $cwd/apps/plugins/open_plugins.opx $!\n";
}
if($bitmap) {
copy("$ROOT/apps/plugins/sokoban.levels", "$temp_dir/rocks/games/sokoban.levels"); # sokoban levels
copy("$ROOT/apps/plugins/snake2.levels", "$temp_dir/rocks/games/snake2.levels"); # snake2 levels