diff --git a/openrtx/include/core/voicePromptUtils.h b/openrtx/include/core/voicePromptUtils.h index 249b3c35..b5caf2f4 100644 --- a/openrtx/include/core/voicePromptUtils.h +++ b/openrtx/include/core/voicePromptUtils.h @@ -35,4 +35,12 @@ void AnnounceInputChar(char ch); void announceInputReceiveOrTransmit(bool tx, VoicePromptQueueFlags_T flags); void ReplayLastPrompt(); void announceError(VoicePromptQueueFlags_T flags); + +/* +This function first tries to see if we have a prompt for the text +passed in and if so, queues it, but if not, just spells the text +character by character. +*/ +void announceText( char* text, VoicePromptQueueFlags_T flags); + #endif //VOICE_PROMPT_UTILS_H_INCLUDED \ No newline at end of file diff --git a/openrtx/include/ui/UIStrings.h b/openrtx/include/ui/UIStrings.h index 4af9af45..e9b78501 100644 --- a/openrtx/include/ui/UIStrings.h +++ b/openrtx/include/ui/UIStrings.h @@ -92,4 +92,6 @@ typedef struct extern const stringsTable_t languages[]; extern const stringsTable_t* currentLanguage; +int GetEnglishStringTableOffset( char* text); + #endif \ No newline at end of file diff --git a/openrtx/src/core/voicePromptUtils.c b/openrtx/src/core/voicePromptUtils.c index df94e036..27994688 100644 --- a/openrtx/src/core/voicePromptUtils.c +++ b/openrtx/src/core/voicePromptUtils.c @@ -193,3 +193,20 @@ void announceError(VoicePromptQueueFlags_T flags) vpPlayIfNeeded(flags); } + +void announceText( char* text, VoicePromptQueueFlags_T flags) +{ + if (!text || !*text) + return; + + vpInitIfNeeded(flags); + // see if we have a prompt for this string. + int offset = GetEnglishStringTableOffset(text); + + if (offset != -1) + vpQueueStringTableEntry((const char* const *)(¤tLanguage->languageName + offset)); + else // just spel it out + vpQueueString(text, (flags&~(vpqInit|vpqPlayImmediately))); + + vpPlayIfNeeded(flags); +} diff --git a/openrtx/src/ui/UIStrings.c b/openrtx/src/ui/UIStrings.c index f0037743..e91a5fb9 100644 --- a/openrtx/src/ui/UIStrings.c +++ b/openrtx/src/ui/UIStrings.c @@ -22,9 +22,36 @@ This string table's order must not be altered as voice prompts will be indexed i */ #include "ui/UIStrings.h" #include "ui/EnglishStrings.h" - + #include + // add more languages here. const stringsTable_t languages[NUM_LANGUAGES]={ englishStrings }; // default to English. const stringsTable_t* currentLanguage=&languages[0]; + +/* +Given an english string such as a menu item or value, +search the english string table and return the offset if found. +This can then be used to look up the localized string in the currentLanguages +struct, or to announce an indexed voice prompt. +*/ +int GetEnglishStringTableOffset( char* text) +{ + if (!text || !*text) + return -1; // error. + + uint8_t stringCount =sizeof(stringsTable_t)/sizeof(char*); + + for (uint8_t i = 0; i < stringCount; ++i) + { + const char* strPtr = ((const char **)&englishStrings)[i]; + + if (strcmp(text, strPtr) == 0) + { + return (i * sizeof(char *)); + } + } + + return -1; +} diff --git a/openrtx/src/ui/ui_menu.c b/openrtx/src/ui/ui_menu.c index f9443c45..c9cb84d4 100644 --- a/openrtx/src/ui/ui_menu.c +++ b/openrtx/src/ui/ui_menu.c @@ -29,10 +29,11 @@ #include #include #include +#include /* UI main screen helper functions, their implementation is in "ui_main.c" */ extern void _ui_drawMainBottom(); - +static int priorMenuIndex = -1; const char *display_timer_values[] = { "Off", @@ -53,6 +54,31 @@ const char *display_timer_values[] = "1 hour" }; +bool DidSelectedMenuItemChange(uint8_t index) +{ + if (priorMenuIndex == -1) + return true; + bool result = index != priorMenuIndex; + priorMenuIndex = index; + return result; +} + +static void announceMenuItemIfNeeded(uint8_t index, char* name, char* value) +{ + if (!name || !*name) + return; + + if (!DidSelectedMenuItemChange(index)) + return; + + announceText(name, vpqInit); + + if (value && *value) + announceText(name, vpqDefault); + + vpPlay(); +} + void _ui_drawMenuList(uint8_t selected, int (*getCurrentEntry)(char *buf, uint8_t max_len, uint8_t index)) { point_t pos = layout.line1_pos; @@ -77,6 +103,7 @@ void _ui_drawMenuList(uint8_t selected, int (*getCurrentEntry)(char *buf, uint8_ // Draw rectangle under selected item, compensating for text height point_t rect_pos = {0, pos.y - layout.menu_h + 3}; gfx_drawRect(rect_pos, SCREEN_WIDTH, layout.menu_h, color_white, true); + announceMenuItemIfNeeded(item+scroll, entry_buf, NULL); } gfx_print(pos, layout.menu_font, TEXT_ALIGN_LEFT, text_color, entry_buf); pos.y += layout.menu_h; @@ -120,6 +147,11 @@ void _ui_drawMenuListValue(ui_state_t* ui_state, uint8_t selected, } point_t rect_pos = {0, pos.y - layout.menu_h + 3}; gfx_drawRect(rect_pos, SCREEN_WIDTH, layout.menu_h, color_white, full_rect); + if (!ui_state->edit_mode) + {// If in edit mode, only want to speak the char being entered,, + //not repeat the entire display. + announceMenuItemIfNeeded(item+scroll, entry_buf, value_buf); + } } gfx_print(pos, layout.menu_font, TEXT_ALIGN_LEFT, text_color, entry_buf); gfx_print(pos, layout.menu_font, TEXT_ALIGN_RIGHT, text_color, value_buf);