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 "sound.h"
|
||||
#include "misc.h"
|
||||
#include "talk.h"
|
||||
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
#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_name = callback_get_item_name;
|
||||
gui_list->callback_speak_item = NULL;
|
||||
gui_list->display = NULL;
|
||||
gui_list_set_nb_items(gui_list, 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_start_item = -1 ;
|
||||
gui_list->scheduled_talk_tick = gui_list->last_talked_tick = 0;
|
||||
gui_list->show_selection_marker = true;
|
||||
|
||||
#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)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -863,6 +872,43 @@ static void gui_synclist_scroll_left(struct gui_synclist * lists)
|
|||
}
|
||||
#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);
|
||||
|
||||
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
|
||||
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
||||
#endif
|
||||
{
|
||||
gui_synclist_draw(lists);
|
||||
}
|
||||
_gui_synclist_speak_item(lists,
|
||||
action == ACTION_STD_PREVREPEAT
|
||||
|| next_item_modifier >1);
|
||||
yield();
|
||||
*actionptr = ACTION_STD_PREV;
|
||||
return true;
|
||||
|
|
@ -955,9 +1002,10 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
|||
#ifndef HAVE_SCROLLWHEEL
|
||||
if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
|
||||
#endif
|
||||
{
|
||||
gui_synclist_draw(lists);
|
||||
}
|
||||
_gui_synclist_speak_item(lists,
|
||||
action == ACTION_STD_NEXTREPEAT
|
||||
|| next_item_modifier >1);
|
||||
yield();
|
||||
*actionptr = ACTION_STD_NEXT;
|
||||
return true;
|
||||
|
|
@ -1006,6 +1054,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
|||
SCREEN_MAIN;
|
||||
gui_synclist_select_previous_page(lists, screen);
|
||||
gui_synclist_draw(lists);
|
||||
_gui_synclist_speak_item(lists, false);
|
||||
yield();
|
||||
*actionptr = ACTION_STD_NEXT;
|
||||
}
|
||||
|
|
@ -1021,14 +1070,48 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
|||
SCREEN_MAIN;
|
||||
gui_synclist_select_next_page(lists, screen);
|
||||
gui_synclist_draw(lists);
|
||||
_gui_synclist_speak_item(lists, false);
|
||||
yield();
|
||||
*actionptr = ACTION_STD_PREV;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
static int simplelist_line_count = 0;
|
||||
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
|
||||
*/
|
||||
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
|
||||
/*
|
||||
* Color callback
|
||||
|
|
@ -97,9 +105,11 @@ struct gui_list
|
|||
#endif
|
||||
/* Cache the width of the title string in pixels/characters */
|
||||
int title_width;
|
||||
long scheduled_talk_tick, last_talked_tick;
|
||||
|
||||
list_get_icon *callback_get_item_icon;
|
||||
list_get_name *callback_get_item_name;
|
||||
list_speak_item *callback_speak_item;
|
||||
|
||||
struct screen * display;
|
||||
/* 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) \
|
||||
(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
|
||||
/*
|
||||
* 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_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_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 */
|
||||
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_ */
|
||||
|
|
|
|||
|
|
@ -11417,3 +11417,17 @@
|
|||
*: "Blank"
|
||||
</voice>
|
||||
</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