1. diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
  2. index 2c76616..4773c0e 100644
  3. --- a/apps/gui/skin_engine/skin_parser.c
  4. +++ b/apps/gui/skin_engine/skin_parser.c
  5. @@ -1330,6 +1330,9 @@ static int skin_element_callback(struct skin_element* element, void* data)
  6. case SKIN_TOKEN_ALIGN_LANGDIRECTION:
  7. follow_lang_direction = 2;
  8. break;
  9. + case SKIN_TOKEN_VOICE:
  10. + token->value.data = current_tick;
  11. + break;
  12. case SKIN_TOKEN_LOGICAL_IF:
  13. function = parse_logical_if;
  14. break;
  15. diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
  16. index 0c18848..a602725 100644
  17. --- a/apps/gui/skin_engine/skin_render.c
  18. +++ b/apps/gui/skin_engine/skin_render.c
  19. @@ -46,6 +46,8 @@
  20. #include "playlist.h"
  21. #include "root_menu.h"
  22. #include "misc.h"
  23. +#include "talk.h"
  24. +#include "lang.h"
  25.  
  26.  
  27. #define MAX_LINE 1024
  28. @@ -78,6 +80,44 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer,
  29. unsigned long refresh_type);
  30. #endif
  31.  
  32. +static void skin_do_talking_tags(struct gui_wps *gwps, struct skin_draw_info *info,
  33. + struct skin_element *element)
  34. +{
  35. + int i, val;
  36. + char buf[128];
  37. + const char* out;
  38. + struct wps_token *token;
  39. + for (i=0; i<element->params_count; i++)
  40. + {
  41. + struct skin_tag_parameter *param = &element->params[i];
  42. + switch (param->type)
  43. + {
  44. + case DEFAULT:
  45. + if (i==0)
  46. + talk_shutup();
  47. + else
  48. + talk_id(VOICE_PAUSE, true);
  49. + break;
  50. + case STRING:
  51. + talk_spell(param->data.text, true);
  52. + break;
  53. + case CODE:
  54. + val = TOKEN_VALUE_ONLY;
  55. + token = param->data.code->data;
  56. + out = get_token_value(gwps, token, 0,
  57. + buf, sizeof buf, &val);
  58. + if (val != -1 || token->type == SKIN_TOKEN_VOLUME)
  59. + talk_number(val, true);
  60. + else
  61. + talk_spell(out, true);
  62. + break;
  63. + default:
  64. + break;
  65. + }
  66. + }
  67. +
  68. +}
  69. +
  70. static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
  71. struct skin_element *element, struct viewport* vp)
  72. {
  73. @@ -89,6 +129,14 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
  74. bool do_refresh = (element->tag->flags & info->refresh_type) > 0;
  75. switch (token->type)
  76. {
  77. + case SKIN_TOKEN_VOICE:
  78. + if (TIME_AFTER(current_tick, token->value.data+HZ))
  79. + {
  80. + printf("%d %d\n", current_tick, token->value.data);
  81. + skin_do_talking_tags(gwps, info, element);
  82. + }
  83. + token->value.data = current_tick;
  84. + break;
  85. #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
  86. case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
  87. {
  88. diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
  89. index 9c0b51d..4418ff1 100644
  90. --- a/lib/skin_parser/tag_table.c
  91. +++ b/lib/skin_parser/tag_table.c
  92. @@ -191,6 +191,9 @@ static const struct tag_info legal_tags[] =
  93. { SKIN_TOKEN_UIVIEWPORT_LOAD, "Vi" , "sIIiii", 0 },
  94. { SKIN_TOKEN_VIEWPORT_LOAD, "V" , "IIiii", 0 },
  95.  
  96. + { SKIN_TOKEN_VOICE, "Vx", "|[sT][sT][sT][sT][sT][sT][sT][sT]",
  97. + SKIN_REFRESH_STATIC|NOBREAK },
  98. +
  99. { SKIN_TOKEN_IMAGE_BACKDROP, "X" , "f", SKIN_REFRESH_STATIC|NOBREAK },
  100.  
  101. { SKIN_TOKEN_SETTING, "St" , "S", SKIN_REFRESH_DYNAMIC },
  102. diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h
  103. index f16709d..670ca98 100644
  104. --- a/lib/skin_parser/tag_table.h
  105. +++ b/lib/skin_parser/tag_table.h
  106. @@ -210,6 +210,8 @@ enum skin_token_type {
  107.  
  108. SKIN_TOKEN_LOAD_FONT,
  109.  
  110. + SKIN_TOKEN_VOICE,
  111. +
  112. /* buttons */
  113. SKIN_TOKEN_BUTTON_VOLUME,
  114. SKIN_TOKEN_LASTTOUCH,