diff --git a/apps/lang/english.lang b/apps/lang/english.lang index c06f94c436..5873552252 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -6951,6 +6951,21 @@ *: "Add to Shortcuts" + + id: LANG_ADD_CURRENT_TO_FAVES + desc: + user: core + + *: "Add Current to Shortcuts" + + + *: "Add Current to Shortcuts" + + + *: "Add Current to Shortcuts" + + + id: LANG_PITCH desc: "pitch" in the pitch screen diff --git a/apps/menu.c b/apps/menu.c index 727255d837..c58eb5ecad 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -513,29 +513,37 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, if (type == MT_SETTING_W_TEXT || type == MT_SETTING) { -#ifdef HAVE_QUICKSCREEN - MENUITEM_STRINGLIST(quickscreen_able_option, + const struct menu_item_ex *context_menu; + const struct settings_list *setting = + find_setting(temp->variable); + + MENUITEM_STRINGLIST(settings_op_menu, ID2P(LANG_ONPLAY_MENU_TITLE), NULL, ID2P(LANG_RESET_SETTING), +#ifndef HAVE_QUICKSCREEN + }; + context_menu = &settings_op_menu; +#else ID2P(LANG_TOP_QS_ITEM), ID2P(LANG_LEFT_QS_ITEM), ID2P(LANG_BOTTOM_QS_ITEM), ID2P(LANG_RIGHT_QS_ITEM), + ID2P(LANG_ADD_CURRENT_TO_FAVES), ID2P(LANG_ADD_TO_FAVES)); -#endif - MENUITEM_STRINGLIST(notquickscreen_able_option, - ID2P(LANG_ONPLAY_MENU_TITLE), NULL, - ID2P(LANG_RESET_SETTING)); - const struct menu_item_ex *context_menu; - const struct settings_list *setting = - find_setting(temp->variable); -#ifdef HAVE_QUICKSCREEN - if (is_setting_quickscreenable(setting)) - context_menu = &quickscreen_able_option; - else -#endif - context_menu = ¬quickscreen_able_option; + /* re-use the strings and desc from the settings_op_menu */ + static const struct menu_item_ex non_quickscreen_op_menu = + {MT_RETURN_ID|MENU_HAS_DESC|MENU_ITEM_COUNT(1), + { .strings = settings_op_menu_}, + {.callback_and_desc = &settings_op_menu__}}; + + if (is_setting_quickscreenable(setting)) + context_menu = &settings_op_menu; + else + { + context_menu = &non_quickscreen_op_menu; + } +#endif int msel = do_menu(context_menu, NULL, NULL, false); switch (msel) @@ -560,7 +568,12 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, case 4: /* set as right QS item */ global_settings.qs_items[QUICKSCREEN_RIGHT] = setting; break; - case 5: /* Add to faves. Same limitation on which can be + case 5: /* Add current value of setting to faves. + Same limitation on which can be + added to the shortcuts menu as the quickscreen */ + shortcuts_add(SHORTCUT_SETTING_APPLY, (void*)setting); + break; + case 6: /* Add to faves. Same limitation on which can be added to the shortcuts menu as the quickscreen */ shortcuts_add(SHORTCUT_SETTING, (void*)setting); break; diff --git a/apps/settings.c b/apps/settings.c index 04114a8f31..68020a2d13 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -258,14 +258,114 @@ bool copy_filename_setting(char *buf, size_t buflen, const char *input, return true; } +void string_to_cfg(const char *name, char* value, bool *theme_changed) +{ + const struct settings_list *setting = find_setting_by_cfgname(name); + if (!setting) + return; + + uint32_t flags = setting->flags; + + if (flags & F_THEMESETTING) + *theme_changed = true; + + switch (flags & F_T_MASK) + { + case F_T_CUSTOM: + setting->custom_setting->load_from_cfg(setting->setting, value); + logf("Val: %s\r\n",value); + break; + case F_T_INT: + case F_T_UINT: +#ifdef HAVE_LCD_COLOR + if (flags & F_RGB) + { + hex_to_rgb(value, (int*)setting->setting); + logf("Val: %s\r\n", value); + } + else +#endif + if (setting_get_cfgvals(setting) == NULL) + { + *(int*)setting->setting = atoi(value); + logf("Val: %s\r\n",value); + } + else + { + int temp, *v = (int*)setting->setting; + bool found = cfg_string_to_int(setting, &temp, value); + if (found) + { + if (flags & F_TABLE_SETTING) + *v = setting->table_setting->values[temp]; + else + *v = temp; + logf("Val: %d\r\n", *v); + } + else if (flags & F_ALLOW_ARBITRARY_VALS) + { + *v = atoi(value); + logf("Val: %s = %d\r\n", value, *v); + } + else if (flags & F_TABLE_SETTING) + { + const struct table_setting *info = setting->table_setting; + temp = atoi(value); + *v = setting->default_val.int_; + if (info->values) + { + for(int i = 0; i < info->count; i++) + { + if (info->values[i] == temp) + { + *v = temp; + break; + } + } + } + logf("Val: %s", *v == temp ? "Found":"Error Not Found"); + logf("Val: %s = %d\r\n", value, *v); + } + + else + { + logf("Error: %s: Not Found! [%s]\r\n", + setting->cfg_name, value); + } + } + break; + case F_T_BOOL: + { + int temp; + if (cfg_string_to_int(setting, &temp, value)) + { + *(bool*)setting->setting = !!temp; + logf("Val: %s\r\n", value); + } + if (setting->bool_setting->option_callback) + { + setting->bool_setting->option_callback(!!temp); + } + break; + } + /* these can be plain text, filenames, or dirnames */ + case F_T_CHARPTR: + case F_T_UCHARPTR: + { + const struct filename_setting *fs = setting->filename_setting; + copy_filename_setting((char*)setting->setting, + fs->max_len, value, fs); + logf("Val: %s\r\n", value); + break; + } + } +} + bool settings_load_config(const char* file, bool apply) { logf("%s()\r\n", __func__); - const struct settings_list *setting; int fd; char line[128]; - char* name; - char* value; bool theme_changed = false; fd = open_utf8(file, O_RDONLY); @@ -274,106 +374,10 @@ bool settings_load_config(const char* file, bool apply) while (read_line(fd, line, sizeof line) > 0) { + char *name, *value; if (!settings_parseline(line, &name, &value)) continue; - - setting = find_setting_by_cfgname(name); - if (!setting) - continue; - - if (setting->flags & F_THEMESETTING) - theme_changed = true; - - switch (setting->flags & F_T_MASK) - { - case F_T_CUSTOM: - setting->custom_setting->load_from_cfg(setting->setting, value); - logf("Val: %s\r\n",value); - break; - case F_T_INT: - case F_T_UINT: -#ifdef HAVE_LCD_COLOR - if (setting->flags & F_RGB) - { - hex_to_rgb(value, (int*)setting->setting); - logf("Val: %s\r\n", value); - } - else -#endif - if (setting_get_cfgvals(setting) == NULL) - { - *(int*)setting->setting = atoi(value); - logf("Val: %s\r\n",value); - } - else - { - int temp, *v = (int*)setting->setting; - bool found = cfg_string_to_int(setting, &temp, value); - if (found) - { - if (setting->flags & F_TABLE_SETTING) - *v = setting->table_setting->values[temp]; - else - *v = temp; - logf("Val: %d\r\n", *v); - } - else if (setting->flags & F_ALLOW_ARBITRARY_VALS) - { - *v = atoi(value); - logf("Val: %s = %d\r\n", value, *v); - } - else if (setting->flags & F_TABLE_SETTING) - { - const struct table_setting *info = setting->table_setting; - temp = atoi(value); - *v = setting->default_val.int_; - if (info->values) - { - for(int i = 0; i < info->count; i++) - { - if (info->values[i] == temp) - { - *v = temp; - break; - } - } - } - logf("Val: %s", *v == temp ? "Found":"Error Not Found"); - logf("Val: %s = %d\r\n", value, *v); - } - - else - { - logf("Error: %s: Not Found! [%s]\r\n", - setting->cfg_name, value); - } - } - break; - case F_T_BOOL: - { - int temp; - if (cfg_string_to_int(setting, &temp, value)) - { - *(bool*)setting->setting = !!temp; - logf("Val: %s\r\n", value); - } - if (setting->bool_setting->option_callback) - { - setting->bool_setting->option_callback(!!temp); - } - break; - } - /* these can be plain text, filenames, or dirnames */ - case F_T_CHARPTR: - case F_T_UCHARPTR: - { - const struct filename_setting *fs = setting->filename_setting; - copy_filename_setting((char*)setting->setting, - fs->max_len, value, fs); - logf("Val: %s\r\n", value); - break; - } - } + string_to_cfg(name, value, &theme_changed); } /* while(...) */ close(fd); diff --git a/apps/settings.h b/apps/settings.h index 2fc20221ea..cc8c698bd2 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -288,6 +288,8 @@ const struct settings_list* find_setting_by_cfgname(const char* name); bool cfg_int_to_string(const struct settings_list *setting, int val, char* buf, int buf_len); bool cfg_string_to_int(const struct settings_list *setting, int* out, const char* str); void cfg_to_string(const struct settings_list *setting, char* buf, int buf_len); +void string_to_cfg(const char *name, char* value, bool *theme_changed); + bool copy_filename_setting(char *buf, size_t buflen, const char *input, const struct filename_setting *fs); bool set_bool_options(const char* string, const bool* variable, diff --git a/apps/shortcuts.c b/apps/shortcuts.c index adac5e3327..cdff6c69ad 100644 --- a/apps/shortcuts.c +++ b/apps/shortcuts.c @@ -52,10 +52,11 @@ #endif #define MAX_SHORTCUT_NAME 64 +#define SHORTCUTS_HDR "[shortcut]" #define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt" static const char * const type_strings[SHORTCUT_TYPE_COUNT] = { [SHORTCUT_SETTING] = "setting", - [SHORTCUT_FILE] = "file", + [SHORTCUT_SETTING_APPLY] = "apply", [SHORTCUT_DEBUGITEM] = "debug", [SHORTCUT_BROWSER] = "browse", [SHORTCUT_PLAYLISTMENU] = "playlist menu", @@ -63,16 +64,17 @@ static const char * const type_strings[SHORTCUT_TYPE_COUNT] = { [SHORTCUT_SHUTDOWN] = "shutdown", [SHORTCUT_REBOOT] = "reboot", [SHORTCUT_TIME] = "time", + [SHORTCUT_FILE] = "file", }; struct shortcut { enum shortcut_type type; + int8_t icon; char name[MAX_SHORTCUT_NAME]; char talk_clip[MAX_PATH]; - int icon; + const struct settings_list *setting; union { char path[MAX_PATH]; - const struct settings_list *setting; struct { #if CONFIG_RTC bool talktime; @@ -81,6 +83,7 @@ struct shortcut { } timedata; } u; }; + #define SHORTCUTS_PER_HANDLE 4 struct shortcut_handle { struct shortcut shortcuts[SHORTCUTS_PER_HANDLE]; @@ -121,19 +124,34 @@ static void reset_shortcuts(void) shortcut_count = 0; } -static struct shortcut* get_shortcut(int index) +static struct shortcut_handle * alloc_first_sc_handle(void) +{ + struct shortcut_handle *h = NULL; +#if 0 /* all paths are guarded, compiler doesn't recognize INIT_ATTR callers */ + if (first_handle != 0) + return h; /* No re-init allowed */ +#endif + first_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); + if (first_handle > 0) + { + h = core_get_data(first_handle); + h->next_handle = 0; + } + + return h; +} + +static struct shortcut* get_shortcut(int index, struct shortcut *fail) { int handle_count, handle_index; int current_handle = first_handle; - struct shortcut_handle *h = NULL; + struct shortcut_handle *h; if (first_handle == 0) { - first_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); - if (first_handle <= 0) - return NULL; - h = core_get_data(first_handle); - h->next_handle = 0; + h = alloc_first_sc_handle(); + if (!h) + return fail; current_handle = first_handle; } @@ -143,15 +161,18 @@ static struct shortcut* get_shortcut(int index) h = core_get_data(current_handle); current_handle = h->next_handle; handle_count--; - } while (handle_count > 0 && current_handle > 0); - if (handle_count > 0 && handle_index == 0) + if(handle_count <= 0) + return &h->shortcuts[handle_index]; + } while (current_handle > 0); + + if (handle_index == 0) { /* prevent invalidation of 'h' during compaction */ ++buflib_move_lock; h->next_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); --buflib_move_lock; if (h->next_handle <= 0) - return NULL; + return fail; h = core_get_data(h->next_handle); h->next_handle = 0; } @@ -161,11 +182,11 @@ static struct shortcut* get_shortcut(int index) static void remove_shortcut(int index) { int this = index, next = index + 1; - struct shortcut *prev = get_shortcut(this); + struct shortcut *prev = get_shortcut(this, NULL); while (next <= shortcut_count) { - struct shortcut *sc = get_shortcut(next); + struct shortcut *sc = get_shortcut(next, NULL); memcpy(prev, sc, sizeof(struct shortcut)); next++; prev = sc; @@ -183,8 +204,9 @@ static bool verify_shortcut(struct shortcut* sc) case SHORTCUT_FILE: case SHORTCUT_PLAYLISTMENU: return sc->u.path[0] != '\0'; + case SHORTCUT_SETTING_APPLY: case SHORTCUT_SETTING: - return sc->u.setting != NULL; + return sc->setting != NULL; case SHORTCUT_TIME: #if CONFIG_RTC if (sc->u.timedata.talktime) @@ -203,10 +225,8 @@ static bool verify_shortcut(struct shortcut* sc) static void init_shortcut(struct shortcut* sc) { + memset(sc, 0, sizeof(*sc)); sc->type = SHORTCUT_UNDEFINED; - sc->name[0] = '\0'; - sc->u.path[0] = '\0'; - sc->talk_clip[0] = '\0'; sc->icon = Icon_NOICON; } @@ -215,7 +235,7 @@ static bool overwrite_shortcuts = false; static void shortcuts_ata_idle_callback(void) { int fd; - char buf[MAX_PATH]; + int current_idx = first_idx_to_writeback; int append = overwrite_shortcuts ? O_TRUNC : O_APPEND; @@ -231,17 +251,16 @@ static void shortcuts_ata_idle_callback(void) while (current_idx < shortcut_count) { - struct shortcut* sc = get_shortcut(current_idx++); + struct shortcut* sc = get_shortcut(current_idx++, NULL); const char *type; - int len; + if (!sc) break; type = type_strings[sc->type]; - len = snprintf(buf, MAX_PATH, "[shortcut]\ntype: %s\ndata: ", type); - write(fd, buf, len); - if (sc->type == SHORTCUT_SETTING) - write(fd, sc->u.setting->cfg_name, strlen(sc->u.setting->cfg_name)); - else if (sc->type == SHORTCUT_TIME) + + fdprintf(fd, SHORTCUTS_HDR "\ntype: %s\ndata: ", type); + + if (sc->type == SHORTCUT_TIME) { #if CONFIG_RTC if (sc->u.timedata.talktime) @@ -249,23 +268,25 @@ static void shortcuts_ata_idle_callback(void) else #endif { - write(fd, "sleep ", 6); - if (sc->u.timedata.sleep_timeout >= 0) - { - len = snprintf(buf, MAX_PATH, "%d", sc->u.timedata.sleep_timeout); - write(fd, buf, len); - } + write(fd, "sleep", 5); + if(sc->u.timedata.sleep_timeout >= 0) + fdprintf(fd, " %d", sc->u.timedata.sleep_timeout); } } + else if (sc->type == SHORTCUT_SETTING_APPLY) + { + fdprintf(fd, "%s: %s", sc->setting->cfg_name, sc->u.path); + } + else if (sc->type == SHORTCUT_SETTING) + { + write(fd, sc->setting->cfg_name, strlen(sc->setting->cfg_name)); + } else write(fd, sc->u.path, strlen(sc->u.path)); /* write name:, icon:, talkclip: */ - len = snprintf(buf, MAX_PATH, "\nname: %s\nicon: %d\ntalkclip: ", - sc->name, sc->icon); - write(fd, buf, len); - write(fd, sc->talk_clip, strlen(sc->talk_clip)); - write(fd, "\n\n", 2); + fdprintf(fd, "\nname: %s\nicon: %d\ntalkclip: %s\n\n", + sc->name, sc->icon, sc->talk_clip); } close(fd); if (first_idx_to_writeback == 0) @@ -282,13 +303,17 @@ static void shortcuts_ata_idle_callback(void) void shortcuts_add(enum shortcut_type type, const char* value) { - struct shortcut* sc = get_shortcut(shortcut_count++); + struct shortcut* sc = get_shortcut(shortcut_count++, NULL); if (!sc) return; init_shortcut(sc); sc->type = type; - if (type == SHORTCUT_SETTING) - sc->u.setting = (void*)value; + if (type == SHORTCUT_SETTING || type == SHORTCUT_SETTING_APPLY) + { + sc->setting = (void*)value; + /* write the current value, will be ignored for SHORTCUT_SETTING */ + cfg_to_string(sc->setting, sc->u.path, sizeof(sc->u.path)); + } else strmemccpy(sc->u.path, value, MAX_PATH); @@ -306,11 +331,13 @@ static int readline_cb(int n, char *buf, void *parameters) struct shortcut* sc = *param; char *name, *value; - if (!strcasecmp(skip_whitespace(buf), "[shortcut]")) + buf = skip_whitespace(buf); + + if (!strcasecmp(buf, SHORTCUTS_HDR)) { if (sc && verify_shortcut(sc)) shortcut_count++; - sc = get_shortcut(shortcut_count); + sc = get_shortcut(shortcut_count, NULL); if (!sc) return 1; init_shortcut(sc); @@ -319,7 +346,7 @@ static int readline_cb(int n, char *buf, void *parameters) else if (sc && settings_parseline(buf, &name, &value)) { static const char * const nm_options[] = {"type", "name", "data", - "icon", "talkclip", NULL}; + "icon", "talkclip", NULL}; int nm_op = string_option(name, nm_options, false); if (nm_op == 0) /*type*/ @@ -347,8 +374,19 @@ static int readline_cb(int n, char *buf, void *parameters) case SHORTCUT_PLAYLISTMENU: strmemccpy(sc->u.path, value, MAX_PATH); break; + case SHORTCUT_SETTING_APPLY: case SHORTCUT_SETTING: - sc->u.setting = find_setting_by_cfgname(value); + /* can handle 'name: value' pair for either type */ + if (settings_parseline(value, &name, &value)) + { + sc->setting = find_setting_by_cfgname(name); + strmemccpy(sc->u.path, value, MAX_PATH); + } + else /* force SHORTCUT_SETTING, no 'name: value' pair */ + { + sc->type = SHORTCUT_SETTING; + sc->setting = find_setting_by_cfgname(value); + } break; case SHORTCUT_TIME: #if CONFIG_RTC @@ -357,11 +395,13 @@ static int readline_cb(int n, char *buf, void *parameters) sc->u.timedata.talktime = true; else #endif - if (!strncasecmp(value, "sleep", strlen("sleep"))) + if (!strncasecmp(value, "sleep", sizeof("sleep")-1)) { /* 'sleep' may appear alone or followed by number after a space */ - sc->u.timedata.sleep_timeout = strlen(&value[5]) > 1 ? - atoi(&value[strlen("sleep ")]) : -1; + if (strlen(value) > sizeof("sleep")) /* sizeof 1 larger (+space chr..) */ + sc->u.timedata.sleep_timeout = atoi(&value[sizeof("sleep")-1]); + else + sc->u.timedata.sleep_timeout = -1; } else sc->type = SHORTCUT_UNDEFINED; /* error */ @@ -374,7 +414,8 @@ static int readline_cb(int n, char *buf, void *parameters) } else if (nm_op == 3) /*icon*/ { - if (!strcmp(value, "filetype") && sc->type != SHORTCUT_SETTING && sc->u.path[0]) + if (!strcmp(value, "filetype") && sc->type != SHORTCUT_SETTING + && sc->type != SHORTCUT_SETTING_APPLY && sc->u.path[0]) { sc->icon = filetype_get_icon(filetype_get_attr(sc->u.path)); } @@ -401,17 +442,14 @@ void shortcuts_init(void) fd = open_utf8(SHORTCUTS_FILENAME, O_RDONLY); if (fd < 0) return; - first_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); - if (first_handle <= 0) { + h = alloc_first_sc_handle(); + if (!h) { close(fd); return; } - h = core_get_data(first_handle); - h->next_handle = 0; - /* we enter readline_cb() multiple times with a buffer - obtained when we encounter a "[shortcut]" section. + obtained when we encounter a SHORTCUTS_HDR ("[shortcut]") section. fast_readline() might yield() -> protect buffer */ ++buflib_move_lock; @@ -429,11 +467,19 @@ static const char * shortcut_menu_get_name(int selected_item, void * data, char * buffer, size_t buffer_len) { (void)data; - struct shortcut *sc = get_shortcut(selected_item); + struct shortcut *sc = get_shortcut(selected_item, NULL); if (!sc) return ""; - if (sc->type == SHORTCUT_SETTING) - return sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)); + const char *ret = sc->u.path; + + if (sc->type == SHORTCUT_SETTING && sc->name[0] == '\0') + return P2STR(ID2P(sc->setting->lang_id)); + else if (sc->type == SHORTCUT_SETTING_APPLY && sc->name[0] == '\0') + { + snprintf(buffer, buffer_len, "%s (%s)", + P2STR(ID2P(sc->setting->lang_id)), sc->u.path); + return buffer; + } else if (sc->type == SHORTCUT_SEPARATOR) return sc->name; else if (sc->type == SHORTCUT_TIME) @@ -463,13 +509,13 @@ static const char * shortcut_menu_get_name(int selected_item, void * data, } } - return sc->name[0] ? sc->name : sc->u.path; + return sc->name[0] ? sc->name : ret; } static int shortcut_menu_speak_item(int selected_item, void * data) { (void)data; - struct shortcut *sc = get_shortcut(selected_item); + struct shortcut *sc = get_shortcut(selected_item, NULL); if (sc) { if (sc->talk_clip[0]) @@ -523,9 +569,13 @@ static int shortcut_menu_speak_item(int selected_item, void * data) case SHORTCUT_PLAYLISTMENU: talk_file_or_spell(NULL, sc->u.path, NULL, false); break; + case SHORTCUT_SETTING_APPLY: case SHORTCUT_SETTING: - talk_id(sc->u.setting->lang_id, false); + talk_id(sc->setting->lang_id, false); + if (sc->type == SHORTCUT_SETTING_APPLY) + talk_spell(sc->u.path, true); break; + case SHORTCUT_TIME: #if CONFIG_RTC if (sc->u.timedata.talktime) @@ -557,11 +607,7 @@ static int shortcut_menu_speak_item(int selected_item, void * data) static int shortcut_menu_get_action(int action, struct gui_synclist *lists) { (void)lists; - if (action == ACTION_STD_OK || action == ACTION_STD_MENU) - return ACTION_STD_CANCEL; - else if (action == ACTION_STD_QUICKSCREEN && action != ACTION_STD_CONTEXT) - return ACTION_STD_CANCEL; - else if (action == ACTION_STD_CONTEXT) + if (action == ACTION_STD_CONTEXT) { int selection = gui_synclist_get_sel_pos(lists); @@ -580,52 +626,74 @@ static int shortcut_menu_get_action(int action, struct gui_synclist *lists) first_idx_to_writeback = 0; overwrite_shortcuts = true; shortcuts_ata_idle_callback(); - if (shortcut_count == 0) - return ACTION_STD_CANCEL; - shortcut_menu_speak_item(gui_synclist_get_sel_pos(lists), NULL); - return ACTION_REDRAW; + if (shortcut_count > 0) + { + shortcut_menu_speak_item(gui_synclist_get_sel_pos(lists), NULL); + return ACTION_REDRAW; + } + + return ACTION_STD_CANCEL; } + + if (action == ACTION_STD_OK + || action == ACTION_STD_MENU + || action == ACTION_STD_QUICKSCREEN) + { + return ACTION_STD_CANCEL; + } + return action; } static enum themable_icons shortcut_menu_get_icon(int selected_item, void * data) { + static const int8_t type_icons[SHORTCUT_TYPE_COUNT] = { + [SHORTCUT_SETTING] = Icon_Menu_setting, + [SHORTCUT_SETTING_APPLY] = Icon_Queued, + [SHORTCUT_DEBUGITEM] = Icon_Menu_functioncall, + [SHORTCUT_BROWSER] = Icon_Folder, + [SHORTCUT_PLAYLISTMENU] = Icon_Playlist, + [SHORTCUT_SEPARATOR] = Icon_NOICON, + [SHORTCUT_SHUTDOWN] = Icon_System_menu, + [SHORTCUT_REBOOT] = Icon_System_menu, + [SHORTCUT_TIME] = Icon_Menu_functioncall, + [SHORTCUT_FILE] = Icon_NOICON, + }; + (void)data; int icon; - struct shortcut *sc = get_shortcut(selected_item); + struct shortcut *sc = get_shortcut(selected_item, NULL); if (!sc) return Icon_NOICON; if (sc->icon == Icon_NOICON) { - - switch (sc->type) + if (sc->type == SHORTCUT_BROWSER || sc->type == SHORTCUT_FILE) { - case SHORTCUT_FILE: - return filetype_get_icon(filetype_get_attr(sc->u.path)); - case SHORTCUT_BROWSER: - icon = filetype_get_icon(filetype_get_attr(sc->u.path)); - if (icon <= 0) - icon = Icon_Folder; + icon = filetype_get_icon(filetype_get_attr(sc->u.path)); + if (icon > 0) return icon; - case SHORTCUT_SETTING: - return Icon_Menu_setting; - case SHORTCUT_DEBUGITEM: - return Icon_Menu_functioncall; - case SHORTCUT_PLAYLISTMENU: - return Icon_Playlist; - case SHORTCUT_SHUTDOWN: - case SHORTCUT_REBOOT: - return Icon_System_menu; - case SHORTCUT_TIME: - return Icon_Menu_functioncall; - default: - break; } + /* excluding SHORTCUT_UNDEFINED (-1) */ + if (sc->type >= 0 && sc->type < SHORTCUT_TYPE_COUNT) + return type_icons[sc->type]; } return sc->icon; } +static void apply_new_setting(const struct settings_list *setting) +{ + settings_apply(false); + if (setting->flags & F_THEMESETTING) + { + settings_apply_skins(); + } + if (setting->setting == &global_settings.sleeptimer_duration && get_sleep_timer()) + { + set_sleeptimer_duration(global_settings.sleeptimer_duration); + } +} + int do_shortcut_menu(void *ignored) { (void)ignored; @@ -665,7 +733,7 @@ int do_shortcut_menu(void *ignored) break; else { - sc = get_shortcut(list.selection); + sc = get_shortcut(list.selection, NULL); if (!sc) continue; @@ -711,22 +779,19 @@ int do_shortcut_menu(void *ignored) } break; + case SHORTCUT_SETTING_APPLY: + { + bool theme_changed; + string_to_cfg(sc->setting->cfg_name, sc->u.path, &theme_changed); + settings_save(); + apply_new_setting(sc->setting); + break; + } case SHORTCUT_SETTING: { - int old_sleeptimer_duration = global_settings.sleeptimer_duration; -#ifdef HAVE_ALBUMART - int old_album_art = global_settings.album_art; -#endif - do_setting_screen(sc->u.setting, - sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)),NULL); - -#ifdef HAVE_ALBUMART - if (old_album_art != global_settings.album_art) - set_albumart_mode(global_settings.album_art); -#endif - if (old_sleeptimer_duration != global_settings.sleeptimer_duration && - get_sleep_timer()) - set_sleeptimer_duration(global_settings.sleeptimer_duration); + do_setting_screen(sc->setting, + sc->name[0] ? sc->name : P2STR(ID2P(sc->setting->lang_id)),NULL); + apply_new_setting(sc->setting); break; } case SHORTCUT_DEBUGITEM: diff --git a/apps/shortcuts.h b/apps/shortcuts.h index aaccccb1b3..70c2b66c4f 100644 --- a/apps/shortcuts.h +++ b/apps/shortcuts.h @@ -30,6 +30,7 @@ enum shortcut_type { SHORTCUT_FILE, SHORTCUT_DEBUGITEM, SHORTCUT_BROWSER, + SHORTCUT_SETTING_APPLY, SHORTCUT_PLAYLISTMENU, SHORTCUT_SEPARATOR, SHORTCUT_SHUTDOWN, diff --git a/manual/main_menu/main.tex b/manual/main_menu/main.tex index f09cc448cb..0f150d4d25 100644 --- a/manual/main_menu/main.tex +++ b/manual/main_menu/main.tex @@ -286,6 +286,8 @@ settings. With a shortcut, a specified file or folder \item A file's or folder's ``Playing Next...'' context menu item can be displayed + \item A settings current value (any which can be added to the + \setting{Quick Screen}) \item A setting can be configured (any which can be added to the \setting{Quick Screen}) \item A debug menu item can be displayed (useful for developers mostly) @@ -321,6 +323,9 @@ Available types are: ``Playing Next...'' context menu item on (see \reference{ref:playingnext_submenu}) \item[setting] \config{data} is the config name of the setting you want to change (see \reference{ref:config_file_options} for the list of the possible settings) +\item[apply] \config{data} is the config name of the setting followed by ':' + and the value you want applied. ex. 'data: volume: 20' would set the volume to 20 when selected + (see \reference{ref:config_file_options} for the list of the possible settings) \item[debug] \config{data} is the name of the debug menu item to display \item[separator] \config{data} is ignored; \config{name} can be used to display text, or left blank to make the list more accessible with visual gaps