[Feature] Set values of settings from shortcuts

Adds 'Add Current to Shortcuts' for settings alowing you to save
the current value and restore it with a shortcut

Change-Id: I0d5c5da9553248a70fd46d5553486ebf7865a20a
This commit is contained in:
William Wilgus 2025-01-24 02:43:41 -05:00
parent bdf89bf4b0
commit 43068ef270
7 changed files with 329 additions and 224 deletions

View file

@ -6951,6 +6951,21 @@
*: "Add to Shortcuts" *: "Add to Shortcuts"
</voice> </voice>
</phrase> </phrase>
<phrase>
id: LANG_ADD_CURRENT_TO_FAVES
desc:
user: core
<source>
*: "Add Current to Shortcuts"
</source>
<dest>
*: "Add Current to Shortcuts"
</dest>
<voice>
*: "Add Current to Shortcuts"
</voice>
</phrase>
<phrase> <phrase>
id: LANG_PITCH id: LANG_PITCH
desc: "pitch" in the pitch screen desc: "pitch" in the pitch screen

View file

@ -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) if (type == MT_SETTING_W_TEXT || type == MT_SETTING)
{ {
#ifdef HAVE_QUICKSCREEN const struct menu_item_ex *context_menu;
MENUITEM_STRINGLIST(quickscreen_able_option, const struct settings_list *setting =
find_setting(temp->variable);
MENUITEM_STRINGLIST(settings_op_menu,
ID2P(LANG_ONPLAY_MENU_TITLE), NULL, ID2P(LANG_ONPLAY_MENU_TITLE), NULL,
ID2P(LANG_RESET_SETTING), ID2P(LANG_RESET_SETTING),
#ifndef HAVE_QUICKSCREEN
};
context_menu = &settings_op_menu;
#else
ID2P(LANG_TOP_QS_ITEM), ID2P(LANG_TOP_QS_ITEM),
ID2P(LANG_LEFT_QS_ITEM), ID2P(LANG_LEFT_QS_ITEM),
ID2P(LANG_BOTTOM_QS_ITEM), ID2P(LANG_BOTTOM_QS_ITEM),
ID2P(LANG_RIGHT_QS_ITEM), ID2P(LANG_RIGHT_QS_ITEM),
ID2P(LANG_ADD_CURRENT_TO_FAVES),
ID2P(LANG_ADD_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 = &notquickscreen_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); int msel = do_menu(context_menu, NULL, NULL, false);
switch (msel) 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 */ case 4: /* set as right QS item */
global_settings.qs_items[QUICKSCREEN_RIGHT] = setting; global_settings.qs_items[QUICKSCREEN_RIGHT] = setting;
break; 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 */ added to the shortcuts menu as the quickscreen */
shortcuts_add(SHORTCUT_SETTING, (void*)setting); shortcuts_add(SHORTCUT_SETTING, (void*)setting);
break; break;

View file

@ -258,33 +258,18 @@ bool copy_filename_setting(char *buf, size_t buflen, const char *input,
return true; return true;
} }
bool settings_load_config(const char* file, bool apply) void string_to_cfg(const char *name, char* value, bool *theme_changed)
{ {
logf("%s()\r\n", __func__); const struct settings_list *setting = find_setting_by_cfgname(name);
const struct settings_list *setting;
int fd;
char line[128];
char* name;
char* value;
bool theme_changed = false;
fd = open_utf8(file, O_RDONLY);
if (fd < 0)
return false;
while (read_line(fd, line, sizeof line) > 0)
{
if (!settings_parseline(line, &name, &value))
continue;
setting = find_setting_by_cfgname(name);
if (!setting) if (!setting)
continue; return;
if (setting->flags & F_THEMESETTING) uint32_t flags = setting->flags;
theme_changed = true;
switch (setting->flags & F_T_MASK) if (flags & F_THEMESETTING)
*theme_changed = true;
switch (flags & F_T_MASK)
{ {
case F_T_CUSTOM: case F_T_CUSTOM:
setting->custom_setting->load_from_cfg(setting->setting, value); setting->custom_setting->load_from_cfg(setting->setting, value);
@ -293,7 +278,7 @@ bool settings_load_config(const char* file, bool apply)
case F_T_INT: case F_T_INT:
case F_T_UINT: case F_T_UINT:
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
if (setting->flags & F_RGB) if (flags & F_RGB)
{ {
hex_to_rgb(value, (int*)setting->setting); hex_to_rgb(value, (int*)setting->setting);
logf("Val: %s\r\n", value); logf("Val: %s\r\n", value);
@ -311,18 +296,18 @@ bool settings_load_config(const char* file, bool apply)
bool found = cfg_string_to_int(setting, &temp, value); bool found = cfg_string_to_int(setting, &temp, value);
if (found) if (found)
{ {
if (setting->flags & F_TABLE_SETTING) if (flags & F_TABLE_SETTING)
*v = setting->table_setting->values[temp]; *v = setting->table_setting->values[temp];
else else
*v = temp; *v = temp;
logf("Val: %d\r\n", *v); logf("Val: %d\r\n", *v);
} }
else if (setting->flags & F_ALLOW_ARBITRARY_VALS) else if (flags & F_ALLOW_ARBITRARY_VALS)
{ {
*v = atoi(value); *v = atoi(value);
logf("Val: %s = %d\r\n", value, *v); logf("Val: %s = %d\r\n", value, *v);
} }
else if (setting->flags & F_TABLE_SETTING) else if (flags & F_TABLE_SETTING)
{ {
const struct table_setting *info = setting->table_setting; const struct table_setting *info = setting->table_setting;
temp = atoi(value); temp = atoi(value);
@ -374,6 +359,25 @@ bool settings_load_config(const char* file, bool apply)
break; break;
} }
} }
}
bool settings_load_config(const char* file, bool apply)
{
logf("%s()\r\n", __func__);
int fd;
char line[128];
bool theme_changed = false;
fd = open_utf8(file, O_RDONLY);
if (fd < 0)
return false;
while (read_line(fd, line, sizeof line) > 0)
{
char *name, *value;
if (!settings_parseline(line, &name, &value))
continue;
string_to_cfg(name, value, &theme_changed);
} /* while(...) */ } /* while(...) */
close(fd); close(fd);

View file

@ -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_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); 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 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, bool copy_filename_setting(char *buf, size_t buflen, const char *input,
const struct filename_setting *fs); const struct filename_setting *fs);
bool set_bool_options(const char* string, const bool* variable, bool set_bool_options(const char* string, const bool* variable,

View file

@ -52,10 +52,11 @@
#endif #endif
#define MAX_SHORTCUT_NAME 64 #define MAX_SHORTCUT_NAME 64
#define SHORTCUTS_HDR "[shortcut]"
#define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt" #define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt"
static const char * const type_strings[SHORTCUT_TYPE_COUNT] = { static const char * const type_strings[SHORTCUT_TYPE_COUNT] = {
[SHORTCUT_SETTING] = "setting", [SHORTCUT_SETTING] = "setting",
[SHORTCUT_FILE] = "file", [SHORTCUT_SETTING_APPLY] = "apply",
[SHORTCUT_DEBUGITEM] = "debug", [SHORTCUT_DEBUGITEM] = "debug",
[SHORTCUT_BROWSER] = "browse", [SHORTCUT_BROWSER] = "browse",
[SHORTCUT_PLAYLISTMENU] = "playlist menu", [SHORTCUT_PLAYLISTMENU] = "playlist menu",
@ -63,16 +64,17 @@ static const char * const type_strings[SHORTCUT_TYPE_COUNT] = {
[SHORTCUT_SHUTDOWN] = "shutdown", [SHORTCUT_SHUTDOWN] = "shutdown",
[SHORTCUT_REBOOT] = "reboot", [SHORTCUT_REBOOT] = "reboot",
[SHORTCUT_TIME] = "time", [SHORTCUT_TIME] = "time",
[SHORTCUT_FILE] = "file",
}; };
struct shortcut { struct shortcut {
enum shortcut_type type; enum shortcut_type type;
int8_t icon;
char name[MAX_SHORTCUT_NAME]; char name[MAX_SHORTCUT_NAME];
char talk_clip[MAX_PATH]; char talk_clip[MAX_PATH];
int icon; const struct settings_list *setting;
union { union {
char path[MAX_PATH]; char path[MAX_PATH];
const struct settings_list *setting;
struct { struct {
#if CONFIG_RTC #if CONFIG_RTC
bool talktime; bool talktime;
@ -81,6 +83,7 @@ struct shortcut {
} timedata; } timedata;
} u; } u;
}; };
#define SHORTCUTS_PER_HANDLE 4 #define SHORTCUTS_PER_HANDLE 4
struct shortcut_handle { struct shortcut_handle {
struct shortcut shortcuts[SHORTCUTS_PER_HANDLE]; struct shortcut shortcuts[SHORTCUTS_PER_HANDLE];
@ -121,19 +124,34 @@ static void reset_shortcuts(void)
shortcut_count = 0; 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 handle_count, handle_index;
int current_handle = first_handle; int current_handle = first_handle;
struct shortcut_handle *h = NULL; struct shortcut_handle *h;
if (first_handle == 0) if (first_handle == 0)
{ {
first_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); h = alloc_first_sc_handle();
if (first_handle <= 0) if (!h)
return NULL; return fail;
h = core_get_data(first_handle);
h->next_handle = 0;
current_handle = first_handle; current_handle = first_handle;
} }
@ -143,15 +161,18 @@ static struct shortcut* get_shortcut(int index)
h = core_get_data(current_handle); h = core_get_data(current_handle);
current_handle = h->next_handle; current_handle = h->next_handle;
handle_count--; handle_count--;
} while (handle_count > 0 && current_handle > 0); if(handle_count <= 0)
if (handle_count > 0 && handle_index == 0) return &h->shortcuts[handle_index];
} while (current_handle > 0);
if (handle_index == 0)
{ {
/* prevent invalidation of 'h' during compaction */ /* prevent invalidation of 'h' during compaction */
++buflib_move_lock; ++buflib_move_lock;
h->next_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); h->next_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops);
--buflib_move_lock; --buflib_move_lock;
if (h->next_handle <= 0) if (h->next_handle <= 0)
return NULL; return fail;
h = core_get_data(h->next_handle); h = core_get_data(h->next_handle);
h->next_handle = 0; h->next_handle = 0;
} }
@ -161,11 +182,11 @@ static struct shortcut* get_shortcut(int index)
static void remove_shortcut(int index) static void remove_shortcut(int index)
{ {
int this = index, next = index + 1; int this = index, next = index + 1;
struct shortcut *prev = get_shortcut(this); struct shortcut *prev = get_shortcut(this, NULL);
while (next <= shortcut_count) while (next <= shortcut_count)
{ {
struct shortcut *sc = get_shortcut(next); struct shortcut *sc = get_shortcut(next, NULL);
memcpy(prev, sc, sizeof(struct shortcut)); memcpy(prev, sc, sizeof(struct shortcut));
next++; next++;
prev = sc; prev = sc;
@ -183,8 +204,9 @@ static bool verify_shortcut(struct shortcut* sc)
case SHORTCUT_FILE: case SHORTCUT_FILE:
case SHORTCUT_PLAYLISTMENU: case SHORTCUT_PLAYLISTMENU:
return sc->u.path[0] != '\0'; return sc->u.path[0] != '\0';
case SHORTCUT_SETTING_APPLY:
case SHORTCUT_SETTING: case SHORTCUT_SETTING:
return sc->u.setting != NULL; return sc->setting != NULL;
case SHORTCUT_TIME: case SHORTCUT_TIME:
#if CONFIG_RTC #if CONFIG_RTC
if (sc->u.timedata.talktime) if (sc->u.timedata.talktime)
@ -203,10 +225,8 @@ static bool verify_shortcut(struct shortcut* sc)
static void init_shortcut(struct shortcut* sc) static void init_shortcut(struct shortcut* sc)
{ {
memset(sc, 0, sizeof(*sc));
sc->type = SHORTCUT_UNDEFINED; sc->type = SHORTCUT_UNDEFINED;
sc->name[0] = '\0';
sc->u.path[0] = '\0';
sc->talk_clip[0] = '\0';
sc->icon = Icon_NOICON; sc->icon = Icon_NOICON;
} }
@ -215,7 +235,7 @@ static bool overwrite_shortcuts = false;
static void shortcuts_ata_idle_callback(void) static void shortcuts_ata_idle_callback(void)
{ {
int fd; int fd;
char buf[MAX_PATH];
int current_idx = first_idx_to_writeback; int current_idx = first_idx_to_writeback;
int append = overwrite_shortcuts ? O_TRUNC : O_APPEND; int append = overwrite_shortcuts ? O_TRUNC : O_APPEND;
@ -231,17 +251,16 @@ static void shortcuts_ata_idle_callback(void)
while (current_idx < shortcut_count) while (current_idx < shortcut_count)
{ {
struct shortcut* sc = get_shortcut(current_idx++); struct shortcut* sc = get_shortcut(current_idx++, NULL);
const char *type; const char *type;
int len;
if (!sc) if (!sc)
break; break;
type = type_strings[sc->type]; type = type_strings[sc->type];
len = snprintf(buf, MAX_PATH, "[shortcut]\ntype: %s\ndata: ", type);
write(fd, buf, len); fdprintf(fd, SHORTCUTS_HDR "\ntype: %s\ndata: ", type);
if (sc->type == SHORTCUT_SETTING)
write(fd, sc->u.setting->cfg_name, strlen(sc->u.setting->cfg_name)); if (sc->type == SHORTCUT_TIME)
else if (sc->type == SHORTCUT_TIME)
{ {
#if CONFIG_RTC #if CONFIG_RTC
if (sc->u.timedata.talktime) if (sc->u.timedata.talktime)
@ -249,23 +268,25 @@ static void shortcuts_ata_idle_callback(void)
else else
#endif #endif
{ {
write(fd, "sleep ", 6); write(fd, "sleep", 5);
if(sc->u.timedata.sleep_timeout >= 0) if(sc->u.timedata.sleep_timeout >= 0)
fdprintf(fd, " %d", sc->u.timedata.sleep_timeout);
}
}
else if (sc->type == SHORTCUT_SETTING_APPLY)
{ {
len = snprintf(buf, MAX_PATH, "%d", sc->u.timedata.sleep_timeout); fdprintf(fd, "%s: %s", sc->setting->cfg_name, sc->u.path);
write(fd, buf, len);
}
} }
else if (sc->type == SHORTCUT_SETTING)
{
write(fd, sc->setting->cfg_name, strlen(sc->setting->cfg_name));
} }
else else
write(fd, sc->u.path, strlen(sc->u.path)); write(fd, sc->u.path, strlen(sc->u.path));
/* write name:, icon:, talkclip: */ /* write name:, icon:, talkclip: */
len = snprintf(buf, MAX_PATH, "\nname: %s\nicon: %d\ntalkclip: ", fdprintf(fd, "\nname: %s\nicon: %d\ntalkclip: %s\n\n",
sc->name, sc->icon); sc->name, sc->icon, sc->talk_clip);
write(fd, buf, len);
write(fd, sc->talk_clip, strlen(sc->talk_clip));
write(fd, "\n\n", 2);
} }
close(fd); close(fd);
if (first_idx_to_writeback == 0) 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) 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) if (!sc)
return; return;
init_shortcut(sc); init_shortcut(sc);
sc->type = type; sc->type = type;
if (type == SHORTCUT_SETTING) if (type == SHORTCUT_SETTING || type == SHORTCUT_SETTING_APPLY)
sc->u.setting = (void*)value; {
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 else
strmemccpy(sc->u.path, value, MAX_PATH); 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; struct shortcut* sc = *param;
char *name, *value; char *name, *value;
if (!strcasecmp(skip_whitespace(buf), "[shortcut]")) buf = skip_whitespace(buf);
if (!strcasecmp(buf, SHORTCUTS_HDR))
{ {
if (sc && verify_shortcut(sc)) if (sc && verify_shortcut(sc))
shortcut_count++; shortcut_count++;
sc = get_shortcut(shortcut_count); sc = get_shortcut(shortcut_count, NULL);
if (!sc) if (!sc)
return 1; return 1;
init_shortcut(sc); init_shortcut(sc);
@ -347,8 +374,19 @@ static int readline_cb(int n, char *buf, void *parameters)
case SHORTCUT_PLAYLISTMENU: case SHORTCUT_PLAYLISTMENU:
strmemccpy(sc->u.path, value, MAX_PATH); strmemccpy(sc->u.path, value, MAX_PATH);
break; break;
case SHORTCUT_SETTING_APPLY:
case SHORTCUT_SETTING: 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; break;
case SHORTCUT_TIME: case SHORTCUT_TIME:
#if CONFIG_RTC #if CONFIG_RTC
@ -357,11 +395,13 @@ static int readline_cb(int n, char *buf, void *parameters)
sc->u.timedata.talktime = true; sc->u.timedata.talktime = true;
else else
#endif #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 */ /* 'sleep' may appear alone or followed by number after a space */
sc->u.timedata.sleep_timeout = strlen(&value[5]) > 1 ? if (strlen(value) > sizeof("sleep")) /* sizeof 1 larger (+space chr..) */
atoi(&value[strlen("sleep ")]) : -1; sc->u.timedata.sleep_timeout = atoi(&value[sizeof("sleep")-1]);
else
sc->u.timedata.sleep_timeout = -1;
} }
else else
sc->type = SHORTCUT_UNDEFINED; /* error */ 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*/ 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)); 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); fd = open_utf8(SHORTCUTS_FILENAME, O_RDONLY);
if (fd < 0) if (fd < 0)
return; return;
first_handle = core_alloc_ex(sizeof(struct shortcut_handle), &shortcut_ops); h = alloc_first_sc_handle();
if (first_handle <= 0) { if (!h) {
close(fd); close(fd);
return; return;
} }
h = core_get_data(first_handle);
h->next_handle = 0;
/* we enter readline_cb() multiple times with a buffer /* 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 */ fast_readline() might yield() -> protect buffer */
++buflib_move_lock; ++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) char * buffer, size_t buffer_len)
{ {
(void)data; (void)data;
struct shortcut *sc = get_shortcut(selected_item); struct shortcut *sc = get_shortcut(selected_item, NULL);
if (!sc) if (!sc)
return ""; return "";
if (sc->type == SHORTCUT_SETTING) const char *ret = sc->u.path;
return sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id));
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) else if (sc->type == SHORTCUT_SEPARATOR)
return sc->name; return sc->name;
else if (sc->type == SHORTCUT_TIME) 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) static int shortcut_menu_speak_item(int selected_item, void * data)
{ {
(void)data; (void)data;
struct shortcut *sc = get_shortcut(selected_item); struct shortcut *sc = get_shortcut(selected_item, NULL);
if (sc) if (sc)
{ {
if (sc->talk_clip[0]) if (sc->talk_clip[0])
@ -523,9 +569,13 @@ static int shortcut_menu_speak_item(int selected_item, void * data)
case SHORTCUT_PLAYLISTMENU: case SHORTCUT_PLAYLISTMENU:
talk_file_or_spell(NULL, sc->u.path, NULL, false); talk_file_or_spell(NULL, sc->u.path, NULL, false);
break; break;
case SHORTCUT_SETTING_APPLY:
case SHORTCUT_SETTING: 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; break;
case SHORTCUT_TIME: case SHORTCUT_TIME:
#if CONFIG_RTC #if CONFIG_RTC
if (sc->u.timedata.talktime) 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) static int shortcut_menu_get_action(int action, struct gui_synclist *lists)
{ {
(void)lists; (void)lists;
if (action == ACTION_STD_OK || action == ACTION_STD_MENU) if (action == ACTION_STD_CONTEXT)
return ACTION_STD_CANCEL;
else if (action == ACTION_STD_QUICKSCREEN && action != ACTION_STD_CONTEXT)
return ACTION_STD_CANCEL;
else if (action == ACTION_STD_CONTEXT)
{ {
int selection = gui_synclist_get_sel_pos(lists); 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; first_idx_to_writeback = 0;
overwrite_shortcuts = true; overwrite_shortcuts = true;
shortcuts_ata_idle_callback(); shortcuts_ata_idle_callback();
if (shortcut_count == 0)
return ACTION_STD_CANCEL;
if (shortcut_count > 0)
{
shortcut_menu_speak_item(gui_synclist_get_sel_pos(lists), NULL); shortcut_menu_speak_item(gui_synclist_get_sel_pos(lists), NULL);
return ACTION_REDRAW; 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; return action;
} }
static enum themable_icons shortcut_menu_get_icon(int selected_item, void * data) 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; (void)data;
int icon; int icon;
struct shortcut *sc = get_shortcut(selected_item); struct shortcut *sc = get_shortcut(selected_item, NULL);
if (!sc) if (!sc)
return Icon_NOICON; return Icon_NOICON;
if (sc->icon == Icon_NOICON) if (sc->icon == Icon_NOICON)
{ {
if (sc->type == SHORTCUT_BROWSER || sc->type == SHORTCUT_FILE)
switch (sc->type)
{ {
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)); icon = filetype_get_icon(filetype_get_attr(sc->u.path));
if (icon <= 0) if (icon > 0)
icon = Icon_Folder;
return icon; 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; 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) int do_shortcut_menu(void *ignored)
{ {
(void)ignored; (void)ignored;
@ -665,7 +733,7 @@ int do_shortcut_menu(void *ignored)
break; break;
else else
{ {
sc = get_shortcut(list.selection); sc = get_shortcut(list.selection, NULL);
if (!sc) if (!sc)
continue; continue;
@ -711,22 +779,19 @@ int do_shortcut_menu(void *ignored)
} }
break; 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: case SHORTCUT_SETTING:
{ {
int old_sleeptimer_duration = global_settings.sleeptimer_duration; do_setting_screen(sc->setting,
#ifdef HAVE_ALBUMART sc->name[0] ? sc->name : P2STR(ID2P(sc->setting->lang_id)),NULL);
int old_album_art = global_settings.album_art; apply_new_setting(sc->setting);
#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);
break; break;
} }
case SHORTCUT_DEBUGITEM: case SHORTCUT_DEBUGITEM:

View file

@ -30,6 +30,7 @@ enum shortcut_type {
SHORTCUT_FILE, SHORTCUT_FILE,
SHORTCUT_DEBUGITEM, SHORTCUT_DEBUGITEM,
SHORTCUT_BROWSER, SHORTCUT_BROWSER,
SHORTCUT_SETTING_APPLY,
SHORTCUT_PLAYLISTMENU, SHORTCUT_PLAYLISTMENU,
SHORTCUT_SEPARATOR, SHORTCUT_SEPARATOR,
SHORTCUT_SHUTDOWN, SHORTCUT_SHUTDOWN,

View file

@ -286,6 +286,8 @@ settings. With a shortcut,
a specified file or folder a specified file or folder
\item A file's or folder's ``Playing Next...'' context menu item can \item A file's or folder's ``Playing Next...'' context menu item can
be displayed 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 \item A setting can be configured (any which can be added to the
\setting{Quick Screen}) \setting{Quick Screen})
\item A debug menu item can be displayed (useful for developers mostly) \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}) ``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 \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) (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[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, \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 or left blank to make the list more accessible with visual gaps