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:
Stéphane Doyon 2007-10-21 00:20:10 +00:00
parent 5ca8abfff0
commit 8486c0413e
3 changed files with 132 additions and 4 deletions

View file

@ -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];

View file

@ -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_ */

View file

@ -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>