Accept FS#6159 'Add voice to roughly 100 splash screens and yes-no menus' by Stephane Doyon with some minor tweaks by me. Rerun 'configure' and do a 'make clean' before rebuilding your voice files.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14213 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Nils Wallménius 2007-08-06 13:08:36 +00:00
parent d755c283ca
commit 5b76936a44
24 changed files with 411 additions and 171 deletions

View file

@ -186,10 +186,10 @@ bool bookmark_autobookmark(void)
return write_bookmark(false); return write_bookmark(false);
} }
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
unsigned char *lines[]={str(LANG_AUTO_BOOKMARK_QUERY)}; unsigned char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY)};
struct text_message message={(char **)lines, 1}; struct text_message message={(char **)lines, 1};
#else #else
unsigned char *lines[]={str(LANG_AUTO_BOOKMARK_QUERY), unsigned char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY),
str(LANG_CONFIRM_WITH_BUTTON)}; str(LANG_CONFIRM_WITH_BUTTON)};
struct text_message message={(char **)lines, 2}; struct text_message message={(char **)lines, 2};
#endif #endif
@ -244,8 +244,8 @@ static bool write_bookmark(bool create_bookmark_file)
} }
} }
gui_syncsplash(HZ, str(success ? LANG_BOOKMARK_CREATE_SUCCESS gui_syncsplash(HZ, success ? ID2P(LANG_BOOKMARK_CREATE_SUCCESS)
: LANG_BOOKMARK_CREATE_FAILURE)); : ID2P(LANG_BOOKMARK_CREATE_FAILURE));
return true; return true;
} }
@ -634,7 +634,7 @@ static char* select_bookmark(const char* bookmark_file_name, bool show_dont_resu
if (bookmarks->total_count < 1) if (bookmarks->total_count < 1)
{ {
/* No more bookmarks, delete file and exit */ /* No more bookmarks, delete file and exit */
gui_syncsplash(HZ, str(LANG_BOOKMARK_LOAD_EMPTY)); gui_syncsplash(HZ, ID2P(LANG_BOOKMARK_LOAD_EMPTY));
remove(bookmark_file_name); remove(bookmark_file_name);
return NULL; return NULL;
} }

View file

@ -342,21 +342,21 @@ int ft_enter(struct tree_context* c)
switch ( file->attr & FILE_ATTR_MASK ) { switch ( file->attr & FILE_ATTR_MASK ) {
case FILE_ATTR_M3U: case FILE_ATTR_M3U:
if (global_settings.party_mode) { if (global_settings.party_mode) {
gui_syncsplash(HZ, str(LANG_PARTY_MODE)); gui_syncsplash(HZ, ID2P(LANG_PARTY_MODE));
break; break;
} }
if (bookmark_autoload(buf)) if (bookmark_autoload(buf))
break; break;
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
/* about to create a new current playlist... /* about to create a new current playlist...
allow user to cancel the operation */ allow user to cancel the operation */
if (global_settings.warnon_erase_dynplaylist && if (global_settings.warnon_erase_dynplaylist &&
playlist_modified(NULL)) playlist_modified(NULL))
{ {
char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)};
struct text_message message={lines, 1}; struct text_message message={lines, 1};
if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES)
@ -377,7 +377,7 @@ int ft_enter(struct tree_context* c)
if (bookmark_autoload(c->currdir)) if (bookmark_autoload(c->currdir))
break; break;
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
/* about to create a new current playlist... /* about to create a new current playlist...
allow user to cancel the operation */ allow user to cancel the operation */
@ -385,7 +385,7 @@ int ft_enter(struct tree_context* c)
!global_settings.party_mode && !global_settings.party_mode &&
playlist_modified(NULL)) playlist_modified(NULL))
{ {
char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)};
struct text_message message={lines, 1}; struct text_message message={lines, 1};
if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES)
@ -396,7 +396,7 @@ int ft_enter(struct tree_context* c)
{ {
playlist_insert_track(NULL, buf, playlist_insert_track(NULL, buf,
PLAYLIST_INSERT_LAST, true, true); PLAYLIST_INSERT_LAST, true, true);
gui_syncsplash(HZ, str(LANG_QUEUE_LAST)); gui_syncsplash(HZ, ID2P(LANG_QUEUE_LAST));
} }
else if (playlist_create(c->currdir, NULL) != -1) else if (playlist_create(c->currdir, NULL) != -1)
{ {
@ -421,7 +421,7 @@ int ft_enter(struct tree_context* c)
/* fmr preset file */ /* fmr preset file */
case FILE_ATTR_FMR: case FILE_ATTR_FMR:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
/* Preset inside the default folder. */ /* Preset inside the default folder. */
if(!strncasecmp(FMPRESET_PATH, buf, strlen(FMPRESET_PATH))) if(!strncasecmp(FMPRESET_PATH, buf, strlen(FMPRESET_PATH)))
@ -448,7 +448,7 @@ int ft_enter(struct tree_context* c)
/* wps config file */ /* wps config file */
case FILE_ATTR_WPS: case FILE_ATTR_WPS:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
unload_wps_backdrop(); unload_wps_backdrop();
#endif #endif
@ -460,7 +460,7 @@ int ft_enter(struct tree_context* c)
#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
/* remote-wps config file */ /* remote-wps config file */
case FILE_ATTR_RWPS: case FILE_ATTR_RWPS:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
unload_remote_wps_backdrop(); unload_remote_wps_backdrop();
#endif #endif
@ -471,39 +471,39 @@ int ft_enter(struct tree_context* c)
#endif #endif
case FILE_ATTR_CFG: case FILE_ATTR_CFG:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if (!settings_load_config(buf,true)) if (!settings_load_config(buf,true))
break; break;
gui_syncsplash(HZ, str(LANG_SETTINGS_LOADED)); gui_syncsplash(HZ, ID2P(LANG_SETTINGS_LOADED));
break; break;
case FILE_ATTR_BMARK: case FILE_ATTR_BMARK:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
bookmark_load(buf, false); bookmark_load(buf, false);
reload_dir = true; reload_dir = true;
break; break;
case FILE_ATTR_LNG: case FILE_ATTR_LNG:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if(!lang_load(buf)) { if(!lang_load(buf)) {
set_file(buf, (char *)global_settings.lang_file, set_file(buf, (char *)global_settings.lang_file,
MAX_FILENAME); MAX_FILENAME);
talk_init(); /* use voice of same language */ talk_init(); /* use voice of same language */
gui_syncsplash(HZ, str(LANG_LANGUAGE_LOADED)); gui_syncsplash(HZ, ID2P(LANG_LANGUAGE_LOADED));
} }
break; break;
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
case FILE_ATTR_FONT: case FILE_ATTR_FONT:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
font_load(buf); font_load(buf);
set_file(buf, (char *)global_settings.font_file, MAX_FILENAME); set_file(buf, (char *)global_settings.font_file, MAX_FILENAME);
break; break;
case FILE_ATTR_KBD: case FILE_ATTR_KBD:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if (!load_kbd(buf)) if (!load_kbd(buf))
gui_syncsplash(HZ, str(LANG_KEYBOARD_LOADED)); gui_syncsplash(HZ, ID2P(LANG_KEYBOARD_LOADED));
set_file(buf, (char *)global_settings.kbd_file, MAX_FILENAME); set_file(buf, (char *)global_settings.kbd_file, MAX_FILENAME);
break; break;
#endif #endif
@ -511,7 +511,7 @@ int ft_enter(struct tree_context* c)
#ifndef SIMULATOR #ifndef SIMULATOR
/* firmware file */ /* firmware file */
case FILE_ATTR_MOD: case FILE_ATTR_MOD:
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
rolo_load(buf); rolo_load(buf);
break; break;
#endif #endif
@ -519,11 +519,11 @@ int ft_enter(struct tree_context* c)
/* plugin file */ /* plugin file */
case FILE_ATTR_ROCK: case FILE_ATTR_ROCK:
if (global_settings.party_mode) { if (global_settings.party_mode) {
gui_syncsplash(HZ, str(LANG_PARTY_MODE)); gui_syncsplash(HZ, ID2P(LANG_PARTY_MODE));
break; break;
} }
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if (plugin_load(buf,NULL) == PLUGIN_USB_CONNECTED) if (plugin_load(buf,NULL) == PLUGIN_USB_CONNECTED)
{ {
@ -545,7 +545,7 @@ int ft_enter(struct tree_context* c)
char* plugin; char* plugin;
if (global_settings.party_mode) { if (global_settings.party_mode) {
gui_syncsplash(HZ, str(LANG_PARTY_MODE)); gui_syncsplash(HZ, ID2P(LANG_PARTY_MODE));
break; break;
} }

View file

@ -300,7 +300,7 @@ static void read_config(char* config_file)
{ {
if (filetype_count >= MAX_FILETYPES) if (filetype_count >= MAX_FILETYPES)
{ {
gui_syncsplash(HZ, str(LANG_FILETYPES_FULL)); gui_syncsplash(HZ, ID2P(LANG_FILETYPES_FULL));
break; break;
} }
rm_whitespaces(line); rm_whitespaces(line);

View file

@ -294,7 +294,7 @@ bool gui_wps_display(void)
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
gui_syncstatusbar_draw(&statusbars, true); gui_syncstatusbar_draw(&statusbars, true);
#endif #endif
gui_syncsplash(HZ, str(LANG_END_PLAYLIST)); gui_syncsplash(HZ, ID2P(LANG_END_PLAYLIST));
return true; return true;
} }
else else

View file

@ -22,6 +22,9 @@
#include "stdio.h" #include "stdio.h"
#include "kernel.h" #include "kernel.h"
#include "screen_access.h" #include "screen_access.h"
#include "lang.h"
#include "settings.h"
#include "talk.h"
#ifndef MAX #ifndef MAX
#define MAX(a, b) (((a)>(b))?(a):(b)) #define MAX(a, b) (((a)>(b))?(a):(b))
@ -197,6 +200,15 @@ void gui_syncsplash(int ticks, const unsigned char *fmt, ...)
{ {
va_list ap; va_list ap;
int i; int i;
long id;
/* fmt may be a so called virtual pointer. See settings.h. */
if((id = P2ID(fmt)) >= 0)
/* If fmt specifies a voicefont ID, and voice menus are
enabled, then speak it. */
cond_talk_ids_fq(id);
/* If fmt is a lang ID then get the corresponding string (which
still might contain % place holders). */
fmt = P2STR(fmt);
va_start( ap, fmt ); va_start( ap, fmt );
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
splash(&(screens[i]), fmt, ap); splash(&(screens[i]), fmt, ap);

View file

@ -23,6 +23,7 @@
#include "misc.h" #include "misc.h"
#include "lang.h" #include "lang.h"
#include "action.h" #include "action.h"
#include "talk.h"
/* /*
* Initializes the yesno asker * Initializes the yesno asker
@ -97,7 +98,28 @@ static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result)
gui_textarea_put_message(yn->display, message, 0); gui_textarea_put_message(yn->display, message, 0);
return(true); return(true);
} }
#include "debug.h" #include "debug.h"
/* Processes a text_message whose lines may be virtual pointers
representing language / voicefont IDs (see settings.h). Copies out
the IDs to the ids array, which is of length maxlen, and replaces
the pointers in the text_message with the actual language strings.
The ids array is terminated with the TALK_FINAL_ID sentinel
element. */
static void extract_talk_ids(struct text_message *m, long *ids, int maxlen)
{
int line, i=0;
if(m)
for(line=0; line<m->nb_lines; line++) {
long id = P2ID((unsigned char *)m->message_lines[line]);
if(id>=0 && i<maxlen-1)
ids[i++] = id;
m->message_lines[line] = (char *)P2STR((unsigned char *)m->message_lines[line]);
}
ids[i] = TALK_FINAL_ID;
}
enum yesno_res gui_syncyesno_run(struct text_message * main_message, enum yesno_res gui_syncyesno_run(struct text_message * main_message,
struct text_message * yes_message, struct text_message * yes_message,
struct text_message * no_message) struct text_message * no_message)
@ -107,6 +129,13 @@ enum yesno_res gui_syncyesno_run(struct text_message * main_message,
int result=-1; int result=-1;
bool result_displayed; bool result_displayed;
struct gui_yesno yn[NB_SCREENS]; struct gui_yesno yn[NB_SCREENS];
long voice_ids[5];
long talked_tick = 0;
/* The text messages may contain virtual pointers to IDs (see
settings.h) instead of plain strings. Copy the IDs out so we
can speak them, and unwrap the actual language strings. */
extract_talk_ids(main_message, voice_ids,
sizeof(voice_ids)/sizeof(voice_ids[0]));
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
{ {
gui_yesno_init(&(yn[i]), main_message, yes_message, no_message); gui_yesno_init(&(yn[i]), main_message, yes_message, no_message);
@ -115,7 +144,14 @@ enum yesno_res gui_syncyesno_run(struct text_message * main_message,
} }
while (result==-1) while (result==-1)
{ {
button = get_action(CONTEXT_YESNOSCREEN,TIMEOUT_BLOCK); /* Repeat the question every 5secs (more or less) */
if (talk_menus_enabled()
&& (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5)))
{
talked_tick = current_tick;
talk_idarray(voice_ids, false);
}
button = get_action(CONTEXT_YESNOSCREEN, HZ*5);
switch (button) switch (button)
{ {
case ACTION_YESNO_ACCEPT: case ACTION_YESNO_ACCEPT:
@ -133,6 +169,13 @@ enum yesno_res gui_syncyesno_run(struct text_message * main_message,
} }
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
result_displayed=gui_yesno_draw_result(&(yn[i]), result); result_displayed=gui_yesno_draw_result(&(yn[i]), result);
extract_talk_ids((result == YESNO_YES) ? yes_message : no_message,
voice_ids, sizeof(voice_ids)/sizeof(voice_ids[0]));
if (talk_menus_enabled())
{
talk_idarray(voice_ids, false);
talk_force_enqueue_next();
}
if(result_displayed) if(result_displayed)
sleep(HZ); sleep(HZ);
return(result); return(result);

View file

@ -197,7 +197,7 @@
*: "Loading..." *: "Loading..."
</dest> </dest>
<voice> <voice>
*: "" *: "Loading"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -225,7 +225,7 @@
*: "Scanning disk..." *: "Scanning disk..."
</dest> </dest>
<voice> <voice>
*: "" *: "Scanning disk"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -239,7 +239,7 @@
*: "Shutting down..." *: "Shutting down..."
</dest> </dest>
<voice> <voice>
*: "" *: "Shutting down"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -267,7 +267,7 @@
*: "Cancelled" *: "Cancelled"
</dest> </dest>
<voice> <voice>
*: "" *: "Cancelled"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -281,7 +281,7 @@
*: "Failed" *: "Failed"
</dest> </dest>
<voice> <voice>
*: "" *: "Failed"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -309,7 +309,7 @@
*: "Are You Sure?" *: "Are You Sure?"
</dest> </dest>
<voice> <voice>
*: "" *: "Are You Sure?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -632,7 +632,7 @@
*: "Create a Bookmark?" *: "Create a Bookmark?"
</dest> </dest>
<voice> <voice>
*: "" *: "Create a Bookmark?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -646,7 +646,7 @@
*: "Bookmark Created" *: "Bookmark Created"
</dest> </dest>
<voice> <voice>
*: "" *: "Bookmark Created"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -660,7 +660,7 @@
*: "Bookmark Failed!" *: "Bookmark Failed!"
</dest> </dest>
<voice> <voice>
*: "" *: "Bookmark Failed!"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -674,7 +674,7 @@
*: "Bookmark Empty" *: "Bookmark Empty"
</dest> </dest>
<voice> <voice>
*: "" *: "Bookmark Empty"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -2430,7 +2430,11 @@
h10,h10_5gb,e200: "Building database... %d found (PREV to return)" h10,h10_5gb,e200: "Building database... %d found (PREV to return)"
</dest> </dest>
<voice> <voice>
*: "" *: "entries found for database"
h100,h120,h300: "entries found for database"
ipod*: "entries found for database"
x5,m5: "entries found for database"
h10,h10_5gb,e200: "entries found for database"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -2545,7 +2549,7 @@
*: "Updating in background" *: "Updating in background"
</dest> </dest>
<voice> <voice>
*: "" *: "Updating in background"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -2559,7 +2563,7 @@
*: "Committing database" *: "Committing database"
</dest> </dest>
<voice> <voice>
*: "" *: "Committing database"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -4893,7 +4897,7 @@
*: "New Language" *: "New Language"
</dest> </dest>
<voice> <voice>
*: "" *: "New Language"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5061,7 +5065,7 @@
*: "Settings Loaded" *: "Settings Loaded"
</dest> </dest>
<voice> <voice>
*: "" *: "Settings Loaded"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5089,7 +5093,7 @@
*: "Cleared" *: "Cleared"
</dest> </dest>
<voice> <voice>
*: "" *: "Settings Cleared"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5117,7 +5121,7 @@
*: "Settings Saved" *: "Settings Saved"
</dest> </dest>
<voice> <voice>
*: "" *: "Settings Saved"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5213,7 +5217,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "No presets"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5281,7 +5285,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "Preset Save Failed"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5298,7 +5302,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "The Preset List is Full"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5468,7 +5472,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "Clear Current Presets?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5604,7 +5608,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "No settings found. Autoscan?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -5621,7 +5625,7 @@
</dest> </dest>
<voice> <voice>
*: none *: none
radio: "" radio: "Save Changes?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -6766,7 +6770,7 @@
*: "Saved %d tracks (%s)" *: "Saved %d tracks (%s)"
</dest> </dest>
<voice> <voice>
*: "" *: "tracks saved"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -6808,7 +6812,7 @@
*: "Recursively?" *: "Recursively?"
</dest> </dest>
<voice> <voice>
*: "" *: "Recursively?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -6836,7 +6840,7 @@
*: "Erase dynamic playlist?" *: "Erase dynamic playlist?"
</dest> </dest>
<voice> <voice>
*: "" *: "Erase dynamic playlist?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -7221,7 +7225,7 @@
*: "Inserted %d tracks (%s)" *: "Inserted %d tracks (%s)"
</dest> </dest>
<voice> <voice>
*: "" *: "tracks inserted"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -7235,7 +7239,7 @@
*: "Queued %d tracks (%s)" *: "Queued %d tracks (%s)"
</dest> </dest>
<voice> <voice>
*: "" *: "tracks queued"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -7781,7 +7785,7 @@
*: "File/directory exists. Overwrite?" *: "File/directory exists. Overwrite?"
</dest> </dest>
<voice> <voice>
*: "" *: "File or directory exists. Overwrite?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -7823,7 +7827,7 @@
*: "Delete?" *: "Delete?"
</dest> </dest>
<voice> <voice>
*: "" *: "Really delete?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -7879,7 +7883,7 @@
*: "Deleted" *: "Deleted"
</dest> </dest>
<voice> <voice>
*: "" *: "Deleted"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8085,7 +8089,7 @@
*: "Playlist Buffer Full" *: "Playlist Buffer Full"
</dest> </dest>
<voice> <voice>
*: "" *: "Playlist Buffer Full"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8101,7 +8105,8 @@
player: "End of List" player: "End of List"
</dest> </dest>
<voice> <voice>
*: "" *: "End of Song List"
player: "End of List"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8129,7 +8134,7 @@
*: "Nothing to resume" *: "Nothing to resume"
</dest> </dest>
<voice> <voice>
*: "" *: "Nothing to resume"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8143,7 +8148,7 @@
*: "Error updating playlist control file" *: "Error updating playlist control file"
</dest> </dest>
<voice> <voice>
*: "" *: "Error updating playlist control file"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8157,7 +8162,7 @@
*: "Error accessing playlist file" *: "Error accessing playlist file"
</dest> </dest>
<voice> <voice>
*: "" *: "Error accessing playlist file"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8171,7 +8176,7 @@
*: "Error accessing playlist control file" *: "Error accessing playlist control file"
</dest> </dest>
<voice> <voice>
*: "" *: "Error accessing playlist control file"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8185,7 +8190,7 @@
*: "Error accessing directory" *: "Error accessing directory"
</dest> </dest>
<voice> <voice>
*: "" *: "Error accessing directory"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8199,7 +8204,7 @@
*: "Playlist control file is invalid" *: "Playlist control file is invalid"
</dest> </dest>
<voice> <voice>
*: "" *: "Playlist control file is invalid"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8213,7 +8218,7 @@
*: "Save Failed" *: "Save Failed"
</dest> </dest>
<voice> <voice>
*: "" *: "Save Failed"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8419,7 +8424,7 @@
*: "Boot changed" *: "Boot changed"
</dest> </dest>
<voice> <voice>
*: "" *: "Boot changed"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8433,7 +8438,7 @@
*: "Reboot now?" *: "Reboot now?"
</dest> </dest>
<voice> <voice>
*: "" *: "Reboot now?"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8469,7 +8474,7 @@
*: "No files" *: "No files"
</dest> </dest>
<voice> <voice>
*: "" *: "No files"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8483,7 +8488,7 @@
*: "New Keyboard" *: "New Keyboard"
</dest> </dest>
<voice> <voice>
*: "" *: "New Keyboard"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8567,7 +8572,7 @@
*: "Extension array full" *: "Extension array full"
</dest> </dest>
<voice> <voice>
*: "" *: "Extension array full"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8581,7 +8586,7 @@
*: "Filetype array full" *: "Filetype array full"
</dest> </dest>
<voice> <voice>
*: "" *: "Filetype array full"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8595,7 +8600,7 @@
*: "Dir Buffer is Full!" *: "Dir Buffer is Full!"
</dest> </dest>
<voice> <voice>
*: "" *: "Directory Buffer is Full!"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8623,7 +8628,7 @@
*: "Plugin name too long" *: "Plugin name too long"
</dest> </dest>
<voice> <voice>
*: "" *: "Plugin name too long"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8654,7 +8659,7 @@
*: "Please reboot to enable" *: "Please reboot to enable"
</dest> </dest>
<voice> <voice>
*: "" *: "Please reboot to enable"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8720,7 +8725,7 @@
*: "WARNING! Low Battery!" *: "WARNING! Low Battery!"
</dest> </dest>
<voice> <voice>
*: "" *: "WARNING! Low Battery!"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -8734,7 +8739,7 @@
*: "Battery empty! RECHARGE!" *: "Battery empty! RECHARGE!"
</dest> </dest>
<voice> <voice>
*: "" *: "Battery empty! RECHARGE!"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
@ -10943,4 +10948,18 @@
agc: "AGC maximum gain" agc: "AGC maximum gain"
</voice> </voice>
</phrase> </phrase>
<phrase>
id: VOICE_OF
desc: spoken only, as in 3/8 => 3 of 8
user:
<source>
*: ""
</source>
<dest>
*: ""
</dest>
<voice>
*: "of"
</voice>
</phrase>

View file

@ -217,6 +217,17 @@ static void init_tagcache(void)
if (ret > 0) if (ret > 0)
{ {
static long talked_tick = 0;
if(talk_menus_enabled()
&& (talked_tick == 0
|| TIME_AFTER(current_tick, talked_tick+7*HZ)))
{
talked_tick = current_tick;
talk_id(LANG_TAGCACHE_INIT, false);
talk_number(ret, true);
talk_id(VOICE_OF, true);
talk_number(tagcache_get_max_commit_step(), true);
}
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
gui_syncsplash(0, "%s [%d/%d]", gui_syncsplash(0, "%s [%d/%d]",
str(LANG_TAGCACHE_INIT), ret, str(LANG_TAGCACHE_INIT), ret,
@ -474,7 +485,7 @@ static void init(void)
if (button_hold()) if (button_hold())
#endif #endif
{ {
gui_syncsplash(HZ*2, str(LANG_RESET_DONE_CLEAR)); gui_syncsplash(HZ*2, ID2P(LANG_RESET_DONE_CLEAR));
settings_reset(); settings_reset();
} }
else else

View file

@ -67,12 +67,12 @@ int browse_folder(void *param)
static int reset_settings(void) static int reset_settings(void)
{ {
unsigned char *lines[]={str(LANG_RESET_ASK)}; unsigned char *lines[]={ID2P(LANG_RESET_ASK)};
unsigned char *yes_lines[]={ unsigned char *yes_lines[]={
str(LANG_SETTINGS), str(LANG_SETTINGS),
str(LANG_RESET_DONE_CLEAR) ID2P(LANG_RESET_DONE_CLEAR)
}; };
unsigned char *no_lines[]={yes_lines[0], str(LANG_CANCEL)}; unsigned char *no_lines[]={yes_lines[0], ID2P(LANG_CANCEL)};
struct text_message message={(char **)lines, 1}; struct text_message message={(char **)lines, 1};
struct text_message yes_message={(char **)yes_lines, 2}; struct text_message yes_message={(char **)yes_lines, 2};
struct text_message no_message={(char **)no_lines, 2}; struct text_message no_message={(char **)no_lines, 2};

View file

@ -138,7 +138,7 @@ int audioscrobbler_callback(int action,const struct menu_item_ex *this_item)
{ {
case ACTION_EXIT_MENUITEM: /* on exit */ case ACTION_EXIT_MENUITEM: /* on exit */
if (!scrobbler_is_enabled() && global_settings.audioscrobbler) if (!scrobbler_is_enabled() && global_settings.audioscrobbler)
gui_syncsplash(HZ*2, str(LANG_PLEASE_REBOOT)); gui_syncsplash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
if(scrobbler_is_enabled() && !global_settings.audioscrobbler) if(scrobbler_is_enabled() && !global_settings.audioscrobbler)
scrobbler_shutdown(); scrobbler_shutdown();
@ -156,7 +156,7 @@ int cuesheet_callback(int action,const struct menu_item_ex *this_item)
{ {
case ACTION_EXIT_MENUITEM: /* on exit */ case ACTION_EXIT_MENUITEM: /* on exit */
if (!cuesheet_is_enabled() && global_settings.cuesheet) if (!cuesheet_is_enabled() && global_settings.cuesheet)
gui_syncsplash(HZ*2, str(LANG_PLEASE_REBOOT)); gui_syncsplash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
break; break;
} }
return action; return action;

View file

@ -49,13 +49,13 @@
static void tagcache_rebuild_with_splash(void) static void tagcache_rebuild_with_splash(void)
{ {
tagcache_rebuild(); tagcache_rebuild();
gui_syncsplash(HZ*2, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); gui_syncsplash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
} }
static void tagcache_update_with_splash(void) static void tagcache_update_with_splash(void)
{ {
tagcache_update(); tagcache_update();
gui_syncsplash(HZ*2, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); gui_syncsplash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
} }
#ifdef HAVE_TC_RAMCACHE #ifdef HAVE_TC_RAMCACHE
@ -174,7 +174,7 @@ static int dircache_callback(int action,const struct menu_item_ex *this_item)
{ {
case true: case true:
if (!dircache_is_enabled()) if (!dircache_is_enabled())
gui_syncsplash(HZ*2, str(LANG_PLEASE_REBOOT)); gui_syncsplash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
break; break;
case false: case false:
if (dircache_is_enabled()) if (dircache_is_enabled())

View file

@ -62,6 +62,7 @@
#include "bookmark.h" #include "bookmark.h"
#include "misc.h" #include "misc.h"
#include "playback.h"
#ifdef BOOTFILE #ifdef BOOTFILE
#if !defined(USB_NONE) && !defined(USB_IPODSTYLE) #if !defined(USB_NONE) && !defined(USB_IPODSTYLE)
@ -603,6 +604,7 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter)
call_ata_idle_notifys(true); call_ata_idle_notifys(true);
exit(0); exit(0);
#else #else
long msg_id = -1;
int i; int i;
scrobbler_poweroff(); scrobbler_poweroff();
@ -625,19 +627,23 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter)
if (!tagcache_prepare_shutdown()) if (!tagcache_prepare_shutdown())
{ {
cancel_shutdown(); cancel_shutdown();
gui_syncsplash(HZ, str(LANG_TAGCACHE_BUSY)); gui_syncsplash(HZ, ID2P(LANG_TAGCACHE_BUSY));
return false; return false;
} }
#endif #endif
if (battery_level() > 10) if (battery_level() > 10)
gui_syncsplash(0, str(LANG_SHUTTINGDOWN)); gui_syncsplash(0, str(LANG_SHUTTINGDOWN));
else else
{
msg_id = LANG_WARNING_BATTERY_LOW;
gui_syncsplash(0, "%s %s", gui_syncsplash(0, "%s %s",
str(LANG_WARNING_BATTERY_LOW), str(LANG_WARNING_BATTERY_LOW),
str(LANG_SHUTTINGDOWN)); str(LANG_SHUTTINGDOWN));
} }
}
else else
{ {
msg_id = LANG_WARNING_BATTERY_EMPTY;
gui_syncsplash(0, "%s %s", gui_syncsplash(0, "%s %s",
str(LANG_WARNING_BATTERY_EMPTY), str(LANG_WARNING_BATTERY_EMPTY),
str(LANG_SHUTTINGDOWN)); str(LANG_SHUTTINGDOWN));
@ -675,6 +681,21 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter)
#if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
audio_close_recording(); audio_close_recording();
#endif #endif
if(talk_menus_enabled())
{
bool enqueue = false;
if(msg_id != -1)
{
talk_id(msg_id, enqueue);
enqueue = true;
}
talk_id(LANG_SHUTTINGDOWN, enqueue);
#if CONFIG_CODEC == SWCODEC
voice_wait();
#endif
}
system_flush(); system_flush();
#ifdef HAVE_EEPROM_SETTINGS #ifdef HAVE_EEPROM_SETTINGS
if (firmware_settings.initialized) if (firmware_settings.initialized)
@ -974,8 +995,8 @@ void check_bootfile(bool do_rolo)
if((entry->wrtdate != wrtdate) || if((entry->wrtdate != wrtdate) ||
(entry->wrttime != wrttime)) (entry->wrttime != wrttime))
{ {
char *lines[] = { str(LANG_BOOT_CHANGED), char *lines[] = { ID2P(LANG_BOOT_CHANGED),
str(LANG_REBOOT_NOW) }; ID2P(LANG_REBOOT_NOW) };
struct text_message message={ lines, 2 }; struct text_message message={ lines, 2 };
button_clear_queue(); /* Empty the keyboard buffer */ button_clear_queue(); /* Empty the keyboard buffer */
if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES)

View file

@ -160,12 +160,12 @@ static bool add_to_playlist(int position, bool queue)
{ {
bool new_playlist = !(audio_status() & AUDIO_STATUS_PLAY); bool new_playlist = !(audio_status() & AUDIO_STATUS_PLAY);
char *lines[] = { char *lines[] = {
(char *)str(LANG_RECURSE_DIRECTORY_QUESTION), ID2P(LANG_RECURSE_DIRECTORY_QUESTION),
selected_file selected_file
}; };
struct text_message message={lines, 2}; struct text_message message={lines, 2};
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if (new_playlist) if (new_playlist)
playlist_create(NULL, NULL); playlist_create(NULL, NULL);
@ -502,7 +502,7 @@ static int remove_dir(char* dirname, int len)
#endif #endif
if(ACTION_STD_CANCEL == get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) if(ACTION_STD_CANCEL == get_action(CONTEXT_STD,TIMEOUT_NOBLOCK))
{ {
gui_syncsplash(HZ, str(LANG_CANCEL)); gui_syncsplash(HZ, ID2P(LANG_CANCEL));
result = -1; result = -1;
break; break;
} }
@ -524,11 +524,11 @@ static int remove_dir(char* dirname, int len)
static bool delete_handler(bool is_dir) static bool delete_handler(bool is_dir)
{ {
char *lines[]={ char *lines[]={
(char *)str(LANG_REALLY_DELETE), ID2P(LANG_REALLY_DELETE),
selected_file selected_file
}; };
char *yes_lines[]={ char *yes_lines[]={
(char *)str(LANG_DELETED), ID2P(LANG_DELETED),
selected_file selected_file
}; };
@ -599,6 +599,7 @@ static bool rename_file(void)
lcd_puts(0,0,str(LANG_RENAME)); lcd_puts(0,0,str(LANG_RENAME));
lcd_puts(0,1,str(LANG_FAILED)); lcd_puts(0,1,str(LANG_FAILED));
lcd_update(); lcd_update();
cond_talk_ids_fq(LANG_RENAME, LANG_FAILED);
sleep(HZ*2); sleep(HZ*2);
} }
else else
@ -628,6 +629,7 @@ static bool create_dir(void)
rc = mkdir(dirname); rc = mkdir(dirname);
if (rc < 0) { if (rc < 0) {
cond_talk_ids_fq(LANG_CREATE_DIR, LANG_FAILED);
gui_syncsplash(HZ, (unsigned char *)"%s %s", gui_syncsplash(HZ, (unsigned char *)"%s %s",
str(LANG_CREATE_DIR), str(LANG_FAILED)); str(LANG_CREATE_DIR), str(LANG_FAILED));
} else { } else {
@ -873,7 +875,7 @@ static bool clipboard_paste(void)
bool success; bool success;
int target_fd; int target_fd;
unsigned char *lines[]={str(LANG_REALLY_OVERWRITE)}; unsigned char *lines[]={ID2P(LANG_REALLY_OVERWRITE)};
struct text_message message={(char **)lines, 1}; struct text_message message={(char **)lines, 1};
/* Get the name of the current directory */ /* Get the name of the current directory */
@ -896,11 +898,11 @@ static bool clipboard_paste(void)
} }
if (clipboard_is_copy) { if (clipboard_is_copy) {
gui_syncsplash(0, str(LANG_COPYING)); gui_syncsplash(0, ID2P(LANG_COPYING));
} }
else else
{ {
gui_syncsplash(0, str(LANG_MOVING)); gui_syncsplash(0, ID2P(LANG_MOVING));
} }
/* Now figure out what we're doing */ /* Now figure out what we're doing */
@ -939,6 +941,7 @@ static bool clipboard_paste(void)
/* Force reload of the current directory */ /* Force reload of the current directory */
onplay_result = ONPLAY_RELOAD_DIR; onplay_result = ONPLAY_RELOAD_DIR;
} else { } else {
cond_talk_ids_fq(LANG_PASTE, LANG_FAILED);
gui_syncsplash(HZ, (unsigned char *)"%s %s", gui_syncsplash(HZ, (unsigned char *)"%s %s",
str(LANG_PASTE), str(LANG_FAILED)); str(LANG_PASTE), str(LANG_FAILED));
} }

View file

@ -957,6 +957,24 @@ static void voice_stop(void)
pcmbuf_play_stop(); pcmbuf_play_stop();
#endif #endif
} /* voice_stop */ } /* voice_stop */
/* Is voice still speaking */
/* Unfortunately only reliable when music is not also playing. */
static bool is_voice_speaking(void)
{
return is_voice_queued()
|| voice_is_playing
|| (!playing && pcm_is_playing());
}
/* Wait for voice to finish speaking. */
/* Also only reliable when music is not also playing. */
void voice_wait(void)
{
while (is_voice_speaking())
sleep(HZ/10);
}
#endif /* PLAYBACK_VOICE */ #endif /* PLAYBACK_VOICE */
static void set_filebuf_watermark(int seconds) static void set_filebuf_watermark(int seconds)

View file

@ -63,6 +63,7 @@ void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
bool last_track)); bool last_track));
void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3, void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
bool last_track)); bool last_track));
void voice_wait(void);
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
extern void audio_next_dir(void); extern void audio_next_dir(void);

View file

@ -181,7 +181,8 @@ static int get_previous_directory(char *dir);
static int check_subdir_for_music(char *dir, char *subdir); static int check_subdir_for_music(char *dir, char *subdir);
static int format_track_path(char *dest, char *src, int buf_length, int max, static int format_track_path(char *dest, char *src, int buf_length, int max,
char *dir); char *dir);
static void display_playlist_count(int count, const unsigned char *fmt); static void display_playlist_count(int count, const unsigned char *fmt,
bool final);
static void display_buffer_full(void); static void display_buffer_full(void);
static int flush_cached_control(struct playlist_info* playlist); static int flush_cached_control(struct playlist_info* playlist);
static int update_control(struct playlist_info* playlist, static int update_control(struct playlist_info* playlist,
@ -288,6 +289,7 @@ static void create_control(struct playlist_info* playlist)
{ {
if (check_rockboxdir()) if (check_rockboxdir())
{ {
cond_talk_ids_fq(LANG_PLAYLIST_CONTROL_ACCESS_ERROR);
gui_syncsplash(HZ*2, (unsigned char *)"%s (%d)", gui_syncsplash(HZ*2, (unsigned char *)"%s (%d)",
str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR), str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR),
playlist->control_fd); playlist->control_fd);
@ -483,8 +485,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
else else
lcd_setmargins(0, 0); lcd_setmargins(0, 0);
#endif #endif
gui_syncsplash(0, ID2P(LANG_WAIT));
gui_syncsplash(0, str(LANG_WAIT));
if (!buffer) if (!buffer)
{ {
@ -770,11 +771,11 @@ static int directory_search_callback(char* filename, void* context)
unsigned char* count_str; unsigned char* count_str;
if (c->queue) if (c->queue)
count_str = str(LANG_PLAYLIST_QUEUE_COUNT); count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
else else
count_str = str(LANG_PLAYLIST_INSERT_COUNT); count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT);
display_playlist_count(c->count, count_str); display_playlist_count(c->count, count_str, false);
if ((c->count) == PLAYLIST_DISPLAY_COUNT && if ((c->count) == PLAYLIST_DISPLAY_COUNT &&
(audio_status() & AUDIO_STATUS_PLAY) && (audio_status() & AUDIO_STATUS_PLAY) &&
@ -1350,9 +1351,9 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
if (max < 0) if (max < 0)
{ {
if (control_file) if (control_file)
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
else else
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR));
return max; return max;
} }
@ -1445,7 +1446,7 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
if (ft_load(tc, (dir[0]=='\0')?"/":dir) < 0) if (ft_load(tc, (dir[0]=='\0')?"/":dir) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR));
exit = true; exit = true;
result = -1; result = -1;
break; break;
@ -1530,7 +1531,7 @@ static int check_subdir_for_music(char *dir, char *subdir)
if (ft_load(tc, dir) < 0) if (ft_load(tc, dir) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR));
return -2; return -2;
} }
@ -1584,7 +1585,7 @@ static int check_subdir_for_music(char *dir, char *subdir)
/* we now need to reload our current directory */ /* we now need to reload our current directory */
if(ft_load(tc, dir) < 0) if(ft_load(tc, dir) < 0)
gui_syncsplash(HZ*2, gui_syncsplash(HZ*2,
str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR));
} }
return result; return result;
@ -1657,8 +1658,23 @@ static int format_track_path(char *dest, char *src, int buf_length, int max,
* Display splash message showing progress of playlist/directory insertion or * Display splash message showing progress of playlist/directory insertion or
* save. * save.
*/ */
static void display_playlist_count(int count, const unsigned char *fmt) static void display_playlist_count(int count, const unsigned char *fmt,
bool final)
{ {
static long talked_tick = 0;
long id = P2ID(fmt);
if(talk_menus_enabled() && id>=0)
{
if(final || (count && (talked_tick == 0
|| TIME_AFTER(current_tick, talked_tick+5*HZ))))
{
talked_tick = current_tick;
talk_number(count, false);
talk_id(id, true);
}
}
fmt = P2STR(fmt);
lcd_clear_display(); lcd_clear_display();
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
@ -1676,7 +1692,7 @@ static void display_playlist_count(int count, const unsigned char *fmt)
*/ */
static void display_buffer_full(void) static void display_buffer_full(void)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_BUFFER_FULL)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_BUFFER_FULL));
} }
/* /*
@ -1755,7 +1771,7 @@ static int flush_cached_control(struct playlist_info* playlist)
else else
{ {
result = -1; result = -1;
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_UPDATE_ERROR));
} }
return result; return result;
@ -1942,11 +1958,11 @@ int playlist_resume(void)
empty_playlist(playlist, true); empty_playlist(playlist, true);
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
playlist->control_fd = open(playlist->control_filename, O_RDWR); playlist->control_fd = open(playlist->control_filename, O_RDWR);
if (playlist->control_fd < 0) if (playlist->control_fd < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
playlist->control_created = true; playlist->control_created = true;
@ -1954,7 +1970,7 @@ int playlist_resume(void)
control_file_size = filesize(playlist->control_fd); control_file_size = filesize(playlist->control_fd);
if (control_file_size <= 0) if (control_file_size <= 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -1963,7 +1979,7 @@ int playlist_resume(void)
PLAYLIST_COMMAND_SIZE<buflen?PLAYLIST_COMMAND_SIZE:buflen); PLAYLIST_COMMAND_SIZE<buflen?PLAYLIST_COMMAND_SIZE:buflen);
if(nread <= 0) if(nread <= 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -2258,7 +2274,7 @@ int playlist_resume(void)
if (result < 0) if (result < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_INVALID)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID));
return result; return result;
} }
@ -2267,7 +2283,7 @@ int playlist_resume(void)
if ((total_read + count) >= control_file_size) if ((total_read + count) >= control_file_size)
{ {
/* no newline at end of control file */ /* no newline at end of control file */
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_INVALID)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID));
return -1; return -1;
} }
@ -2361,6 +2377,7 @@ int playlist_shuffle(int random_seed, int start_index)
start_current = true; start_current = true;
} }
cond_talk_ids(LANG_WAIT);
gui_syncsplash(0, str(LANG_PLAYLIST_SHUFFLE)); gui_syncsplash(0, str(LANG_PLAYLIST_SHUFFLE));
randomise_playlist(playlist, random_seed, start_current, true); randomise_playlist(playlist, random_seed, start_current, true);
@ -2853,7 +2870,7 @@ int playlist_insert_track(struct playlist_info* playlist, const char *filename,
if (check_control(playlist) < 0) if (check_control(playlist) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -2884,7 +2901,7 @@ int playlist_insert_directory(struct playlist_info* playlist,
if (check_control(playlist) < 0) if (check_control(playlist) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -2897,11 +2914,11 @@ int playlist_insert_directory(struct playlist_info* playlist,
} }
if (queue) if (queue)
count_str = str(LANG_PLAYLIST_QUEUE_COUNT); count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
else else
count_str = str(LANG_PLAYLIST_INSERT_COUNT); count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT);
display_playlist_count(0, count_str); display_playlist_count(0, count_str, false);
context.playlist = playlist; context.playlist = playlist;
context.position = position; context.position = position;
@ -2917,7 +2934,7 @@ int playlist_insert_directory(struct playlist_info* playlist,
cpu_boost(false); cpu_boost(false);
display_playlist_count(context.count, count_str); display_playlist_count(context.count, count_str, true);
if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
audio_flush_and_reload_tracks(); audio_flush_and_reload_tracks();
@ -2950,14 +2967,14 @@ int playlist_insert_playlist(struct playlist_info* playlist, char *filename,
if (check_control(playlist) < 0) if (check_control(playlist) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
fd = open(filename, O_RDONLY); fd = open(filename, O_RDONLY);
if (fd < 0) if (fd < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR));
return -1; return -1;
} }
@ -2971,11 +2988,11 @@ int playlist_insert_playlist(struct playlist_info* playlist, char *filename,
dir = "/"; dir = "/";
if (queue) if (queue)
count_str = str(LANG_PLAYLIST_QUEUE_COUNT); count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
else else
count_str = str(LANG_PLAYLIST_INSERT_COUNT); count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT);
display_playlist_count(count, count_str); display_playlist_count(count, count_str, false);
if (position == PLAYLIST_REPLACE) if (position == PLAYLIST_REPLACE)
{ {
@ -3023,7 +3040,7 @@ int playlist_insert_playlist(struct playlist_info* playlist, char *filename,
if ((count%PLAYLIST_DISPLAY_COUNT) == 0) if ((count%PLAYLIST_DISPLAY_COUNT) == 0)
{ {
display_playlist_count(count, count_str); display_playlist_count(count, count_str, false);
if (count == PLAYLIST_DISPLAY_COUNT && if (count == PLAYLIST_DISPLAY_COUNT &&
(audio_status() & AUDIO_STATUS_PLAY) && (audio_status() & AUDIO_STATUS_PLAY) &&
@ -3045,7 +3062,7 @@ int playlist_insert_playlist(struct playlist_info* playlist, char *filename,
cpu_boost(false); cpu_boost(false);
display_playlist_count(count, count_str); display_playlist_count(count, count_str, true);
if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
audio_flush_and_reload_tracks(); audio_flush_and_reload_tracks();
@ -3070,7 +3087,7 @@ int playlist_delete(struct playlist_info* playlist, int index)
if (check_control(playlist) < 0) if (check_control(playlist) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -3105,7 +3122,7 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
if (check_control(playlist) < 0) if (check_control(playlist) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
return -1; return -1;
} }
@ -3368,7 +3385,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
if (playlist->buffer_size < (int)(playlist->amount * sizeof(int))) if (playlist->buffer_size < (int)(playlist->amount * sizeof(int)))
{ {
/* not enough buffer space to store updated indices */ /* not enough buffer space to store updated indices */
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR));
return -1; return -1;
} }
@ -3384,11 +3401,11 @@ int playlist_save(struct playlist_info* playlist, char *filename)
fd = open(path, O_CREAT|O_WRONLY|O_TRUNC); fd = open(path, O_CREAT|O_WRONLY|O_TRUNC);
if (fd < 0) if (fd < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR));
return -1; return -1;
} }
display_playlist_count(count, str(LANG_PLAYLIST_SAVE_COUNT)); display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT), false);
cpu_boost(true); cpu_boost(true);
@ -3425,7 +3442,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
if (fdprintf(fd, "%s\n", tmp_buf) < 0) if (fdprintf(fd, "%s\n", tmp_buf) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR));
result = -1; result = -1;
break; break;
} }
@ -3433,7 +3450,8 @@ int playlist_save(struct playlist_info* playlist, char *filename)
count++; count++;
if ((count % PLAYLIST_DISPLAY_COUNT) == 0) if ((count % PLAYLIST_DISPLAY_COUNT) == 0)
display_playlist_count(count, str(LANG_PLAYLIST_SAVE_COUNT)); display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT),
false);
yield(); yield();
} }
@ -3441,7 +3459,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
index = (index+1)%playlist->amount; index = (index+1)%playlist->amount;
} }
display_playlist_count(count, str(LANG_PLAYLIST_SAVE_COUNT)); display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT), true);
close(fd); close(fd);
@ -3512,7 +3530,7 @@ int playlist_directory_tracksearch(const char* dirname, bool recurse,
if (ft_load(tc, dirname) < 0) if (ft_load(tc, dirname) < 0)
{ {
gui_syncsplash(HZ*2, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); gui_syncsplash(HZ*2, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR));
*(tc->dirfilter) = old_dirfilter; *(tc->dirfilter) = old_dirfilter;
return -1; return -1;
} }

View file

@ -537,7 +537,7 @@ int plugin_load(const char* plugin, void* parameter)
plugin_loaded = false; plugin_loaded = false;
} }
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
strcpy(current_plugin,p); strcpy(current_plugin,p);
#ifdef SIMULATOR #ifdef SIMULATOR

View file

@ -487,7 +487,7 @@ int radio_screen(void)
radio_start(); radio_start();
#endif #endif
if(num_presets < 1 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN))) if(num_presets < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
scan_presets(); scan_presets();
curr_preset = find_preset(curr_freq); curr_preset = find_preset(curr_freq);
@ -551,7 +551,7 @@ int radio_screen(void)
done = true; done = true;
if(presets_changed) if(presets_changed)
{ {
if(yesno_pop(str(LANG_FM_SAVE_CHANGES))) if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
{ {
if(filepreset[0] == '\0') if(filepreset[0] == '\0')
save_preset_list(); save_preset_list();
@ -606,7 +606,7 @@ int radio_screen(void)
ret_val = GO_TO_ROOT; ret_val = GO_TO_ROOT;
if(presets_changed) if(presets_changed)
{ {
if(yesno_pop(str(LANG_FM_SAVE_CHANGES))) if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
{ {
if(filepreset[0] == '\0') if(filepreset[0] == '\0')
save_preset_list(); save_preset_list();
@ -690,7 +690,7 @@ int radio_screen(void)
case ACTION_FM_PRESET: case ACTION_FM_PRESET:
if(num_presets < 1) if(num_presets < 1)
{ {
gui_syncsplash(HZ, str(LANG_FM_NO_PRESETS)); gui_syncsplash(HZ, ID2P(LANG_FM_NO_PRESETS));
update_screen = true; update_screen = true;
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
{ {
@ -996,7 +996,7 @@ static void radio_save_presets(void)
} }
else else
{ {
gui_syncsplash(HZ, str(LANG_FM_PRESET_SAVE_FAILED)); gui_syncsplash(HZ, ID2P(LANG_FM_PRESET_SAVE_FAILED));
} }
} }
@ -1082,7 +1082,7 @@ static int radio_add_preset(void)
} }
else else
{ {
gui_syncsplash(HZ, str(LANG_FM_NO_FREE_PRESETS)); gui_syncsplash(HZ, ID2P(LANG_FM_NO_FREE_PRESETS));
} }
return true; return true;
} }
@ -1170,7 +1170,7 @@ static int save_preset_list(void)
if((!p1) || (len > MAX_FILENAME) || (len == 0)) if((!p1) || (len > MAX_FILENAME) || (len == 0))
{ {
/* no slash, too long or too short */ /* no slash, too long or too short */
gui_syncsplash(HZ, str(LANG_INVALID_FILENAME)); gui_syncsplash(HZ, ID2P(LANG_INVALID_FILENAME));
} }
else else
{ {
@ -1190,7 +1190,7 @@ static int save_preset_list(void)
} }
} }
else else
gui_syncsplash(HZ, str(LANG_FM_NO_PRESETS)); gui_syncsplash(HZ, ID2P(LANG_FM_NO_PRESETS));
return true; return true;
} }
@ -1339,7 +1339,7 @@ static int scan_presets(void)
bool do_scan = true; bool do_scan = true;
if(num_presets > 0) /* Do that to avoid 2 questions. */ if(num_presets > 0) /* Do that to avoid 2 questions. */
do_scan = yesno_pop(str(LANG_FM_CLEAR_PRESETS)); do_scan = yesno_pop(ID2P(LANG_FM_CLEAR_PRESETS));
if(do_scan) if(do_scan)
{ {

View file

@ -129,7 +129,7 @@ static int browser(void* param)
/* Maybe just needs to reboot due to delayed commit */ /* Maybe just needs to reboot due to delayed commit */
if (stat->commit_delayed) if (stat->commit_delayed)
{ {
gui_syncsplash(HZ*2, str(LANG_PLEASE_REBOOT)); gui_syncsplash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
break; break;
} }
@ -146,7 +146,7 @@ static int browser(void* param)
{ {
/* Prompt the user */ /* Prompt the user */
reinit_attempted = true; reinit_attempted = true;
char *lines[]={str(LANG_TAGCACHE_BUSY), str(LANG_TAGCACHE_FORCE_UPDATE)}; char *lines[]={ID2P(LANG_TAGCACHE_BUSY), ID2P(LANG_TAGCACHE_FORCE_UPDATE)};
struct text_message message={lines, 2}; struct text_message message={lines, 2};
if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO) if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO)
break; break;
@ -159,6 +159,24 @@ static int browser(void* param)
} }
/* Display building progress */ /* Display building progress */
static long talked_tick = 0;
if(talk_menus_enabled() &&
(talked_tick == 0
|| TIME_AFTER(current_tick, talked_tick+7*HZ)))
{
talked_tick = current_tick;
if (stat->commit_step > 0)
{
talk_id(LANG_TAGCACHE_INIT, false);
talk_number(stat->commit_step, true);
talk_id(VOICE_OF, true);
talk_number(tagcache_get_max_commit_step(), true);
} else if(stat->processed_entries)
{
talk_number(stat->processed_entries, false);
talk_id(LANG_BUILDING_DATABASE, true);
}
}
if (stat->commit_step > 0) if (stat->commit_step > 0)
{ {
gui_syncsplash(0, "%s [%d/%d]", gui_syncsplash(0, "%s [%d/%d]",
@ -236,7 +254,7 @@ static int wpsscrn(void* param)
} }
else else
{ {
gui_syncsplash(HZ*2, str(LANG_NOTHING_TO_RESUME)); gui_syncsplash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME));
} }
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
show_main_backdrop(); show_main_backdrop();

View file

@ -544,6 +544,7 @@ int settings_save( void )
screens[i].update(); screens[i].update();
#endif #endif
} }
cond_talk_ids_fq(LANG_SETTINGS_SAVE_FAILED);
sleep(HZ*2); sleep(HZ*2);
return -1; return -1;
} }
@ -575,15 +576,15 @@ bool settings_save_config(int options)
break; break;
} }
else { else {
gui_syncsplash(HZ, str(LANG_CANCEL)); gui_syncsplash(HZ, ID2P(LANG_CANCEL));
return false; return false;
} }
} }
if (settings_write_config(filename, options)) if (settings_write_config(filename, options))
gui_syncsplash(HZ, str(LANG_SETTINGS_SAVED)); gui_syncsplash(HZ, ID2P(LANG_SETTINGS_SAVED));
else else
gui_syncsplash(HZ, str(LANG_FAILED)); gui_syncsplash(HZ, ID2P(LANG_FAILED));
return true; return true;
} }

View file

@ -690,7 +690,7 @@ bool tagtree_export(void)
gui_syncsplash(0, str(LANG_CREATING)); gui_syncsplash(0, str(LANG_CREATING));
if (!tagcache_create_changelog(&tcs)) if (!tagcache_create_changelog(&tcs))
{ {
gui_syncsplash(HZ*2, str(LANG_FAILED)); gui_syncsplash(HZ*2, ID2P(LANG_FAILED));
} }
return false; return false;
@ -698,10 +698,10 @@ bool tagtree_export(void)
bool tagtree_import(void) bool tagtree_import(void)
{ {
gui_syncsplash(0, str(LANG_WAIT)); gui_syncsplash(0, ID2P(LANG_WAIT));
if (!tagcache_import_changelog()) if (!tagcache_import_changelog())
{ {
gui_syncsplash(HZ*2, str(LANG_FAILED)); gui_syncsplash(HZ*2, ID2P(LANG_FAILED));
} }
return false; return false;
@ -1228,7 +1228,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
if (!sort && (sort_inverse || sort_limit)) if (!sort && (sort_inverse || sort_limit))
{ {
gui_syncsplash(HZ*4, str(LANG_SHOWDIR_BUFFER_FULL), total_count); gui_syncsplash(HZ*4, ID2P(LANG_SHOWDIR_BUFFER_FULL), total_count);
logf("Too small dir buffer"); logf("Too small dir buffer");
return 0; return 0;
} }
@ -1419,7 +1419,7 @@ int tagtree_enter(struct tree_context* c)
!global_settings.party_mode && !global_settings.party_mode &&
playlist_modified(NULL)) playlist_modified(NULL))
{ {
char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)};
struct text_message message={lines, 1}; struct text_message message={lines, 1};
if (gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) if (gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES)
@ -1496,7 +1496,7 @@ static bool insert_all_playlist(struct tree_context *c, int position, bool queue
cpu_boost(true); cpu_boost(true);
if (!tagcache_search(&tcs, tag_filename)) if (!tagcache_search(&tcs, tag_filename))
{ {
gui_syncsplash(HZ, str(LANG_TAGCACHE_BUSY)); gui_syncsplash(HZ, ID2P(LANG_TAGCACHE_BUSY));
cpu_boost(false); cpu_boost(false);
return false; return false;
} }
@ -1599,12 +1599,12 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
} }
if (tc->filesindir <= 0) if (tc->filesindir <= 0)
gui_syncsplash(HZ, str(LANG_END_PLAYLIST)); gui_syncsplash(HZ, ID2P(LANG_END_PLAYLIST));
else else
{ {
logf("insert_all_playlist"); logf("insert_all_playlist");
if (!insert_all_playlist(tc, position, queue)) if (!insert_all_playlist(tc, position, queue))
gui_syncsplash(HZ*2, str(LANG_FAILED)); gui_syncsplash(HZ*2, ID2P(LANG_FAILED));
} }
/* Finally return the dirlevel to its original value. */ /* Finally return the dirlevel to its original value. */

View file

@ -117,6 +117,8 @@ static long size_for_thumbnail; /* leftover buffer size for it */
static struct voicefile* p_voicefile; /* loaded voicefile */ static struct voicefile* p_voicefile; /* loaded voicefile */
static bool has_voicefile; /* a voicefile file is present */ static bool has_voicefile; /* a voicefile file is present */
static struct queue_entry queue[QUEUE_SIZE]; /* queue of scheduled clips */ static struct queue_entry queue[QUEUE_SIZE]; /* queue of scheduled clips */
/* enqueue next utterance even if enqueue is false. */
static bool force_enqueue_next;
static int queue_write; /* write index of queue, by application */ static int queue_write; /* write index of queue, by application */
static int queue_read; /* read index of queue, by ISR context */ static int queue_read; /* read index of queue, by ISR context */
static int sent; /* how many bytes handed over to playback, owned by ISR */ static int sent; /* how many bytes handed over to playback, owned by ISR */
@ -134,7 +136,6 @@ static int talk_menu_disable; /* if non-zero, temporarily disable voice UI (not
static void load_voicefile(void); static void load_voicefile(void);
static void mp3_callback(unsigned char** start, size_t* size); static void mp3_callback(unsigned char** start, size_t* size);
static int shutup(void);
static int queue_clip(unsigned char* buf, long size, bool enqueue); static int queue_clip(unsigned char* buf, long size, bool enqueue);
static int open_voicefile(void); static int open_voicefile(void);
static unsigned char* get_clip(long id, long* p_size); static unsigned char* get_clip(long id, long* p_size);
@ -267,6 +268,13 @@ load_err:
} }
/* Are more voice clips queued and waiting? */
bool is_voice_queued()
{
return !!QUEUE_LEVEL;
}
/* called in ISR context if mp3 data got consumed */ /* called in ISR context if mp3 data got consumed */
static void mp3_callback(unsigned char** start, size_t* size) static void mp3_callback(unsigned char** start, size_t* size)
{ {
@ -321,7 +329,7 @@ re_check:
} }
/* stop the playback and the pending clips */ /* stop the playback and the pending clips */
static int shutup(void) static int do_shutup(void)
{ {
#if CONFIG_CODEC != SWCODEC #if CONFIG_CODEC != SWCODEC
unsigned char* pos; unsigned char* pos;
@ -387,6 +395,13 @@ static int shutup(void)
return 0; return 0;
} }
/* Shutup the voice, except if force_enqueue_next is set. */
static int shutup(void)
{
if (!force_enqueue_next)
return do_shutup();
return 0;
}
/* schedule a clip, at the end or discard the existing queue */ /* schedule a clip, at the end or discard the existing queue */
static int queue_clip(unsigned char* buf, long size, bool enqueue) static int queue_clip(unsigned char* buf, long size, bool enqueue)
@ -395,6 +410,9 @@ static int queue_clip(unsigned char* buf, long size, bool enqueue)
if (!enqueue) if (!enqueue)
shutup(); /* cut off all the pending stuff */ shutup(); /* cut off all the pending stuff */
/* Something is being enqueued, force_enqueue_next override is no
longer in effect. */
force_enqueue_next = false;
if (!size) if (!size)
return 0; /* safety check */ return 0; /* safety check */
@ -617,6 +635,26 @@ int talk_id(long id, bool enqueue)
return 0; return 0;
} }
/* Speaks zero or more IDs (from an array). */
int talk_idarray(long *ids, bool enqueue)
{
int r;
if(!ids)
return 0;
while(*ids != TALK_FINAL_ID)
{
if((r = talk_id(*ids++, enqueue)) <0)
return r;
enqueue = true;
}
return 0;
}
/* Make sure the current utterance is not interrupted by the next one. */
void talk_force_enqueue_next(void)
{
force_enqueue_next = true;
}
/* play a thumbnail from file */ /* play a thumbnail from file */
int talk_file(const char* filename, bool enqueue) int talk_file(const char* filename, bool enqueue)

View file

@ -66,6 +66,9 @@ bool talk_voice_required(void); /* returns true if voice codec required */
int talk_get_bufsize(void); /* get the loaded voice file size */ int talk_get_bufsize(void); /* get the loaded voice file size */
/* talk_buffer_steal - on SWCODEC, for use by buffer functions only */ /* talk_buffer_steal - on SWCODEC, for use by buffer functions only */
int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
//int shutup(void); /* Interrupt voice, as when enqueue is false */
//int do_shutup(void); /* kill voice unconditionally */
bool is_voice_queued(void); /* Are there more voice clips to be spoken? */
int talk_id(long id, bool enqueue); /* play a voice ID from voicefont */ int talk_id(long id, bool enqueue); /* play a voice ID from voicefont */
int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */ int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */
int talk_number(long n, bool enqueue); /* say a number */ int talk_number(long n, bool enqueue); /* say a number */
@ -74,4 +77,37 @@ int talk_spell(const char* spell, bool enqueue); /* spell a string */
bool talk_menus_enabled(void); /* returns true if menus should be voiced */ bool talk_menus_enabled(void); /* returns true if menus should be voiced */
void talk_disable_menus(void); /* disable voice menus (temporarily, not persisted) */ void talk_disable_menus(void); /* disable voice menus (temporarily, not persisted) */
void talk_enable_menus(void); /* re-enable voice menus */ void talk_enable_menus(void); /* re-enable voice menus */
/* Enqueue next utterance even if enqueue parameter is false: don't
interrupt the current utterance. */
void talk_force_enqueue_next(void);
/* speaks one or more IDs (from an array)). */
int talk_idarray(long *idarray, bool enqueue);
/* This (otherwise invalid) ID signals the end of the array. */
#define TALK_FINAL_ID LANG_LAST_INDEX_IN_ARRAY
/* This makes an initializer for the array of IDs and takes care to
put the final sentinel element at the end. */
#define TALK_IDARRAY(ids...) ((long[]){ids,TALK_FINAL_ID})
/* And this handy macro makes it look like a variadic function. */
#define talk_ids(enqueue, ids...) talk_idarray(TALK_IDARRAY(ids), enqueue)
/* This version talks only if talking menus are enabled, and does not
enqueue the initial id. */
#define cond_talk_ids(ids...) do { \
if (talk_menus_enabled()) \
talk_ids(false, ids); \
} while(0)
/* And a version that takes the array parameter... */
#define cond_talk_idarray(idarray) do { \
if (talk_menus_enabled() \
talk_idarray(idarray, false); \
} while(0)
/* Convenience macro to conditionally speak something and not have
it interrupted. */
#define cond_talk_ids_fq(ids...) do { \
if (talk_menus_enabled()) { \
talk_ids(false, ids); \
talk_force_enqueue_next(); \
} \
}while(0)
#endif /* __TALK_H__ */ #endif /* __TALK_H__ */

View file

@ -325,7 +325,7 @@ static int update_dir(void)
(tc.dirfull || (tc.dirfull ||
tc.filesindir == global_settings.max_files_in_dir) ) tc.filesindir == global_settings.max_files_in_dir) )
{ {
gui_syncsplash(HZ, str(LANG_SHOWDIR_BUFFER_FULL)); gui_syncsplash(HZ, ID2P(LANG_SHOWDIR_BUFFER_FULL));
} }
} }
#ifdef HAVE_TAGCACHE #ifdef HAVE_TAGCACHE
@ -556,7 +556,7 @@ static int dirbrowse()
if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0) if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0)
{ {
gui_syncsplash(HZ*2, str(LANG_NO_FILES)); gui_syncsplash(HZ*2, ID2P(LANG_NO_FILES));
return false; /* No files found for rockbox_browser() */ return false; /* No files found for rockbox_browser() */
} }
@ -567,7 +567,7 @@ static int dirbrowse()
tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */ tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */
#ifdef BOOTFILE #ifdef BOOTFILE
if (boot_changed) { if (boot_changed) {
char *lines[]={str(LANG_BOOT_CHANGED), str(LANG_REBOOT_NOW)}; char *lines[]={ID2P(LANG_BOOT_CHANGED), ID2P(LANG_REBOOT_NOW)};
struct text_message message={lines, 2}; struct text_message message={lines, 2};
if(gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES) if(gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES)
rolo_load("/" BOOTFILE); rolo_load("/" BOOTFILE);
@ -1336,6 +1336,7 @@ void tree_restore(void)
str(LANG_SCANNING_DISK)); str(LANG_SCANNING_DISK));
gui_textarea_update(&screens[i]); gui_textarea_update(&screens[i]);
} }
cond_talk_ids_fq(LANG_SCANNING_DISK);
dircache_build(global_status.dircache_size); dircache_build(global_status.dircache_size);