From 6dbfd44b6e6a4e01066ff3a99748e586d7cd458a Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 13 Feb 2014 22:01:13 +1100 Subject: [PATCH] main_menu_config: New plugin to configur the main menu order Plugins/Applications/main_menu_config allows you to edit the main menu order without having to manually edit config.cfg. Press the standard OK button to access the internal menu which allows you to move items up/down in the order and toggle their visibility. Exit via this menu to have the order saved. (Suggestions welcome to improve this UI) Change-Id: I59715ef1ca265aeb6f9666ef27026bc1093f2579 --- apps/plugin.c | 5 + apps/plugin.h | 6 + apps/plugins/CATEGORIES | 1 + apps/plugins/SOURCES | 1 + apps/plugins/main_menu_config.c | 204 ++++++++++++++++++++++++++++++++ apps/root_menu.c | 12 +- apps/root_menu.h | 10 +- 7 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 apps/plugins/main_menu_config.c diff --git a/apps/plugin.c b/apps/plugin.c index af06a4c484..f9179f3f08 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -792,6 +792,11 @@ static const struct plugin_api rockbox_api = { #endif rbversion, + root_menu_get_options, + root_menu_set_default, + root_menu_write_to_cfg, + root_menu_load_from_cfg, + settings_save, /* new stuff at the end, sort into place next time the API gets incompatible */ diff --git a/apps/plugin.h b/apps/plugin.h index 1d1e9ee26e..0e0580501d 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -68,6 +68,7 @@ void* plugin_get_buffer(size_t *buffer_size); #include "mpeg.h" #include "audio.h" #include "mp3_playback.h" +#include "root_menu.h" #include "talk.h" #ifdef RB_PROFILE #include "profile.h" @@ -964,6 +965,11 @@ struct plugin_api { #endif const char *rbversion; + struct menu_table *(*root_menu_get_options)(int *nb_options); + void (*root_menu_set_default)(void* setting, void* defaultval); + char* (*root_menu_write_to_cfg)(void* setting, char*buf, int buf_len); + void (*root_menu_load_from_cfg)(void* setting, char *value); + int (*settings_save)(void); /* new stuff at the end, sort into place next time the API gets incompatible */ diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 54a316e84b..8a849aafc2 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -48,6 +48,7 @@ logo,demos lrcplayer,apps lua,viewers fractals,demos +main_menu_config,apps matrix,demos maze,games mazezam,games diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index c512a9e02f..59bd4023cc 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -11,6 +11,7 @@ keybox.c logo.c lrcplayer.c mosaique.c +main_menu_config.c properties.c random_folder_advance_config.c rockblox.c diff --git a/apps/plugins/main_menu_config.c b/apps/plugins/main_menu_config.c new file mode 100644 index 0000000000..da9fde8384 --- /dev/null +++ b/apps/plugins/main_menu_config.c @@ -0,0 +1,204 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 Jonathan Gordon + * + * 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. + * + ****************************************************************************/ + +/* mandatory include for all plugins */ +#include "plugin.h" + +static struct menu_table *menu_table; +static int menu_item_count; + +#define MAX_ITEM_NAME 64 +#define MAX_ITEMS 16 +struct items +{ + char string[MAX_ITEM_NAME]; + bool enabled; +}; + +static struct items menu_items[MAX_ITEMS]; + + +static const char * menu_get_name(int selected_item, void * data, + char * buffer, size_t buffer_len) +{ + (void)data; + (void)buffer; + (void)buffer_len; + + return menu_items[selected_item].string; +} + +static enum themable_icons menu_get_icon(int selected_item, void * data) +{ + (void)data; + + return menu_items[selected_item].enabled ? Icon_Config : Icon_NOICON; +} + +void load_from_cfg(void) +{ + char config_str[128]; + char *token, *save; + int done = 0; + int i = 0; + bool found = false; + + rb->root_menu_write_to_cfg(NULL, config_str, sizeof(config_str)); + + token = strtok_r(config_str, ", ", &save); + + while (token) + { + i = 0; + found = false; + for (i = 0, found = false; i < menu_item_count && !found; i++) + { + found = rb->strcmp(token, menu_table[i].string) == 0; + } + if (found) + { + rb->strcpy(menu_items[done].string, token); + menu_items[done].enabled = true; + done++; + } + token = strtok_r(NULL, ", ", &save); + } + + if (done < menu_item_count) + { + for (i = 0; i < menu_item_count; i++) + { + found = false; + for (int j = 0; !found && j < done; j++) + { + found = rb->strcmp(menu_table[i].string, menu_items[j].string) == 0; + } + + if (!found) + { + rb->strcpy(menu_items[done].string, menu_table[i].string); + menu_items[done].enabled = false; + done++; + } + } + } +} + +static void save_to_cfg(void) +{ + char out[128]; + int i, j = 0; + + out[0] = '\0'; + for (i = 0; i < menu_item_count; i++) + { + if (menu_items[i].enabled) + { + j += rb->snprintf(&out[j],sizeof(out) - j, "%s, ", menu_items[i].string); + } + } + + rb->root_menu_load_from_cfg(&rb->global_settings->root_menu_customized, out); +} + +static void swap_items(int a, int b) +{ + char temp[MAX_ITEM_NAME]; + bool enabled; + + rb->strcpy(temp, menu_items[a].string); + enabled = menu_items[a].enabled; + rb->strcpy(menu_items[a].string, + menu_items[b].string); + menu_items[a].enabled = menu_items[b].enabled; + rb->strcpy(menu_items[b].string, temp); + menu_items[b].enabled = enabled; +} + +/* this is the plugin entry point */ +enum plugin_status plugin_start(const void* parameter) +{ + (void)parameter; + struct gui_synclist list; + bool done = false; + int action, cur_sel; + + menu_table = rb->root_menu_get_options(&menu_item_count); + load_from_cfg(); + + rb->gui_synclist_init(&list, menu_get_name, NULL, false, 1, NULL); + rb->gui_synclist_set_icon_callback(&list, menu_get_icon); + rb->gui_synclist_set_nb_items(&list, menu_item_count); + rb->gui_synclist_set_title(&list, "Rockbox Main Menu Order", Icon_Rockbox); + + while (!done) + { + rb->gui_synclist_draw(&list); + cur_sel = rb->gui_synclist_get_sel_pos(&list); + action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); + if (rb->gui_synclist_do_button(&list,&action,LIST_WRAP_UNLESS_HELD)) + continue; + + switch (action) + { + case ACTION_STD_OK: + { + MENUITEM_STRINGLIST(menu, "Main Menu Editor", NULL, + "Toggle Item", + "Move Item Up", "Move Item down", + "----------", + "Load Default Configuration", "Exit"); + switch (rb->do_menu(&menu, NULL, NULL, false)) + { + case 0: + menu_items[cur_sel].enabled = !menu_items[cur_sel].enabled; + break; + case 1: + if (cur_sel == 0) + break; + swap_items(cur_sel, cur_sel - 1); + break; + case 2: + if (cur_sel + 1 == menu_item_count) + break; + swap_items(cur_sel, cur_sel + 1); + break; + case 4: + rb->root_menu_set_default(&rb->global_settings->root_menu_customized, NULL); + load_from_cfg(); + break; + case 5: + done = true; + save_to_cfg(); + rb->global_settings->root_menu_customized = true; + rb->settings_save(); + break; + } + break; + } + case ACTION_STD_CANCEL: + done = true; + break; + } + } + + + return PLUGIN_OK; +} diff --git a/apps/root_menu.c b/apps/root_menu.c index 71844dd41a..f83a97b9ed 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -484,10 +484,7 @@ MENUITEM_FUNCTION(do_shutdown_item, 0, ID2P(LANG_SHUTDOWN), struct menu_item_ex root_menu_; static struct menu_callback_with_desc root_menu_desc = { item_callback, ID2P(LANG_ROCKBOX_TITLE), Icon_Rockbox }; -struct menu_table { - char *string; - const struct menu_item_ex *item; -}; + static struct menu_table menu_table[] = { /* Order here represents the default ordering */ { "bookmarks", &bookmarks }, @@ -514,6 +511,13 @@ static struct menu_table menu_table[] = { #define MAX_MENU_ITEMS (sizeof(menu_table) / sizeof(struct menu_table)) static struct menu_item_ex *root_menu__[MAX_MENU_ITEMS]; +struct menu_table *root_menu_get_options(int *nb_options) +{ + *nb_options = MAX_MENU_ITEMS; + + return menu_table; +} + void root_menu_load_from_cfg(void* setting, char *value) { char *next = value, *start, *end; diff --git a/apps/root_menu.h b/apps/root_menu.h index 32385d9530..6004a43f34 100644 --- a/apps/root_menu.h +++ b/apps/root_menu.h @@ -25,6 +25,12 @@ #include "gcc_extensions.h" void root_menu(void) NORETURN_ATTR; +struct menu_table { + char *string; + const struct menu_item_ex *item; +}; + +struct menu_table *root_menu_get_options(int *nb_options); enum { /* from old menu api, but still required*/ @@ -60,7 +66,7 @@ enum { GO_TO_SYSTEM_SCREEN, GO_TO_SHORTCUTMENU }; - +#ifndef PLUGIN extern struct menu_item_ex root_menu_; extern void previous_music_is_wps(void); @@ -69,7 +75,7 @@ void root_menu_load_from_cfg(void* setting, char *value); char* root_menu_write_to_cfg(void* setting, char*buf, int buf_len); void root_menu_set_default(void* setting, void* defaultval); bool root_menu_is_changed(void* setting, void* defaultval); - +#endif #endif /* __ROOT_MENU_H__ */