Index: apps/action.h =================================================================== --- apps/action.h (revision 25054) +++ apps/action.h (working copy) @@ -128,6 +128,7 @@ ACTION_WPS_MENU, /*this should be the same as ACTION_STD_MENU */ ACTION_WPS_VIEW_PLAYLIST, ACTION_WPS_REC, + ACTION_WPS_VARTOGGLE, #if 0 ACTION_WPSAB_SINGLE, /* This needs to be #defined in the config-.h to one of the ACTION_WPS_ actions Index: apps/gui/skin_engine/skin_parser.c =================================================================== --- apps/gui/skin_engine/skin_parser.c (revision 25054) +++ apps/gui/skin_engine/skin_parser.c (working copy) @@ -185,6 +185,10 @@ } #define parse_touchregion fulline_tag_not_supported #endif +static int parse_variable_define(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); +static int parse_variable_get(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); #ifdef CONFIG_RTC #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC #else @@ -365,6 +369,10 @@ { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_display }, #endif + /* Variables */ + { WPS_TOKEN_DEFINE_VAR, "vd", 0, parse_variable_define }, + { WPS_TOKEN_GET_VAR, "vg", WPS_REFRESH_DYNAMIC, parse_variable_get }, + { WPS_VIEWPORT_ENABLE, "Vd", WPS_REFRESH_DYNAMIC, parse_viewport_display }, #ifdef HAVE_LCD_BITMAP @@ -398,6 +406,7 @@ { WPS_TOKEN_REC_BITRATE, "Rb", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_REC_MONO, "Rm", WPS_REFRESH_DYNAMIC, NULL }, #endif + { WPS_TOKEN_UNKNOWN, "", 0, NULL } /* the array MUST end with an empty string (first char is \0) */ }; @@ -450,7 +459,26 @@ return NULL; } +/* Finds a variable defined by the theme. */ +struct variable* find_variable(char name, struct wps_data *data) { + struct skin_token_list *list = data->variables; + while (list) + { + struct variable* var = (struct variable*) list->token->value.data; + if (var->label == name) + return var; + list= list->next; + } + return NULL; +} +/* Toggles a wps variable. */ +void toggle_variable(struct variable *var) { + var->state++; + if (var->state >= var->num_states) + var->state = 0; +} + /* create and init a new wpsll item. * passing NULL to token will alloc a new one. * You should only pass NULL for the token when the token type (table above) @@ -1451,6 +1479,7 @@ const char *action; const char pb_string[] = "progressbar"; const char vol_string[] = "volume"; + const char vt_string[] = "vt"; int x,y,w,h; /* format: %T|x|y|width|height|action| @@ -1498,6 +1527,7 @@ region->height = h; region->wvp = curr_vp; region->armed = false; + region->actiondata.data = NULL; if(!strncmp(pb_string, action, sizeof(pb_string)-1) && *(action + sizeof(pb_string)-1) == '|') @@ -1529,6 +1559,12 @@ region->action = touchactions[i].action; i++; } + if (!strncmp(vt_string, action, sizeof(vt_string)-1) + && *(action+sizeof(vt_string)) == '|') { + char varname = *(action+sizeof(vt_string)-1); + region->action = ACTION_WPS_VARTOGGLE; + region->actiondata.c = varname; + } if (region->action == ACTION_NONE) return WPS_ERROR_INVALID_PARAM; } @@ -1540,6 +1576,58 @@ } #endif +/* Parse a variable definition. */ +static int parse_variable_define(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + (void)token; /* Kill warnings */ + const char *ptr = wps_bufptr; + const char *label = NULL; + int num_states = 0; + struct variable *var = NULL; + + if (*ptr != '|') + return WPS_ERROR_INVALID_PARAM; + ptr++; + + if (!(ptr = parse_list("sd", NULL, '|', ptr, &label, &num_states ))) + return WPS_ERROR_INVALID_PARAM; + + /* Plausibility check */ + if (*label < 'a' || *label > 'z' || num_states <= 1 || num_states > 255) + return WPS_ERROR_INVALID_PARAM; + + var = skin_buffer_alloc(sizeof(struct variable)); + if (!var) + return WPS_ERROR_INVALID_PARAM; + + var->label = *label; + var->state = 0; + var->num_states = (unsigned char) num_states; + + struct skin_token_list *item = new_skin_token_list_item(NULL, var); + if (!item) + return WPS_ERROR_INVALID_PARAM; + add_to_ll_chain(&wps_data->variables, item); + return skip_end_of_line(wps_bufptr); +} + +/* Parse a variable get. */ +static int parse_variable_get(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + (void)wps_data; + char label = wps_bufptr[0]; + + if (label < 'a' || label > 'z' || !find_variable(label, wps_data)) + return WPS_ERROR_INVALID_PARAM; + + token->value.c = label; + return 1; +} + /* Parse a generic token from the given string. Return the length read */ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) { @@ -1978,6 +2066,7 @@ #endif wps_data->viewports = NULL; wps_data->strings = NULL; + wps_data->variables = NULL; #ifdef HAVE_ALBUMART wps_data->albumart = NULL; if (wps_data->playback_aa_slot >= 0) Index: apps/gui/skin_engine/skin_tokens.c =================================================================== --- apps/gui/skin_engine/skin_tokens.c (revision 25054) +++ apps/gui/skin_engine/skin_tokens.c (working copy) @@ -1207,6 +1207,17 @@ case WPS_TOKEN_LANG_IS_RTL: return lang_is_rtl() ? "r" : NULL; + case WPS_TOKEN_GET_VAR: { + struct variable* var = find_variable(token->value.c, data); + if (var) { + if (intval) + *intval = var->state + 1; + snprintf(buf, buf_size, "%hu", var->state); + return buf; + } + return NULL; + } + default: return NULL; } Index: apps/gui/skin_engine/skin_tokens.h =================================================================== --- apps/gui/skin_engine/skin_tokens.h (revision 25054) +++ apps/gui/skin_engine/skin_tokens.h (working copy) @@ -56,6 +56,10 @@ WPS_VIEWPORT_ENABLE, WPS_VIEWPORT_CUSTOMLIST, + /* Variables */ + WPS_TOKEN_DEFINE_VAR, + WPS_TOKEN_GET_VAR, + /* Battery */ TOKEN_MARKER_BATTERY, WPS_TOKEN_BATTERY_PERCENT, Index: apps/gui/skin_engine/wps_internals.h =================================================================== --- apps/gui/skin_engine/wps_internals.h (revision 25054) +++ apps/gui/skin_engine/wps_internals.h (working copy) @@ -224,9 +224,20 @@ int action; /* action this button will return */ bool armed; /* A region is armed on press. Only armed regions are triggered on repeat or release. */ + union { + char c; + unsigned short i; + void* data; + } actiondata; }; #endif +struct variable { + char label; /* name of the variable */ + unsigned char state; /* current state */ + unsigned char num_states; /* Number of states. Toggling when at max will wrap around to 0. */ +}; + #define MAX_PLAYLISTLINE_TOKENS 16 #define MAX_PLAYLISTLINE_STRINGS 8 #define MAX_PLAYLISTLINE_STRLEN 8 @@ -281,6 +292,7 @@ #endif struct skin_token_list *viewports; struct skin_token_list *strings; + struct skin_token_list *variables; #ifdef HAVE_ALBUMART struct skin_albumart *albumart; int playback_aa_slot; @@ -369,5 +381,10 @@ struct gui_img* find_image(char label, struct wps_data *data); struct skin_viewport* find_viewport(char label, struct wps_data *data); +/* Finds a variable defined by the theme. */ +struct variable* find_variable(char label, struct wps_data *data); +/* Toggles the state of a wps variable. */ +void toggle_variable(struct variable *var); + #endif Index: apps/gui/wps.c =================================================================== --- apps/gui/wps.c (revision 25054) +++ apps/gui/wps.c (working copy) @@ -691,6 +691,14 @@ { last_action = r->action; returncode = r->action; + /* We need to toggle the variable here because we currently + * have no way to return the varname in addition to the action id. */ + if (r->action == ACTION_WPS_VARTOGGLE) + { + struct variable *var = find_variable(r->actiondata.c, data); + if (var) + toggle_variable(var); + } } if (pressed) r->armed = true;