From b39acee3abd199d80b84c68ebfa7301b7e7a957e Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Fri, 12 Nov 2021 20:50:20 -0500 Subject: rb_info plugin and button,action+context name helper rb_info is just a test plugin just some info from the running rockbox install the real star here is the generator scripts to make actions_helper.c and button_helper.c Change-Id: I23f7bbdae3f2cffca2490c4df40bb13b0b5d5064 --- apps/plugins/rb_info.c | 494 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 apps/plugins/rb_info.c (limited to 'apps/plugins/rb_info.c') diff --git a/apps/plugins/rb_info.c b/apps/plugins/rb_info.c new file mode 100644 index 0000000000..f82c80c0cf --- /dev/null +++ b/apps/plugins/rb_info.c @@ -0,0 +1,494 @@ +/*************************************************************************** + * __________ __ ___. + * 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" + +#define MENU_ID(x) (((void*)&"RPBUTACNGX\0" + x)) +enum { + M_ROOT = 0, + M_PATHS, + M_BUFFERS, + M_BUTTONS, + M_BTNTEST, + M_ACTIONS, + M_CONTEXTS, + M_ACTTEST, + M_PLUGINS, + 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"}, +}; + +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_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 ∅ +} + +static void cleanup(void *parameter) +{ + (void)parameter; + +} + +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) /*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); + } + 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 + { + 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_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); + } + } + } + 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; + 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_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_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); + + 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, 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; + + 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; + if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD)) + continue; + selected_item = rb->gui_synclist_get_sel_pos(&lists); + ret = menu_action_cb(action, selected_item, &exit, &lists); + } + } + + return ret; +} -- cgit v1.2.3