mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 13:15:18 -05:00
Accept FS#7774: Voice callback for gui_synclist.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15231 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
5ca8abfff0
commit
8486c0413e
3 changed files with 132 additions and 4 deletions
|
|
@ -36,6 +36,7 @@
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "talk.h"
|
||||||
|
|
||||||
#ifdef HAVE_LCD_CHARCELLS
|
#ifdef HAVE_LCD_CHARCELLS
|
||||||
#define SCROLL_LIMIT 1
|
#define SCROLL_LIMIT 1
|
||||||
|
|
@ -78,6 +79,7 @@ static void gui_list_init(struct gui_list * gui_list,
|
||||||
{
|
{
|
||||||
gui_list->callback_get_item_icon = NULL;
|
gui_list->callback_get_item_icon = NULL;
|
||||||
gui_list->callback_get_item_name = callback_get_item_name;
|
gui_list->callback_get_item_name = callback_get_item_name;
|
||||||
|
gui_list->callback_speak_item = NULL;
|
||||||
gui_list->display = NULL;
|
gui_list->display = NULL;
|
||||||
gui_list_set_nb_items(gui_list, 0);
|
gui_list_set_nb_items(gui_list, 0);
|
||||||
gui_list->selected_item = 0;
|
gui_list->selected_item = 0;
|
||||||
|
|
@ -95,6 +97,7 @@ static void gui_list_init(struct gui_list * gui_list,
|
||||||
|
|
||||||
gui_list->last_displayed_selected_item = -1 ;
|
gui_list->last_displayed_selected_item = -1 ;
|
||||||
gui_list->last_displayed_start_item = -1 ;
|
gui_list->last_displayed_start_item = -1 ;
|
||||||
|
gui_list->scheduled_talk_tick = gui_list->last_talked_tick = 0;
|
||||||
gui_list->show_selection_marker = true;
|
gui_list->show_selection_marker = true;
|
||||||
|
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
|
|
@ -786,6 +789,12 @@ void gui_synclist_set_icon_callback(struct gui_synclist * lists,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_synclist_set_voice_callback(struct gui_synclist * lists,
|
||||||
|
list_speak_item voice_callback)
|
||||||
|
{
|
||||||
|
gui_list_set_voice_callback(&(lists->gui_list[0]), voice_callback);
|
||||||
|
}
|
||||||
|
|
||||||
void gui_synclist_draw(struct gui_synclist * lists)
|
void gui_synclist_draw(struct gui_synclist * lists)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -863,6 +872,43 @@ static void gui_synclist_scroll_left(struct gui_synclist * lists)
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LCD_BITMAP */
|
#endif /* HAVE_LCD_BITMAP */
|
||||||
|
|
||||||
|
static void _gui_synclist_speak_item(struct gui_synclist *lists, bool repeating)
|
||||||
|
{
|
||||||
|
struct gui_list *l = &lists->gui_list[0];
|
||||||
|
list_speak_item *cb = l->callback_speak_item;
|
||||||
|
if(cb && gui_synclist_get_nb_items(lists) != 0)
|
||||||
|
{
|
||||||
|
int sel = gui_synclist_get_sel_pos(lists);
|
||||||
|
talk_shutup();
|
||||||
|
/* If we got a repeating key action, or we have just very
|
||||||
|
recently started talking, then we want to stay silent for a
|
||||||
|
while until things settle. Likewise if we already had a
|
||||||
|
pending scheduled announcement not yet due: we need to
|
||||||
|
reschedule it. */
|
||||||
|
if(repeating
|
||||||
|
|| (l->scheduled_talk_tick
|
||||||
|
&& TIME_BEFORE(current_tick, l->scheduled_talk_tick))
|
||||||
|
|| (l->last_talked_tick
|
||||||
|
&& TIME_BEFORE(current_tick, l->last_talked_tick +HZ/4)))
|
||||||
|
{
|
||||||
|
l->scheduled_talk_tick = current_tick +HZ/4;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
l->scheduled_talk_tick = 0; /* work done */
|
||||||
|
cb(sel, l->data);
|
||||||
|
l->last_talked_tick = current_tick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void gui_synclist_speak_item(struct gui_synclist * lists)
|
||||||
|
/* The list user should call this to speak the first item on entering
|
||||||
|
the list, and whenever the list is updated. */
|
||||||
|
{
|
||||||
|
if(gui_synclist_get_nb_items(lists) == 0 && global_settings.talk_menu)
|
||||||
|
talk_id(VOICE_EMPTY_LIST, true);
|
||||||
|
else _gui_synclist_speak_item(lists, false);
|
||||||
|
}
|
||||||
|
|
||||||
extern intptr_t get_action_data(void);
|
extern intptr_t get_action_data(void);
|
||||||
|
|
||||||
bool gui_synclist_do_button(struct gui_synclist * lists,
|
bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
|
|
@ -941,9 +987,10 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
#ifndef HAVE_SCROLLWHEEL
|
#ifndef HAVE_SCROLLWHEEL
|
||||||
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
gui_synclist_draw(lists);
|
gui_synclist_draw(lists);
|
||||||
}
|
_gui_synclist_speak_item(lists,
|
||||||
|
action == ACTION_STD_PREVREPEAT
|
||||||
|
|| next_item_modifier >1);
|
||||||
yield();
|
yield();
|
||||||
*actionptr = ACTION_STD_PREV;
|
*actionptr = ACTION_STD_PREV;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -955,9 +1002,10 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
#ifndef HAVE_SCROLLWHEEL
|
#ifndef HAVE_SCROLLWHEEL
|
||||||
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
gui_synclist_draw(lists);
|
gui_synclist_draw(lists);
|
||||||
}
|
_gui_synclist_speak_item(lists,
|
||||||
|
action == ACTION_STD_NEXTREPEAT
|
||||||
|
|| next_item_modifier >1);
|
||||||
yield();
|
yield();
|
||||||
*actionptr = ACTION_STD_NEXT;
|
*actionptr = ACTION_STD_NEXT;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1006,6 +1054,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
SCREEN_MAIN;
|
SCREEN_MAIN;
|
||||||
gui_synclist_select_previous_page(lists, screen);
|
gui_synclist_select_previous_page(lists, screen);
|
||||||
gui_synclist_draw(lists);
|
gui_synclist_draw(lists);
|
||||||
|
_gui_synclist_speak_item(lists, false);
|
||||||
yield();
|
yield();
|
||||||
*actionptr = ACTION_STD_NEXT;
|
*actionptr = ACTION_STD_NEXT;
|
||||||
}
|
}
|
||||||
|
|
@ -1021,14 +1070,48 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
SCREEN_MAIN;
|
SCREEN_MAIN;
|
||||||
gui_synclist_select_next_page(lists, screen);
|
gui_synclist_select_next_page(lists, screen);
|
||||||
gui_synclist_draw(lists);
|
gui_synclist_draw(lists);
|
||||||
|
_gui_synclist_speak_item(lists, false);
|
||||||
yield();
|
yield();
|
||||||
*actionptr = ACTION_STD_PREV;
|
*actionptr = ACTION_STD_PREV;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if(lists->gui_list[0].scheduled_talk_tick
|
||||||
|
&& TIME_AFTER(current_tick, lists->gui_list[0].scheduled_talk_tick))
|
||||||
|
/* scheduled postponed item announcement is due */
|
||||||
|
_gui_synclist_speak_item(lists, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int list_do_action_timeout(struct gui_synclist *lists, int timeout)
|
||||||
|
/* Returns the lowest of timeout or the delay until a postponed
|
||||||
|
scheduled announcement is due (if any). */
|
||||||
|
{
|
||||||
|
if(lists->gui_list[0].scheduled_talk_tick)
|
||||||
|
{
|
||||||
|
long delay = lists->gui_list[0].scheduled_talk_tick -current_tick +1;
|
||||||
|
/* +1 because the trigger condition uses TIME_AFTER(), which
|
||||||
|
is implemented as strictly greater than. */
|
||||||
|
if(delay < 0)
|
||||||
|
delay = 0;
|
||||||
|
if(timeout > delay || timeout == TIMEOUT_BLOCK)
|
||||||
|
timeout = delay;
|
||||||
|
}
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool list_do_action(int context, int timeout,
|
||||||
|
struct gui_synclist *lists, int *action,
|
||||||
|
enum list_wrap wrap)
|
||||||
|
/* Combines the get_action() (with possibly overridden timeout) and
|
||||||
|
gui_synclist_do_button() calls. Returns the list action from
|
||||||
|
do_button, and places the action from get_action in *action. */
|
||||||
|
{
|
||||||
|
timeout = list_do_action_timeout(lists, timeout);
|
||||||
|
*action = get_action(context, timeout);
|
||||||
|
return gui_synclist_do_button(lists, action, wrap);
|
||||||
|
}
|
||||||
|
|
||||||
/* Simple use list implementation */
|
/* Simple use list implementation */
|
||||||
static int simplelist_line_count = 0;
|
static int simplelist_line_count = 0;
|
||||||
static char simplelist_text[SIMPLELIST_MAX_LINES][SIMPLELIST_MAX_LINELENGTH];
|
static char simplelist_text[SIMPLELIST_MAX_LINES][SIMPLELIST_MAX_LINELENGTH];
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,14 @@ typedef enum themable_icons list_get_icon(int selected_item, void * data);
|
||||||
* Returns a pointer to a string that contains the text to display
|
* Returns a pointer to a string that contains the text to display
|
||||||
*/
|
*/
|
||||||
typedef char * list_get_name(int selected_item, void * data, char * buffer);
|
typedef char * list_get_name(int selected_item, void * data, char * buffer);
|
||||||
|
/*
|
||||||
|
* Voice callback
|
||||||
|
* - selected_item : an integer that tells the number of the item to speak
|
||||||
|
* - data : a void pointer to the data you gave to the list when you
|
||||||
|
* initialized it
|
||||||
|
* Returns an integer, 0 means success, ignored really...
|
||||||
|
*/
|
||||||
|
typedef int list_speak_item(int selected_item, void * data);
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
/*
|
/*
|
||||||
* Color callback
|
* Color callback
|
||||||
|
|
@ -97,9 +105,11 @@ struct gui_list
|
||||||
#endif
|
#endif
|
||||||
/* Cache the width of the title string in pixels/characters */
|
/* Cache the width of the title string in pixels/characters */
|
||||||
int title_width;
|
int title_width;
|
||||||
|
long scheduled_talk_tick, last_talked_tick;
|
||||||
|
|
||||||
list_get_icon *callback_get_item_icon;
|
list_get_icon *callback_get_item_icon;
|
||||||
list_get_name *callback_get_item_name;
|
list_get_name *callback_get_item_name;
|
||||||
|
list_speak_item *callback_speak_item;
|
||||||
|
|
||||||
struct screen * display;
|
struct screen * display;
|
||||||
/* The data that will be passed to the callback function YOU implement */
|
/* The data that will be passed to the callback function YOU implement */
|
||||||
|
|
@ -140,6 +150,14 @@ struct gui_list
|
||||||
#define gui_list_set_icon_callback(gui_list, _callback) \
|
#define gui_list_set_icon_callback(gui_list, _callback) \
|
||||||
(gui_list)->callback_get_item_icon=_callback
|
(gui_list)->callback_get_item_icon=_callback
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the voice callback function
|
||||||
|
* - gui_list : the list structure
|
||||||
|
* - _callback : the callback function
|
||||||
|
*/
|
||||||
|
#define gui_list_set_voice_callback(gui_list, _callback) \
|
||||||
|
(gui_list)->callback_speak_item=_callback
|
||||||
|
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
/*
|
/*
|
||||||
* Sets the color callback function
|
* Sets the color callback function
|
||||||
|
|
@ -200,6 +218,8 @@ extern void gui_synclist_init(
|
||||||
);
|
);
|
||||||
extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items);
|
extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items);
|
||||||
extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback);
|
extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback);
|
||||||
|
extern void gui_synclist_set_voice_callback(struct gui_synclist * lists, list_speak_item voice_callback);
|
||||||
|
extern void gui_synclist_speak_item(struct gui_synclist * lists);
|
||||||
extern int gui_synclist_get_nb_items(struct gui_synclist * lists);
|
extern int gui_synclist_get_nb_items(struct gui_synclist * lists);
|
||||||
|
|
||||||
extern int gui_synclist_get_sel_pos(struct gui_synclist * lists);
|
extern int gui_synclist_get_sel_pos(struct gui_synclist * lists);
|
||||||
|
|
@ -266,4 +286,15 @@ void simplelist_addline(int line_number, const char *fmt, ...);
|
||||||
before the list is dislplayed for the first time */
|
before the list is dislplayed for the first time */
|
||||||
bool simplelist_show_list(struct simplelist_info *info);
|
bool simplelist_show_list(struct simplelist_info *info);
|
||||||
|
|
||||||
|
/* If the list has a pending postponed scheduled announcement, that
|
||||||
|
may become due before the next get_action tmieout. This function
|
||||||
|
adjusts the get_action timeout appropriately. */
|
||||||
|
extern int list_do_action_timeout(struct gui_synclist *lists, int timeout);
|
||||||
|
/* This one combines a get_action call (with timeout overridden by
|
||||||
|
list_do_action_timeout) with the gui_synclist_do_button call, for
|
||||||
|
convenience. */
|
||||||
|
extern bool list_do_action(int context, int timeout,
|
||||||
|
struct gui_synclist *lists, int *action,
|
||||||
|
enum list_wrap wrap);
|
||||||
|
|
||||||
#endif /* _GUI_LIST_H_ */
|
#endif /* _GUI_LIST_H_ */
|
||||||
|
|
|
||||||
|
|
@ -11417,3 +11417,17 @@
|
||||||
*: "Blank"
|
*: "Blank"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: VOICE_EMPTY_LIST
|
||||||
|
desc: spoken only, when a list dialog contains no elements
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: ""
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: ""
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Empty list"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue