diff --git a/apps/action.h b/apps/action.h index e664c03fdf..a9e4de1665 100644 --- a/apps/action.h +++ b/apps/action.h @@ -196,6 +196,7 @@ enum { ACTION_SETTINGS_DECREPEAT, ACTION_SETTINGS_DECBIGSTEP, ACTION_SETTINGS_RESET, + ACTION_SETTINGS_SET, /* Used by touchscreen targets */ /* bookmark screen */ ACTION_BMS_DELETE, diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 25734954e5..0eb966198d 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -937,7 +937,8 @@ static const struct touchaction touchactions[] = { {"mute", ACTION_TOUCH_MUTE }, /* generic settings changers */ - {"setting_inc", ACTION_SETTINGS_INC}, {"setting_dec", ACTION_SETTINGS_DEC}, + {"setting_inc", ACTION_SETTINGS_INC}, {"setting_dec", ACTION_SETTINGS_DEC}, + {"setting_set", ACTION_SETTINGS_SET}, /* WPS specific actions */ {"browse", ACTION_WPS_BROWSE }, @@ -952,6 +953,7 @@ static const struct touchaction touchactions[] = { {"presets", ACTION_FM_PRESET}, #endif }; +bool cfg_string_to_int(int setting_id, int* out, const char* str); static int parse_touchregion(struct skin_element *element, struct wps_token *token, @@ -966,26 +968,9 @@ static int parse_touchregion(struct skin_element *element, const char vol_string[] = "volume"; char temp[20]; - /* format: %T(x,y,width,height,action) + /* format: %T([label,], x,y,width,height,action[, ...]) * if action starts with & the area must be held to happen - * action is one of: - * play - play/pause playback - * stop - stop playback, exit the wps - * prev - prev track - * next - next track - * ffwd - seek forward - * rwd - seek backwards - * menu - go back to the main menu - * browse - go back to the file/db browser - * shuffle - toggle shuffle mode - * repmode - cycle the repeat mode - * quickscreen - go into the quickscreen - * contextmenu - open the context menu - * playlist - go into the playlist - * pitch - go into the pitchscreen - * volup - increase volume by one step - * voldown - decrease volume by one step - */ + */ region = (struct touchregion*)skin_buffer_alloc(sizeof(struct touchregion)); @@ -1018,7 +1003,7 @@ static int parse_touchregion(struct skin_element *element, region->wvp = curr_vp; region->armed = false; region->reverse_bar = false; - region->data = NULL; + region->value = 0; region->last_press = 0xffff; action = element->params[p++].data.text; @@ -1055,7 +1040,8 @@ static int parse_touchregion(struct skin_element *element, { region->action = touchactions[i].action; if (region->action == ACTION_SETTINGS_INC || - region->action == ACTION_SETTINGS_DEC) + region->action == ACTION_SETTINGS_DEC || + region->action == ACTION_SETTINGS_SET) { if (element->params_count < p+1) { @@ -1072,7 +1058,50 @@ static int parse_touchregion(struct skin_element *element, break; if (j==nb_settings) return WPS_ERROR_INVALID_PARAM; - region->data = (void*)&settings[j]; + region->setting_data.setting = (void*)&settings[j]; + if (region->action == ACTION_SETTINGS_SET) + { + char* text; + int temp; + struct touchsetting *setting = + ®ion->setting_data; + if (element->params_count < p+2) + return WPS_ERROR_INVALID_PARAM; + text = element->params[p+1].data.text; + switch (settings[j].flags&F_T_MASK) + { + case F_T_CUSTOM: + setting->value.text = text; + break; + case F_T_INT: + case F_T_UINT: + if (settings[j].cfg_vals == NULL) + { + setting->value.number = atoi(text); + } + else if (cfg_string_to_int(j, &temp, text)) + { + if (settings[j].flags&F_TABLE_SETTING) + setting->value.number = + settings[j].table_setting->values[temp]; + else + setting->value.number = temp; + } + else + return WPS_ERROR_INVALID_PARAM; + break; + case F_T_BOOL: + if (cfg_string_to_int(j, &temp, text)) + { + setting->value.number = temp; + } + else + return WPS_ERROR_INVALID_PARAM; + break; + default: + return WPS_ERROR_INVALID_PARAM; + } + } } } break; diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c index 3206579adf..110e97f997 100644 --- a/apps/gui/skin_engine/skin_touchsupport.c +++ b/apps/gui/skin_engine/skin_touchsupport.c @@ -27,6 +27,7 @@ #include "misc.h" #include "option_select.h" #include "sound.h" +#include "settings_list.h" /** Disarms all touchregions. */ @@ -129,8 +130,45 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, case ACTION_SETTINGS_INC: case ACTION_SETTINGS_DEC: { - const struct settings_list *setting = temp->data; - option_select_next_val(setting, returncode == ACTION_SETTINGS_DEC, true); + const struct settings_list *setting = + temp->setting_data.setting; + option_select_next_val(setting, + returncode == ACTION_SETTINGS_DEC, + true); + returncode = ACTION_REDRAW; + } + break; + case ACTION_SETTINGS_SET: + { + struct touchsetting *data = &temp->setting_data; + const struct settings_list *s = data->setting; + void (*f)(int) = NULL; + switch (s->flags&F_T_MASK) + { + case F_T_CUSTOM: + s->custom_setting + ->load_from_cfg(s->setting, data->value.text); + break; + case F_T_INT: + case F_T_UINT: + *(int*)s->setting = data->value.number; + if (s->flags&F_CHOICE_SETTING) + f = s->choice_setting->option_callback; + else if (s->flags&F_TABLE_SETTING) + f = s->table_setting->option_callback; + else + f = s->int_setting->option_callback; + + if (f) + f(data->value.number); + break; + case F_T_BOOL: + *(bool*)s->setting = data->value.number ? true : false; + if (s->bool_setting->option_callback) + s->bool_setting + ->option_callback(data->value.number ? true : false); + break; + } returncode = ACTION_REDRAW; } break; diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index 28697c8b69..86d191f687 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -199,12 +199,20 @@ struct touchregion { bool armed; /* A region is armed on press. Only armed regions are triggered on repeat or release. */ union { /* Extra data, action dependant */ - void* data; + struct touchsetting { + const struct settings_list *setting; /* setting being controlled */ + union { /* Value to set the setting to for ACTION_SETTING_SET */ + int number; + char* text; + } value; + } setting_data; int value; }; long last_press; /* last tick this was pressed */ }; + + struct touchregion_lastpress { struct touchregion *region; long timeout; diff --git a/apps/settings.c b/apps/settings.c index e491c5b6f2..e9458dc601 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -231,7 +231,7 @@ void settings_load(int which) } } -static bool cfg_string_to_int(int setting_id, int* out, const char* str) +bool cfg_string_to_int(int setting_id, int* out, const char* str) { const char* start = settings[setting_id].cfg_vals; char* end = NULL; diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index 68e4b03a4e..56f5df1911 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -206,10 +206,10 @@ static const struct tag_info legal_tags[] = /* HACK Alert (jdgordon): The next two tags have hacks so we could * add a S param at the front without breaking old skins. * [SD]D <- handled by the callback, allows SD or S or D params - * [SI]III[SI]|SS -< SIIIIS|S or IIIIS|S + * [SI]III[SI]|SN -< SIIIIS|S or IIIIS|S * keep in sync with parse_touchregion() and parse_lasttouch() */ { SKIN_TOKEN_LASTTOUCH, "Tl" , "|[SD]D", SKIN_REFRESH_DYNAMIC }, - { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|SS", 0|NOBREAK }, + { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|SN", 0|NOBREAK }, { SKIN_TOKEN_HAVE_TOUCH, "Tp", "", FEATURE_TAG },