summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/gui/list.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index ef2711d7c9..b39684ff92 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -292,6 +292,43 @@ static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list,
292 gui_list->start_item[screen] = new_start_item; 292 gui_list->start_item[screen] = new_start_item;
293} 293}
294 294
295static void _gui_synclist_speak_item(struct gui_synclist *lists)
296{
297 list_speak_item *cb = lists->callback_speak_item;
298 if (cb && lists->nb_items != 0)
299 {
300 talk_shutup();
301 /* If we have just very recently started talking, then we want
302 to stay silent for a while until things settle. Likewise if
303 we already had a pending scheduled announcement not yet due
304 we need to reschedule it. */
305 if ((lists->scheduled_talk_tick &&
306 TIME_BEFORE(current_tick, lists->scheduled_talk_tick)) ||
307 (lists->last_talked_tick &&
308 TIME_BEFORE(current_tick, lists->last_talked_tick + HZ/5)))
309 {
310 lists->scheduled_talk_tick = current_tick + HZ/5;
311 }
312 else
313 {
314 lists->scheduled_talk_tick = 0; /* work done */
315 cb(lists->selected_item, lists->data);
316 lists->last_talked_tick = current_tick;
317 }
318 }
319}
320
321void gui_synclist_speak_item(struct gui_synclist *lists)
322{
323 if (global_settings.talk_menu)
324 {
325 if (lists->nb_items == 0)
326 talk_id(VOICE_EMPTY_LIST, true);
327 else
328 _gui_synclist_speak_item(lists);
329 }
330}
331
295/* 332/*
296 * Selects an item in the list 333 * Selects an item in the list
297 * - gui_list : the list structure 334 * - gui_list : the list structure
@@ -302,7 +339,11 @@ void gui_synclist_select_item(struct gui_synclist * gui_list, int item_number)
302 int i; 339 int i;
303 if (item_number >= gui_list->nb_items || item_number < 0) 340 if (item_number >= gui_list->nb_items || item_number < 0)
304 return; 341 return;
305 gui_list->selected_item = item_number; 342 if (item_number != gui_list->selected_item)
343 {
344 gui_list->selected_item = item_number;
345 _gui_synclist_speak_item(gui_list);
346 }
306 FOR_NB_SCREENS(i) 347 FOR_NB_SCREENS(i)
307 gui_list_put_selection_on_screen(gui_list, i); 348 gui_list_put_selection_on_screen(gui_list, i);
308} 349}
@@ -320,12 +361,12 @@ static void gui_list_select_at_offset(struct gui_synclist * gui_list,
320 361
321 if (new_selection >= gui_list->nb_items) 362 if (new_selection >= gui_list->nb_items)
322 { 363 {
323 gui_list->selected_item = gui_list->limit_scroll ? 364 new_selection = gui_list->limit_scroll ?
324 gui_list->nb_items - gui_list->selected_size : 0; 365 gui_list->nb_items - gui_list->selected_size : 0;
325 } 366 }
326 else if (new_selection < 0) 367 else if (new_selection < 0)
327 { 368 {
328 gui_list->selected_item = gui_list->limit_scroll ? 369 new_selection = gui_list->limit_scroll ?
329 0 : gui_list->nb_items - gui_list->selected_size; 370 0 : gui_list->nb_items - gui_list->selected_size;
330 } 371 }
331 else if (gui_list->show_selection_marker == false) 372 else if (gui_list->show_selection_marker == false)
@@ -350,8 +391,7 @@ static void gui_list_select_at_offset(struct gui_synclist * gui_list,
350 } 391 }
351 return; 392 return;
352 } 393 }
353 else gui_list->selected_item += offset; 394 gui_synclist_select_item(gui_list, new_selection);
354 gui_synclist_select_item(gui_list, gui_list->selected_item);
355} 395}
356 396
357/* 397/*
@@ -510,42 +550,6 @@ static void gui_synclist_scroll_left(struct gui_synclist * lists)
510} 550}
511#endif /* HAVE_LCD_BITMAP */ 551#endif /* HAVE_LCD_BITMAP */
512 552
513static void _gui_synclist_speak_item(struct gui_synclist *lists, bool repeating)
514{
515 list_speak_item *cb = lists->callback_speak_item;
516 if(cb && gui_synclist_get_nb_items(lists) != 0)
517 {
518 int sel = gui_synclist_get_sel_pos(lists);
519 talk_shutup();
520 /* If we got a repeating key action, or we have just very
521 recently started talking, then we want to stay silent for a
522 while until things settle. Likewise if we already had a
523 pending scheduled announcement not yet due: we need to
524 reschedule it. */
525 if(repeating
526 || (lists->scheduled_talk_tick
527 && TIME_BEFORE(current_tick, lists->scheduled_talk_tick))
528 || (lists->last_talked_tick
529 && TIME_BEFORE(current_tick, lists->last_talked_tick +HZ/4)))
530 {
531 lists->scheduled_talk_tick = current_tick +HZ/4;
532 return;
533 } else {
534 lists->scheduled_talk_tick = 0; /* work done */
535 cb(sel, lists->data);
536 lists->last_talked_tick = current_tick;
537 }
538 }
539}
540void gui_synclist_speak_item(struct gui_synclist * lists)
541/* The list user should call this to speak the first item on entering
542 the list, and whenever the list is updated. */
543{
544 if(gui_synclist_get_nb_items(lists) == 0 && global_settings.talk_menu)
545 talk_id(VOICE_EMPTY_LIST, true);
546 else _gui_synclist_speak_item(lists, false);
547}
548
549bool gui_synclist_do_button(struct gui_synclist * lists, 553bool gui_synclist_do_button(struct gui_synclist * lists,
550 int *actionptr, enum list_wrap wrap) 554 int *actionptr, enum list_wrap wrap)
551{ 555{
@@ -627,9 +631,6 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
627 if (button_queue_count() < FRAMEDROP_TRIGGER) 631 if (button_queue_count() < FRAMEDROP_TRIGGER)
628#endif 632#endif
629 gui_synclist_draw(lists); 633 gui_synclist_draw(lists);
630 _gui_synclist_speak_item(lists,
631 action == ACTION_STD_PREVREPEAT
632 || next_item_modifier > 1);
633 yield(); 634 yield();
634 *actionptr = ACTION_STD_PREV; 635 *actionptr = ACTION_STD_PREV;
635 return true; 636 return true;
@@ -641,9 +642,6 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
641 if (button_queue_count() < FRAMEDROP_TRIGGER) 642 if (button_queue_count() < FRAMEDROP_TRIGGER)
642#endif 643#endif
643 gui_synclist_draw(lists); 644 gui_synclist_draw(lists);
644 _gui_synclist_speak_item(lists,
645 action == ACTION_STD_NEXTREPEAT
646 || next_item_modifier >1);
647 yield(); 645 yield();
648 *actionptr = ACTION_STD_NEXT; 646 *actionptr = ACTION_STD_NEXT;
649 return true; 647 return true;
@@ -691,7 +689,6 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
691 SCREEN_MAIN; 689 SCREEN_MAIN;
692 gui_synclist_select_previous_page(lists, screen); 690 gui_synclist_select_previous_page(lists, screen);
693 gui_synclist_draw(lists); 691 gui_synclist_draw(lists);
694 _gui_synclist_speak_item(lists, false);
695 yield(); 692 yield();
696 *actionptr = ACTION_STD_NEXT; 693 *actionptr = ACTION_STD_NEXT;
697 } 694 }
@@ -707,7 +704,6 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
707 SCREEN_MAIN; 704 SCREEN_MAIN;
708 gui_synclist_select_next_page(lists, screen); 705 gui_synclist_select_next_page(lists, screen);
709 gui_synclist_draw(lists); 706 gui_synclist_draw(lists);
710 _gui_synclist_speak_item(lists, false);
711 yield(); 707 yield();
712 *actionptr = ACTION_STD_PREV; 708 *actionptr = ACTION_STD_PREV;
713 } 709 }
@@ -716,7 +712,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
716 if(lists->scheduled_talk_tick 712 if(lists->scheduled_talk_tick
717 && TIME_AFTER(current_tick, lists->scheduled_talk_tick)) 713 && TIME_AFTER(current_tick, lists->scheduled_talk_tick))
718 /* scheduled postponed item announcement is due */ 714 /* scheduled postponed item announcement is due */
719 _gui_synclist_speak_item(lists, false); 715 _gui_synclist_speak_item(lists);
720 return false; 716 return false;
721} 717}
722 718