diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2010-08-19 13:49:32 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2010-08-19 13:49:32 +0000 |
commit | 74ec011bb8df08b0fba3709cc590ce3842b1c973 (patch) | |
tree | f70f9dc4ac88f018ac537971c8ead37f5c290920 | |
parent | b73d15e9c6175ac48b2280b089a40f0554d15d6f (diff) | |
download | rockbox-74ec011bb8df08b0fba3709cc590ce3842b1c973.tar.gz rockbox-74ec011bb8df08b0fba3709cc590ce3842b1c973.zip |
New skin tag: %if(<tag>, <operator>, <operand> [,option count]) which lets you do very simple logical comparissons on other tags.
<tag> is the tag to check against
<operator> is the comparisson to do, any one of... =, !=, >, >=, <, <= (when comparring against a string tag like %ia only = and != work, and it is done NOT case sensitive)
<operand> is either another tag, a number, or text.
[option count] is an optinal number to use for the few tags which scale to the amount of options when used as a conditional (i.e %?pv<a|b|c|d> would have 4 options)
example: %?if(%pv, >=, 0)<Warning.. volume clipping|coool...>
That says "If the value from %pv (volume) is greater than or equal to 0 then display the warning line, otherwise the cool line."
%?if(%ia, =, %Ia)<same artist> <= this artist and next artist are the same.
some tags might need a touch of tweaking to work better with this. experiment and have fun
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27846 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 37 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_tokens.c | 101 | ||||
-rw-r--r-- | apps/gui/skin_engine/wps_internals.h | 17 | ||||
-rw-r--r-- | lib/skin_parser/skin_parser.c | 6 | ||||
-rw-r--r-- | lib/skin_parser/tag_table.c | 2 | ||||
-rw-r--r-- | lib/skin_parser/tag_table.h | 1 |
6 files changed, 150 insertions, 14 deletions
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 1d471e8580..2c766162c3 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c | |||
@@ -502,7 +502,39 @@ static int parse_setting_and_lang(struct skin_element *element, | |||
502 | token->value.i = i; | 502 | token->value.i = i; |
503 | return 0; | 503 | return 0; |
504 | } | 504 | } |
505 | 505 | static int parse_logical_if(struct skin_element *element, | |
506 | struct wps_token *token, | ||
507 | struct wps_data *wps_data) | ||
508 | { | ||
509 | (void)wps_data; | ||
510 | char *op = element->params[1].data.text; | ||
511 | struct logical_if *lif = skin_buffer_alloc(sizeof(struct logical_if)); | ||
512 | if (!lif) | ||
513 | return -1; | ||
514 | token->value.data = lif; | ||
515 | lif->token = element->params[0].data.code->data; | ||
516 | |||
517 | if (!strcmp(op, "=")) | ||
518 | lif->op = IF_EQUALS; | ||
519 | if (!strcmp(op, "!=")) | ||
520 | lif->op = IF_NOTEQUALS; | ||
521 | if (!strcmp(op, "<")) | ||
522 | lif->op = IF_LESSTHAN; | ||
523 | if (!strcmp(op, "<=")) | ||
524 | lif->op = IF_LESSTHAN_EQ; | ||
525 | if (!strcmp(op, ">")) | ||
526 | lif->op = IF_GREATERTHAN; | ||
527 | if (!strcmp(op, ">=")) | ||
528 | lif->op = IF_GREATERTHAN_EQ; | ||
529 | |||
530 | memcpy(&lif->operand, &element->params[2], sizeof(lif->operand)); | ||
531 | if (element->params_count > 3) | ||
532 | lif->num_options = element->params[3].data.number; | ||
533 | else | ||
534 | lif->num_options = TOKEN_VALUE_ONLY; | ||
535 | return 0; | ||
536 | |||
537 | } | ||
506 | static int parse_timeout_tag(struct skin_element *element, | 538 | static int parse_timeout_tag(struct skin_element *element, |
507 | struct wps_token *token, | 539 | struct wps_token *token, |
508 | struct wps_data *wps_data) | 540 | struct wps_data *wps_data) |
@@ -1298,6 +1330,9 @@ static int skin_element_callback(struct skin_element* element, void* data) | |||
1298 | case SKIN_TOKEN_ALIGN_LANGDIRECTION: | 1330 | case SKIN_TOKEN_ALIGN_LANGDIRECTION: |
1299 | follow_lang_direction = 2; | 1331 | follow_lang_direction = 2; |
1300 | break; | 1332 | break; |
1333 | case SKIN_TOKEN_LOGICAL_IF: | ||
1334 | function = parse_logical_if; | ||
1335 | break; | ||
1301 | case SKIN_TOKEN_PROGRESSBAR: | 1336 | case SKIN_TOKEN_PROGRESSBAR: |
1302 | case SKIN_TOKEN_VOLUME: | 1337 | case SKIN_TOKEN_VOLUME: |
1303 | case SKIN_TOKEN_BATTERY_PERCENT: | 1338 | case SKIN_TOKEN_BATTERY_PERCENT: |
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index b55588557a..36ad056410 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c | |||
@@ -315,6 +315,8 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3, | |||
315 | 315 | ||
316 | if (intval) | 316 | if (intval) |
317 | { | 317 | { |
318 | if (limit == TOKEN_VALUE_ONLY) | ||
319 | limit = 100; /* make it a percentage */ | ||
318 | *intval = limit * elapsed / length + 1; | 320 | *intval = limit * elapsed / length + 1; |
319 | } | 321 | } |
320 | snprintf(buf, buf_size, "%lu", 100 * elapsed / length); | 322 | snprintf(buf, buf_size, "%lu", 100 * elapsed / length); |
@@ -619,6 +621,72 @@ const char *get_token_value(struct gui_wps *gwps, | |||
619 | 621 | ||
620 | switch (token->type) | 622 | switch (token->type) |
621 | { | 623 | { |
624 | case SKIN_TOKEN_LOGICAL_IF: | ||
625 | { | ||
626 | struct logical_if *lif = token->value.data; | ||
627 | int a = lif->num_options; | ||
628 | int b; | ||
629 | out_text = get_token_value(gwps, lif->token, offset, buf, buf_size, &a); | ||
630 | if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
631 | a = (out_text && *out_text) ? 1 : 0; | ||
632 | switch (lif->operand.type) | ||
633 | { | ||
634 | case STRING: | ||
635 | if (lif->op == IF_EQUALS) | ||
636 | return strcmp(out_text, lif->operand.data.text) == 0 ? | ||
637 | "eq" : NULL; | ||
638 | else | ||
639 | return NULL; | ||
640 | break; | ||
641 | case INTEGER: | ||
642 | case DECIMAL: | ||
643 | b = lif->operand.data.number; | ||
644 | break; | ||
645 | case CODE: | ||
646 | { | ||
647 | char temp_buf[MAX_PATH]; | ||
648 | const char *outb; | ||
649 | struct wps_token *token = lif->operand.data.code->data; | ||
650 | b = lif->num_options; | ||
651 | outb = get_token_value(gwps, token, offset, temp_buf, | ||
652 | sizeof(temp_buf), &b); | ||
653 | if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
654 | { | ||
655 | if (!out_text || !outb) | ||
656 | return (lif->op == IF_EQUALS) ? NULL : "neq"; | ||
657 | bool equal = strcmp(out_text, outb) == 0; | ||
658 | if (lif->op == IF_EQUALS) | ||
659 | return equal ? "eq" : NULL; | ||
660 | else if (lif->op == IF_NOTEQUALS) | ||
661 | return !equal ? "neq" : NULL; | ||
662 | else | ||
663 | b = (outb && *outb) ? 1 : 0; | ||
664 | } | ||
665 | } | ||
666 | break; | ||
667 | case DEFAULT: | ||
668 | break; | ||
669 | } | ||
670 | |||
671 | switch (lif->op) | ||
672 | { | ||
673 | case IF_EQUALS: | ||
674 | return a == b ? "eq" : NULL; | ||
675 | case IF_NOTEQUALS: | ||
676 | return a != b ? "neq" : NULL; | ||
677 | case IF_LESSTHAN: | ||
678 | return a < b ? "lt" : NULL; | ||
679 | case IF_LESSTHAN_EQ: | ||
680 | return a <= b ? "lte" : NULL; | ||
681 | case IF_GREATERTHAN: | ||
682 | return a > b ? "gt" : NULL; | ||
683 | case IF_GREATERTHAN_EQ: | ||
684 | return a >= b ? "gte" : NULL; | ||
685 | } | ||
686 | return NULL; | ||
687 | } | ||
688 | break; | ||
689 | |||
622 | case SKIN_TOKEN_CHARACTER: | 690 | case SKIN_TOKEN_CHARACTER: |
623 | if (token->value.c == '\n') | 691 | if (token->value.c == '\n') |
624 | return NULL; | 692 | return NULL; |
@@ -632,6 +700,8 @@ const char *get_token_value(struct gui_wps *gwps, | |||
632 | 700 | ||
633 | case SKIN_TOKEN_PLAYLIST_ENTRIES: | 701 | case SKIN_TOKEN_PLAYLIST_ENTRIES: |
634 | snprintf(buf, buf_size, "%d", playlist_amount()); | 702 | snprintf(buf, buf_size, "%d", playlist_amount()); |
703 | if (intval) | ||
704 | *intval = playlist_amount(); | ||
635 | return buf; | 705 | return buf; |
636 | 706 | ||
637 | case SKIN_TOKEN_LIST_TITLE_TEXT: | 707 | case SKIN_TOKEN_LIST_TITLE_TEXT: |
@@ -647,6 +717,8 @@ const char *get_token_value(struct gui_wps *gwps, | |||
647 | 717 | ||
648 | case SKIN_TOKEN_PLAYLIST_POSITION: | 718 | case SKIN_TOKEN_PLAYLIST_POSITION: |
649 | snprintf(buf, buf_size, "%d", playlist_get_display_index()+offset); | 719 | snprintf(buf, buf_size, "%d", playlist_get_display_index()+offset); |
720 | if (intval) | ||
721 | *intval = playlist_get_display_index()+offset; | ||
650 | return buf; | 722 | return buf; |
651 | 723 | ||
652 | case SKIN_TOKEN_PLAYLIST_SHUFFLE: | 724 | case SKIN_TOKEN_PLAYLIST_SHUFFLE: |
@@ -661,7 +733,11 @@ const char *get_token_value(struct gui_wps *gwps, | |||
661 | if (intval) | 733 | if (intval) |
662 | { | 734 | { |
663 | int minvol = sound_min(SOUND_VOLUME); | 735 | int minvol = sound_min(SOUND_VOLUME); |
664 | if (global_settings.volume == minvol) | 736 | if (limit == TOKEN_VALUE_ONLY) |
737 | { | ||
738 | *intval = global_settings.volume; | ||
739 | } | ||
740 | else if (global_settings.volume == minvol) | ||
665 | { | 741 | { |
666 | *intval = 1; | 742 | *intval = 1; |
667 | } | 743 | } |
@@ -705,14 +781,21 @@ const char *get_token_value(struct gui_wps *gwps, | |||
705 | 781 | ||
706 | if (intval) | 782 | if (intval) |
707 | { | 783 | { |
708 | limit = MAX(limit, 3); | 784 | if (limit == TOKEN_VALUE_ONLY) |
709 | if (l > -1) { | 785 | { |
710 | /* First enum is used for "unknown level", | 786 | *intval = l; |
711 | * last enum is used for 100%. | 787 | } |
712 | */ | 788 | else |
713 | *intval = (limit - 2) * l / 100 + 2; | 789 | { |
714 | } else { | 790 | limit = MAX(limit, 3); |
715 | *intval = 1; | 791 | if (l > -1) { |
792 | /* First enum is used for "unknown level", | ||
793 | * last enum is used for 100%. | ||
794 | */ | ||
795 | *intval = (limit - 2) * l / 100 + 2; | ||
796 | } else { | ||
797 | *intval = 1; | ||
798 | } | ||
716 | } | 799 | } |
717 | } | 800 | } |
718 | 801 | ||
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index c886a7584f..81958c7966 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h | |||
@@ -50,7 +50,7 @@ | |||
50 | #define WPS_ALIGN_LEFT 128 | 50 | #define WPS_ALIGN_LEFT 128 |
51 | 51 | ||
52 | 52 | ||
53 | #define TOKEN_VALUE_ONLY 0xDEADD0D0 | 53 | #define TOKEN_VALUE_ONLY 0x0DEADC0D |
54 | 54 | ||
55 | #ifdef HAVE_ALBUMART | 55 | #ifdef HAVE_ALBUMART |
56 | 56 | ||
@@ -223,7 +223,7 @@ struct skin_albumart { | |||
223 | int draw_handle; | 223 | int draw_handle; |
224 | }; | 224 | }; |
225 | #endif | 225 | #endif |
226 | 226 | ||
227 | 227 | ||
228 | struct line { | 228 | struct line { |
229 | int timeout; /* if inside a line alternator */ | 229 | int timeout; /* if inside a line alternator */ |
@@ -240,6 +240,19 @@ struct conditional { | |||
240 | struct wps_token *token; | 240 | struct wps_token *token; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | struct logical_if { | ||
244 | struct wps_token *token; | ||
245 | enum { | ||
246 | IF_EQUALS, /* == */ | ||
247 | IF_NOTEQUALS, /* != */ | ||
248 | IF_LESSTHAN, /* < */ | ||
249 | IF_LESSTHAN_EQ, /* <= */ | ||
250 | IF_GREATERTHAN, /* > */ | ||
251 | IF_GREATERTHAN_EQ /* >= */ | ||
252 | } op; | ||
253 | struct skin_tag_parameter operand; | ||
254 | int num_options; | ||
255 | }; | ||
243 | 256 | ||
244 | /* wps_data | 257 | /* wps_data |
245 | this struct holds all necessary data which describes the | 258 | this struct holds all necessary data which describes the |
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c index 66deaab102..b3bc9856b9 100644 --- a/lib/skin_parser/skin_parser.c +++ b/lib/skin_parser/skin_parser.c | |||
@@ -621,11 +621,13 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
621 | } | 621 | } |
622 | temp_params[j] = '\0'; | 622 | temp_params[j] = '\0'; |
623 | j = 0; | 623 | j = 0; |
624 | while (cursor[j] != ',' && cursor[j] != ')') | 624 | while (cursor[j] && cursor[j] != ',' && cursor[j] != ')') |
625 | { | 625 | { |
626 | haspercent = haspercent || (cursor[j] == '%'); | 626 | haspercent = haspercent || (cursor[j] == '%'); |
627 | hasdecimal = hasdecimal || (cursor[j] == '.'); | 627 | hasdecimal = hasdecimal || (cursor[j] == '.'); |
628 | number = number && (isdigit(cursor[j]) || (cursor[j] == '.')); | 628 | number = number && (isdigit(cursor[j]) || |
629 | (cursor[j] == '.') || | ||
630 | (cursor[j] == '-')); | ||
629 | j++; | 631 | j++; |
630 | } | 632 | } |
631 | type_code = '*'; | 633 | type_code = '*'; |
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index 9924d06619..9c0b51dacf 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c | |||
@@ -33,6 +33,8 @@ static const struct tag_info legal_tags[] = | |||
33 | { SKIN_TOKEN_ALIGN_RIGHT_RTL, "aR", "", 0 }, | 33 | { SKIN_TOKEN_ALIGN_RIGHT_RTL, "aR", "", 0 }, |
34 | { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, | 34 | { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, |
35 | 35 | ||
36 | { SKIN_TOKEN_LOGICAL_IF, "if", "TS[ITS]|D", SKIN_REFRESH_DYNAMIC }, | ||
37 | |||
36 | { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC }, | 38 | { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC }, |
37 | { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC }, | 39 | { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC }, |
38 | { SKIN_TOKEN_BATTERY_TIME, "bt", "", SKIN_REFRESH_DYNAMIC }, | 40 | { SKIN_TOKEN_BATTERY_TIME, "bt", "", SKIN_REFRESH_DYNAMIC }, |
diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h index 4b7efaa835..f16709d133 100644 --- a/lib/skin_parser/tag_table.h +++ b/lib/skin_parser/tag_table.h | |||
@@ -73,6 +73,7 @@ enum skin_token_type { | |||
73 | SKIN_TOKEN_SUBLINE_SCROLL, | 73 | SKIN_TOKEN_SUBLINE_SCROLL, |
74 | 74 | ||
75 | /* Conditional */ | 75 | /* Conditional */ |
76 | SKIN_TOKEN_LOGICAL_IF, | ||
76 | SKIN_TOKEN_CONDITIONAL, | 77 | SKIN_TOKEN_CONDITIONAL, |
77 | SKIN_TOKEN_CONDITIONAL_START, | 78 | SKIN_TOKEN_CONDITIONAL_START, |
78 | SKIN_TOKEN_CONDITIONAL_OPTION, | 79 | SKIN_TOKEN_CONDITIONAL_OPTION, |