summaryrefslogtreecommitdiffstats
path: root/apps/plugins/rb_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/rb_info.c')
-rw-r--r--apps/plugins/rb_info.c574
1 files changed, 574 insertions, 0 deletions
diff --git a/apps/plugins/rb_info.c b/apps/plugins/rb_info.c
new file mode 100644
index 0000000000..a89cc658cc
--- /dev/null
+++ b/apps/plugins/rb_info.c
@@ -0,0 +1,574 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+/* WIP rb_info common info that you wonder about when rockboxing?
+ */
+
+#include "plugin.h"
+#include "lang_enum.h"
+#include "../open_plugin.h"
+#include "logf.h"
+#include "lib/action_helper.h"
+#include "lib/button_helper.h"
+#include "lib/pluginlib_actions.h"
+#include "lib/printcell_helper.h"
+
+#define MENU_ID(x) (((void*)&"RPBUTACNGSX\0" + x))
+enum {
+ M_ROOT = 0,
+ M_PATHS,
+ M_BUFFERS,
+ M_BUTTONS,
+ M_BTNTEST,
+ M_ACTIONS,
+ M_CONTEXTS,
+ M_ACTTEST,
+ M_PLUGINS,
+ M_TESTPUT,
+ M_EXIT,
+ M_LAST_ITEM //ITEM COUNT
+};
+
+#define MENU_ID_PLUGINS_ITEMS 5
+
+/*Action test and Button test*/
+static struct menu_test_t {
+ int count;
+ int context;
+ int last_btn_or_act;
+} m_test;
+
+struct menu_buffer_t { const char *name; size_t size;};
+static const struct menu_buffer_t m_buffer[] =
+{
+#ifndef MAX_LOGF_SIZE
+#define MAX_LOGF_SIZE (0)
+#endif
+#ifndef CACHE_SIZE
+#define CACHE_SIZE (0)
+#endif
+ {"thread stack", DEFAULT_STACK_SIZE},
+ {"plugin buffer", PLUGIN_BUFFER_SIZE},
+ {"frame_buffer", FRAMEBUFFER_SIZE},
+ {"codec_buffer", CODEC_SIZE},
+ {"logf_buffer", MAX_LOGF_SIZE},
+ {"cache", CACHE_SIZE},
+};
+
+/* stringify the macro value */
+#define MACROVAL(x) MACROSTR(x)
+#define MACROSTR(x) #x
+static int main_last_sel = 0;
+static struct gui_synclist lists;
+static void synclist_set(char*, int, int, int);
+
+struct paths { const char *name; const char *path; };
+static const struct paths paths[] = {
+ {"Home", ""HOME_DIR},
+ {"Rockbox", ""ROCKBOX_DIR},
+ {"Plugins", ""PLUGIN_DIR},
+ {"Codecs", ""CODECS_DIR},
+ {"WPS", ""WPS_DIR},
+ {"SBS", ""SBS_DIR},
+ {"Theme", ""THEME_DIR},
+ {"Font", ""FONT_DIR},
+ {"Icon", ""ICON_DIR},
+ {"Backdrop", ""BACKDROP_DIR},
+ {"Eq", ""EQS_DIR},
+ {"Rec Presets", ""RECPRESETS_DIR},
+ {"Recordings", ""REC_BASE_DIR,},
+ {"Fm Presets", ""FMPRESET_PATH},
+ {"MAX_PATH", ""MACROVAL(MAX_PATH)" bytes"},
+};
+#define TESTPUT_HEADER "$*64$col1$col2$*128$col3$col4$col5$col6$*64$col7$col8"
+static int testput_cols = 0;
+struct mainmenu { const char *name; void *menuid; int items;};
+static struct mainmenu mainmenu[M_LAST_ITEM] = {
+#define MENU_ITEM(ID, NAME, COUNT) [ID]{NAME, MENU_ID(ID), (int)COUNT}
+MENU_ITEM(M_ROOT, "Rockbox Info Plugin", M_LAST_ITEM),
+MENU_ITEM(M_PATHS, ID2P(LANG_SHOW_PATH), ARRAYLEN(paths)),
+MENU_ITEM(M_BUFFERS, ID2P(LANG_BUFFER_STAT), ARRAYLEN(m_buffer)),
+MENU_ITEM(M_BUTTONS, "Buttons", -1), /* Set at runtime in plugin_start: */
+MENU_ITEM(M_BTNTEST, "Button test", 2),
+MENU_ITEM(M_ACTIONS, "Actions", LAST_ACTION_PLACEHOLDER),
+MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ),
+MENU_ITEM(M_ACTTEST, "Action test", 3),
+MENU_ITEM(M_PLUGINS, ID2P(LANG_PLUGINS), MENU_ID_PLUGINS_ITEMS),
+MENU_ITEM(M_TESTPUT, "Printcell test", 36),
+MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0),
+#undef MENU_ITEM
+};
+
+static const struct mainmenu *mainitem(int selected_item)
+{
+ static const struct mainmenu empty = {0};
+ if (selected_item >= 0 && selected_item < (int) ARRAYLEN(mainmenu))
+ return &mainmenu[selected_item];
+ else
+ return &empty;
+}
+
+static void cleanup(void *parameter)
+{
+ (void)parameter;
+}
+
+#if 0
+static enum themable_icons menu_icon_cb(int selected_item, void * data)
+{
+ (void)data;
+ (void)selected_item;
+ return Icon_NOICON;
+}
+#endif
+
+static const char *menu_plugin_name_cb(int selected_item, void* data,
+ char* buf, size_t buf_len)
+{
+ (void)data;
+ buf[0] = '\0';
+ switch(selected_item)
+ {
+ case 0:
+ rb->snprintf(buf, buf_len, "%s: [%d bytes] ", "plugin_api", (int)sizeof(struct plugin_api));
+ break;
+ case 1:
+ rb->snprintf(buf, buf_len, "%s: [%d bytes] ", "plugin buffer", PLUGIN_BUFFER_SIZE);
+ break;
+ case 2:
+ rb->snprintf(buf, buf_len, "%s: [%d bytes] ", "frame_buffer", (int)FRAMEBUFFER_SIZE);
+ break;
+ case 3:
+ rb->snprintf(buf, buf_len, "%s: [W: %d H:%d] ", "LCD", LCD_WIDTH, LCD_HEIGHT);
+ break;
+ case 4:
+ rb->snprintf(buf, buf_len, "%s: [%d bits] ", "fb_data", (int)(sizeof(fb_data) * CHAR_BIT));
+ break;
+ case 5:
+ break;
+ }
+ return buf;
+}
+
+static const char *menu_button_test_name_cb(int selected_item, void* data,
+ char* buf, size_t buf_len)
+{
+ (void)data;
+ int curbtn = BUTTON_NONE;
+ buf[0] = '\0';
+ switch(selected_item)
+ {
+ case 0:
+ rb->snprintf(buf, buf_len, "%s: [%s] ", "Button test",
+ m_test.count > 0 ? "true":"false");
+ break;
+ case 1:
+ if (m_test.count > 0)
+ {
+ if (m_test.count <= 2)
+ curbtn = rb->button_get_w_tmo(HZ * 2);
+ else
+ m_test.last_btn_or_act = BUTTON_NONE;
+ if (curbtn == BUTTON_NONE)
+ {
+ m_test.count--;
+ }
+ else
+ m_test.last_btn_or_act = curbtn;
+ }
+ get_button_names(buf, buf_len, m_test.last_btn_or_act);
+
+ break;
+ }
+ return buf;
+}
+
+static const char *menu_action_test_name_cb(int selected_item, void* data,
+ char* buf, size_t buf_len)
+{
+ (void)data;
+ const char *fmtstr;
+ int curact = ACTION_NONE;
+ buf[0] = '\0';
+ switch(selected_item)
+ {
+ case 0:
+ rb->snprintf(buf, buf_len, "%s: [%s] ", "Action test",
+ m_test.count > 0 ? "true":"false");
+ break;
+ case 1:
+ if (m_test.count <= 0)
+ {
+ if (m_test.context <= 0)
+ fmtstr = "%s > ";
+ else if (m_test.context >= LAST_CONTEXT_PLACEHOLDER - 1)
+ fmtstr = "< %s ";
+ else
+ fmtstr = "< %s > ";
+ }
+ else
+ fmtstr = "%s";
+
+ rb->snprintf(buf, buf_len, fmtstr, context_name(m_test.context));
+ break;
+ case 2:
+ if (m_test.count > 0)
+ {
+ if (m_test.count <= 2)
+ curact = rb->get_action(m_test.context, HZ * 2);
+ else
+ m_test.last_btn_or_act = ACTION_NONE;
+ if (curact == ACTION_NONE && rb->button_get(false) == BUTTON_NONE)
+ {
+ m_test.count--;
+ }
+ else
+ {
+ m_test.last_btn_or_act = curact;
+ m_test.count = 2;
+ }
+ }
+ return action_name(m_test.last_btn_or_act);
+
+ break;
+ }
+ return buf;
+}
+
+static const char* list_get_name_cb(int selected_item, void* data,
+ char* buf, size_t buf_len)
+{
+ buf[0] = '\0';
+ if (data == MENU_ID(M_ROOT))
+ return mainitem(selected_item)->name;
+ else if (selected_item == 0 && data != MENU_ID(M_TESTPUT)) /*header text*/
+ return mainitem(main_last_sel)->name;
+ else if (selected_item >= mainitem(main_last_sel)->items - 1)
+ return ID2P(LANG_BACK);
+
+ if (data == MENU_ID(M_PATHS))
+ {
+ selected_item--;
+ if (selected_item >= 0 && selected_item < mainitem(M_PATHS)->items)
+ {
+ const struct paths *cur = &paths[selected_item];
+ rb->snprintf(buf, buf_len, "%s: [%s] ", cur->name, cur->path);
+ return buf;
+ }
+ }
+ else if (data == MENU_ID(M_BUTTONS))
+ {
+ const struct available_button *btn = &available_buttons[selected_item - 1];
+ rb->snprintf(buf, buf_len, "%s: [0x%X] ", btn->name, (unsigned int) btn->value);
+ return buf;
+ }
+ else if (data == MENU_ID(M_BTNTEST))
+ return menu_button_test_name_cb(selected_item - 1, data, buf, buf_len);
+ else if (data == MENU_ID(M_ACTIONS))
+ return action_name(selected_item - 1);
+ else if (data == MENU_ID(M_CONTEXTS))
+ return context_name(selected_item - 1);
+ else if (data == MENU_ID(M_ACTTEST))
+ return menu_action_test_name_cb(selected_item - 1, data, buf, buf_len);
+ else if (data == MENU_ID(M_BUFFERS))
+ {
+ const struct menu_buffer_t *bufm = &m_buffer[selected_item - 1];
+ rb->snprintf(buf, buf_len, "%s: [%ld bytes] ", bufm->name, (long)bufm->size);
+ return buf;
+ }
+ else if (data == MENU_ID(M_PLUGINS))
+ {
+ return menu_plugin_name_cb(selected_item - 1, data, buf, buf_len);
+ }
+ else if (data == MENU_ID(M_TESTPUT))
+ {
+ rb->snprintf(buf, buf_len, "put_line item: [ %d ]$Text %d$Text LONGER TEST text %d $4$5$6$7$8$9", selected_item, 1, 2);
+ return buf;
+ }
+ return buf;
+}
+
+static int list_voice_cb(int list_index, void* data)
+{
+ if (!rb->global_settings->talk_menu)
+ return -1;
+
+ if (data == MENU_ID(M_ROOT))
+ {
+ const char * name = mainitem(list_index)->name;
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ rb->talk_spell(name, true);
+ }
+ else if (data == MENU_ID(M_BUFFERS) || data == MENU_ID(M_PLUGINS))
+ {
+ char buf[64];
+ const char* name = list_get_name_cb(list_index, data, buf, sizeof(buf));
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ {
+ char* bytstr = rb->strcasestr(name, "bytes");
+ if (bytstr != NULL)
+ *bytstr = '\0';
+ rb->talk_spell(name, true);
+ }
+ }
+ else if (data == MENU_ID(M_TESTPUT))
+ {
+ char buf[64];
+ const char* name = printcell_get_column_text(printcell_get_column_selected(),
+ buf, sizeof(buf));
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ rb->talk_spell(name, true);
+ }
+ else
+ {
+ char buf[64];
+ const char* name = list_get_name_cb(list_index, data, buf, sizeof(buf));
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ rb->talk_spell(name, true);
+ }
+ return 0;
+}
+
+int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_synclist *lists)
+{
+ if (lists->data == MENU_ID(M_TESTPUT) && (selected_item < (mainitem(M_TESTPUT)->items) - 1)/*back*/)
+ {
+ if (*action == ACTION_STD_OK)
+ {
+ printcell_increment_column(1, true);
+ *action = ACTION_NONE;
+ }
+ else if (*action == ACTION_STD_CANCEL)
+ {
+ if (printcell_increment_column(-1, true) != testput_cols - 1)
+ {
+ *action = ACTION_NONE;
+ }
+ }
+ else if (*action == ACTION_STD_CONTEXT)
+ {
+ char buf[PRINTCELL_MAXLINELEN];
+ char* bufp = buf;
+ int selcol = printcell_get_column_selected();
+ bufp = printcell_get_column_text(selcol, bufp, PRINTCELL_MAXLINELEN);
+ rb->splashf(HZ * 2, "Item: %s", bufp);
+ }
+ }
+ else if (lists->data == MENU_ID(M_ACTTEST))
+ {
+ if (selected_item == 2) /* context */
+ {
+ int ctx = m_test.context;
+ if (*action == ACTION_STD_OK)
+ m_test.context++;
+ else if (*action == ACTION_STD_CANCEL)
+ m_test.context--;
+
+ if (m_test.context < 0)
+ m_test.context = 0;
+ else if (m_test.context >= LAST_CONTEXT_PLACEHOLDER)
+ m_test.context = LAST_CONTEXT_PLACEHOLDER - 1;
+
+ if (ctx != m_test.context)
+ rb->gui_synclist_speak_item(lists);
+
+ goto default_handler;
+ }
+ if (*action == ACTION_STD_OK)
+ {
+ if (selected_item == 1 || selected_item == 3)
+ {
+ m_test.count = 3;
+ rb->gui_synclist_select_item(lists, 3);
+ }
+ }
+ }
+ else if (lists->data == MENU_ID(M_BTNTEST))
+ {
+ if (*action == ACTION_STD_OK)
+ {
+ if (selected_item == 1 || selected_item == 2)
+ {
+ m_test.count = 3;
+ rb->gui_synclist_select_item(lists, 2);
+ }
+ }
+ }
+/* common */
+ if (*action == ACTION_STD_OK)
+ {
+ if (lists->data == MENU_ID(M_ROOT))
+ {
+ rb->memset(&m_test, 0, sizeof(struct menu_test_t));
+ const struct mainmenu *cur = mainitem(selected_item);
+
+ if (cur->menuid == NULL || cur->menuid == MENU_ID(M_EXIT))
+ *exit = true;
+ else
+ {
+ main_last_sel = selected_item;
+
+ if (cur->menuid == MENU_ID(M_TESTPUT))
+ {
+ synclist_set(cur->menuid, 0, cur->items, 1);
+ printcell_enable(true);
+ //lists->callback_draw_item = test_listdraw_fn;
+ }
+ else
+ {
+ printcell_enable(false);
+ synclist_set(cur->menuid, 1, cur->items, 1);
+ }
+ rb->gui_synclist_draw(lists);
+ }
+ }
+ else if (selected_item <= 0) /* title */
+ {
+ rb->gui_synclist_select_item(lists, 1);
+ }
+ else if (selected_item >= (mainitem(main_last_sel)->items) - 1)/*back*/
+ {
+ *action = ACTION_STD_CANCEL;
+ }
+ else if (lists->data == MENU_ID(M_TESTPUT))
+ {
+
+ }
+ else if (lists->data == MENU_ID(M_ACTIONS) ||
+ lists->data == MENU_ID(M_CONTEXTS))
+ {
+ char buf[MAX_PATH];
+ const char *name = list_get_name_cb(selected_item, lists->data, buf, sizeof(buf));
+ /* splash long enough to get fingers off button then wait for new button press */
+ rb->splashf(HZ / 2, "%s %d (0x%X)", name, selected_item -1, selected_item -1);
+ rb->button_get(true);
+ }
+ }
+ if (*action == ACTION_STD_CANCEL)
+ {
+ if (lists->data == MENU_ID(M_TESTPUT))
+ {
+ //lists->callback_draw_item = NULL;
+ printcell_enable(false);
+ }
+ if (lists->data != MENU_ID(M_ROOT))
+ {
+ const struct mainmenu *mainm = &mainmenu[0];
+ synclist_set(mainm->menuid, main_last_sel, mainm->items, 1);
+ rb->gui_synclist_draw(lists);
+ }
+ else
+ *exit = true;
+ }
+default_handler:
+ if (rb->default_event_handler_ex(*action, cleanup, NULL) == SYS_USB_CONNECTED)
+ {
+ *exit = true;
+ return PLUGIN_USB_CONNECTED;
+ }
+ return PLUGIN_OK;
+}
+
+static void synclist_set(char* menu_id, int selected_item, int items, int sel_size)
+{
+ if (items <= 0)
+ return;
+ if (selected_item < 0)
+ selected_item = 0;
+
+ list_voice_cb(0, menu_id);
+ rb->gui_synclist_init(&lists,list_get_name_cb,
+ menu_id, false, sel_size, NULL);
+ if (menu_id == MENU_ID(M_TESTPUT))
+ {
+ testput_cols = printcell_set_columns(&lists, NULL,
+ TESTPUT_HEADER, Icon_Rockbox);
+ }
+ else
+ {
+ rb->gui_synclist_set_title(&lists, NULL,-1);
+ }
+ 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_select_item(&lists, selected_item);
+
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ int ret = PLUGIN_OK;
+ int selected_item = -1;
+ int action;
+ bool redraw = true;
+ bool exit = false;
+ if (parameter)
+ {
+ //
+ }
+ mainmenu[M_BUTTONS].items = available_button_count;
+ /* add header and back item to each submenu */
+ for (int i = 1; i < M_LAST_ITEM; i++)
+ mainmenu[i].items += 2;
+ mainmenu[M_TESTPUT].items -= 1;
+ if (!exit)
+ {
+ const struct mainmenu *mainm = &mainmenu[0];
+ synclist_set(mainm->menuid, main_last_sel, mainm->items, 1);
+ rb->gui_synclist_draw(&lists);
+
+ while (!exit)
+ {
+ action = rb->get_action(CONTEXT_LIST, HZ / 10);
+ if (m_test.count > 0)
+ action = ACTION_REDRAW;
+
+ if (action == ACTION_NONE)
+ {
+ if (redraw)
+ {
+ action = ACTION_REDRAW;
+ redraw = false;
+ }
+ }
+ else
+ redraw = true;
+ ret = menu_action_cb(&action, selected_item, &exit, &lists);
+ if (rb->gui_synclist_do_button(&lists, &action))
+ continue;
+ selected_item = rb->gui_synclist_get_sel_pos(&lists);
+ }
+ }
+ printcell_enable(false);
+ return ret;
+}