summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-07-30 12:47:36 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2024-07-30 14:55:07 -0400
commite3097bf92c9fc74ed3b724caf338dd24d7f21621 (patch)
treea35143bc929914630258467cca20880e732ad147
parentef9490f68329821fc36b2ef9d3c19dc6d7698c55 (diff)
downloadrockbox-e3097bf92c.tar.gz
rockbox-e3097bf92c.zip
[Feature] File Picker Plugin
allows viewers to pop a file browser to let the user pick a relevant file which then gets run by the viewer (only lua so far) Change-Id: I7e6b4c2827fab5e9f596d336f546100636c4b871
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/file_picker.c295
-rw-r--r--apps/plugins/lua/rocklua.c17
5 files changed, 328 insertions, 0 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index aa13faf77d..0635f7b569 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16486,3 +16486,17 @@
*: none
</voice>
</phrase>
+<phrase>
+ id: LANG_CHOOSE_FILE
+ desc: file_picker plugin ask user to select a file
+ user: core
+ <source>
+ *: "Choose File"
+ </source>
+ <dest>
+ *: "Choose File"
+ </dest>
+ <voice>
+ *: "Choose File"
+ </voice>
+</phrase>
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 814fb2f130..79186b7aed 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -35,6 +35,7 @@ doom,games
duke3d,games
euroconverter,apps
fft,demos
+file_picker,viewers
fire,demos
fireworks,demos
firmware_flash,apps
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 0b1d48d5de..a070637a77 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -12,6 +12,7 @@ cube.c
cue_playlist.c
dart_scorer.c
dict.c
+file_picker.c
jackpot.c
keybox.c
keyremap.c
diff --git a/apps/plugins/file_picker.c b/apps/plugins/file_picker.c
new file mode 100644
index 0000000000..ce9d81728e
--- /dev/null
+++ b/apps/plugins/file_picker.c
@@ -0,0 +1,295 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2024 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.
+ *
+ ****************************************************************************/
+/*File Picker Plugin
+
+FPP accepts several arguments to help in your file picking adventure
+* NOTE: anything with spaces should be quoted, -f and -l can't be used together *
+ -r "<GOTO_PLUGIN_NAME>" doesn't need to be a full path demos/file.rock works
+ the file (if choosen, cancel exits) will be passed as a parameter
+ -t "<TITLE ( max 64 chars )>"
+ -s "<START DIR>"
+ -f "<.EXT (max 64 chars) >" the extension of the files you are looking for
+ must have the '.' and ".*" accepts any file
+ -l "<.EXT.EXT,.EXT .EXT (max 64 chars) >" list of extensions for files you are looking for
+ each must have the '.' spaces and commas are ignored
+ -a attrib flags eg FILE_ATTR_AUDIO
+ -d disallow changing directories (hide directories doesn't allow changing from start dir)
+*/
+#include "plugin.h"
+#include "lang_enum.h"
+#include "lib/arg_helper.h"
+
+#if defined(DEBUG) || defined(SIMULATOR)
+ #define logf(...) rb->debugf(__VA_ARGS__); rb->debugf("\n")
+#elif defined(ROCKBOX_HAS_LOGF)
+ #define logf rb->logf
+#else
+ #define logf(...) do { } while(0)
+#endif
+
+#define FIND_NODIRS 0x01
+#define FIND_ATTRIB 0x02
+#define FIND_WILDCARD 0x04
+#define FIND_EXT 0x08
+#define FIND_EXT_IN_LIST 0x10
+
+static struct fpp
+{
+ char return_plugin[MAX_PATH];
+ char start_dir[MAX_PATH];
+ char file_ext[64];
+ char title[64];
+ int tree_attr;
+ int flags;
+}fpp;
+
+static int arg_callback(char argchar, const char **parameter, void *userdata)
+{
+ struct fpp *pfp = userdata;
+ int ret;
+ long num;
+ const char* start = *parameter;
+ while (*parameter[0] > '/' && ispunct(*parameter[0])) (*parameter)++;
+ switch (tolower(argchar))
+ {
+ case 'd' :
+ pfp->flags |= FIND_NODIRS;
+ logf ("Find no dirs");
+ break;
+ case 'r' : /*return_plugin*/
+ logf ("trying PLUGIN_DIR...");
+ size_t l = rb->strlcpy(pfp->return_plugin,
+ PLUGIN_DIR,
+ sizeof(pfp->return_plugin));
+
+ ret = string_parse(parameter,
+ pfp->return_plugin + l,
+ sizeof(pfp->return_plugin) - l);
+
+ if (ret && !rb->file_exists(pfp->return_plugin))
+ {
+ logf("Failed");
+ *parameter = start;
+ string_parse(parameter, pfp->return_plugin,
+ sizeof(pfp->return_plugin));
+ }
+
+ if (ret)
+ {
+ logf ("Ret plugin: Val: %s\n", pfp->return_plugin);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ case 't' : /* title */
+ ret = string_parse(parameter, pfp->title, sizeof(pfp->title));
+ if (ret)
+ {
+ logf ("Title: Val: %s\n", pfp->title);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ case 's' : /* start directory */
+ ret = string_parse(parameter, pfp->start_dir, sizeof(pfp->start_dir));
+ if (ret)
+ {
+ if (!rb->dir_exists(pfp->start_dir))
+ {
+ rb->strlcpy(pfp->start_dir, PATH_ROOTSTR, sizeof(pfp->start_dir));
+ }
+
+ logf ("Start dir: Val: %s\n", pfp->start_dir);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ case 'f' : /* file extension */
+ if (pfp->flags & FIND_EXT_IN_LIST)
+ {
+ rb->splash(HZ*5, "list extensions already active -f ignored");
+ break;
+ }
+ ret = string_parse(parameter, pfp->file_ext, sizeof(pfp->file_ext));
+ if (ret)
+ {
+ if (pfp->file_ext[1] == '*')
+ pfp->flags |= FIND_WILDCARD;
+ else
+ pfp->flags |= FIND_EXT;
+ logf ("Extension: Val: %s\n", pfp->file_ext);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ case 'l' : /* file extension list */
+ if (pfp->flags & FIND_EXT)
+ {
+ rb->splash(HZ*5, "extension already active -l ignored");
+ break;
+ }
+ ret = string_parse(parameter, pfp->file_ext, sizeof(pfp->file_ext));
+ if (ret)
+ {
+ char *wr = pfp->file_ext;
+ char *rd = pfp->file_ext;
+ while (*rd != '\0') /* copy the extensions */
+ {
+ if (*rd == ' ' || *rd == ',' || *rd == ';')
+ {
+ /* ignore spaces, commas, and semicolons */
+ rd++;
+ continue;
+ }
+ *wr++ = *rd++;
+ }
+ *wr = '\0';
+ pfp->flags |= FIND_EXT_IN_LIST;
+ logf ("Extension List: Val: %s\n", pfp->file_ext);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ case 'a' : /* tree attribute */
+ ret = longnum_parse(parameter, &num, NULL);
+ if (ret)
+ {
+ pfp->tree_attr = (num)&FILE_ATTR_MASK;
+ pfp->flags |= FIND_ATTRIB;
+ logf ("Attrib: Val: 0x%x\n", (uint32_t)num);
+ logf("ate %d chars\n", ret);
+ }
+ break;
+ default :
+ rb->splashf(HZ, "Unknown switch '%c'",argchar);
+ logf("Unknown switch '%c'",argchar);
+ //return 0;
+ }
+
+ return 1;
+}
+
+static bool cb_show_item(char *name, int attr, struct tree_context *tc)
+{
+ static int dirlevel = -1;
+ if(attr & ATTR_DIRECTORY)
+ {
+ if (fpp.flags & FIND_NODIRS)
+ {
+ if (tc->dirlevel == dirlevel)
+ return false;
+ dirlevel = tc->dirlevel;
+ if (rb->strcasestr(tc->currdir, fpp.start_dir) == NULL)
+ {
+ tc->is_browsing = false; /* exit immediately */
+ logf("exiting %d", tc->dirlevel);
+ }
+ }
+
+ return true;
+ }
+ if (fpp.flags & FIND_WILDCARD)
+ {
+ return true;
+ }
+ if ((fpp.flags & FIND_ATTRIB) && (fpp.tree_attr & attr) != 0)
+ {
+ return true;
+ }
+ if (fpp.flags & FIND_EXT)
+ {
+ const char *p = rb->strrchr(name, '.' );
+ if (p != NULL && !rb->strcasecmp( p, fpp.file_ext))
+ return true;
+ }
+
+ if (fpp.flags & FIND_EXT_IN_LIST)
+ {
+ const char *p = rb->strrchr(name, '.' );
+ if (p != NULL && rb->strcasestr(fpp.file_ext, p) != NULL)
+ return true;
+ }
+
+ logf("Excluded: %s", name);
+ return false;
+
+}
+
+static int browse_file_dir(struct fpp *pfp)
+{
+ char buf[MAX_PATH];
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY | BROWSE_DIRFILTER,
+ .title = pfp->title,
+ .icon = Icon_Playlist,
+ .buf = buf,
+ .bufsize = sizeof(buf),
+ .root = pfp->start_dir,
+ .callback_show_item = &cb_show_item,
+ };
+
+ if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
+ {
+ if (rb->file_exists(buf))
+ {
+ logf("Loading %s", buf);
+ return rb->plugin_open(pfp->return_plugin, buf);
+ }
+ else
+ {
+ logf("Error opening %s", buf);
+ rb->splashf(HZ *2, "Error Opening %s", buf);
+ return PLUGIN_ERROR;
+ }
+ }
+
+ return PLUGIN_OK;
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ if (!parameter)
+ {
+ rb->splash(HZ *2, "No Args");
+ return PLUGIN_ERROR;
+ }
+
+ argparse((const char*) parameter, -1, &fpp, &arg_callback);
+
+ if (fpp.title[0] == '\0')
+ {
+ if (rb->global_settings->talk_menu)
+ rb->talk_id(LANG_CHOOSE_FILE, true);
+
+ if ((fpp.flags & FIND_EXT) || (fpp.flags & FIND_EXT_IN_LIST))
+ {
+ rb->snprintf(fpp.title, sizeof(fpp.title),
+ "%s (%s)", rb->str(LANG_CHOOSE_FILE), fpp.file_ext);
+ if (rb->global_settings->talk_menu)
+ rb->talk_spell(fpp.file_ext, true);
+ }
+ else
+ {
+ rb->snprintf(fpp.title, sizeof(fpp.title), "%s", rb->str(LANG_CHOOSE_FILE));
+ }
+ rb->talk_force_enqueue_next();
+ }
+ if (fpp.start_dir[0] == '\0' || !rb->dir_exists(fpp.start_dir))
+ rb->strcpy(fpp.start_dir, PATH_ROOTSTR);
+
+ return browse_file_dir(&fpp);
+}
diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c
index 3cf0fce945..650c4d6dae 100644
--- a/apps/plugins/lua/rocklua.c
+++ b/apps/plugins/lua/rocklua.c
@@ -241,6 +241,20 @@ static void display_traceback(const char *errstr)
rb->splash(10 * HZ, errstr);
#endif
}
+
+int browse_scripts(void)
+{
+ static char buf[MAX_PATH];
+ const char *fname = rb->plugin_get_current_filename();
+ /* strip plugin dir to save space in the param buffer */
+ if (rb->strncmp(fname, PLUGIN_DIR, sizeof(PLUGIN_DIR) - 1) == 0)
+ fname += sizeof(PLUGIN_DIR) - 1; /* leave slash */
+ /* -r return to this plugin, -f looking for lua files,
+ -s start in lua_scripts, -d lock to that directory */
+ snprintf(buf, sizeof(buf), "-r'%s'-f'.lua'-s'%s'-d",
+ fname, PLUGIN_DEMOS_DIR"/lua_scripts/");
+ return rb->plugin_open(VIEWERS_DIR "/file_picker.rock", buf);
+}
/***************** Plugin Entry Point *****************/
enum plugin_status plugin_start(const void* parameter)
{
@@ -249,7 +263,10 @@ enum plugin_status plugin_start(const void* parameter)
if (parameter == NULL)
{
if (!Ls)
+ {
rb->splash(HZ, "Play a .lua file!");
+ return browse_scripts();
+ }
}
else
{