summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-08-19 13:49:32 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-08-19 13:49:32 +0000
commit74ec011bb8df08b0fba3709cc590ce3842b1c973 (patch)
treef70f9dc4ac88f018ac537971c8ead37f5c290920
parentb73d15e9c6175ac48b2280b089a40f0554d15d6f (diff)
downloadrockbox-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.c37
-rw-r--r--apps/gui/skin_engine/skin_tokens.c101
-rw-r--r--apps/gui/skin_engine/wps_internals.h17
-rw-r--r--lib/skin_parser/skin_parser.c6
-rw-r--r--lib/skin_parser/tag_table.c2
-rw-r--r--lib/skin_parser/tag_table.h1
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 505static 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}
506static int parse_timeout_tag(struct skin_element *element, 538static 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
228struct line { 228struct 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
243struct 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,