Index: apps/playlist.c =================================================================== --- apps/playlist.c (revision 12799) +++ apps/playlist.c (working copy) @@ -288,6 +288,7 @@ { if (check_rockboxdir()) { + cond_talk_ids_fq(LANG_PLAYLIST_CONTROL_ACCESS_ERROR); gui_syncsplash(HZ*2, true, (unsigned char *)"%s (%d)", str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR), playlist->control_fd); @@ -484,6 +485,7 @@ lcd_setmargins(0, 0); #endif + cond_talk_ids(LANG_WAIT); gui_syncsplash(0, true, str(LANG_PLAYLIST_LOAD)); if (!buffer) @@ -770,9 +772,9 @@ unsigned char* count_str; if (c->queue) - count_str = str(LANG_PLAYLIST_QUEUE_COUNT); + count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); else - count_str = str(LANG_PLAYLIST_INSERT_COUNT); + count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT); display_playlist_count(c->count, count_str); @@ -1348,9 +1350,9 @@ if (max < 0) { if (control_file) - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); else - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); return max; } @@ -1440,7 +1442,7 @@ if (ft_load(tc, (dir[0]=='\0')?"/":dir) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); exit = true; result = -1; break; @@ -1525,7 +1527,7 @@ if (ft_load(tc, dir) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); return -2; } @@ -1578,8 +1580,7 @@ /* we now need to reload our current directory */ if(ft_load(tc, dir) < 0) - gui_syncsplash(HZ*2, true, - str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); } return result; @@ -1654,6 +1655,20 @@ */ static void display_playlist_count(int count, const unsigned char *fmt) { + static long talked_tick = 0; + if(count && (talked_tick == 0 + || TIME_AFTER(current_tick, talked_tick+5*HZ))) + { + talked_tick = current_tick; + long id = P2ID(fmt); + if(id>=0) + { + talk_number(count, false); + talk_id(id, true); + } + } + fmt = P2STR(fmt); + lcd_clear_display(); #ifdef HAVE_LCD_BITMAP @@ -1677,7 +1692,7 @@ */ static void display_buffer_full(void) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_BUFFER_FULL)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_BUFFER_FULL)); } /* @@ -1756,7 +1771,7 @@ else { result = -1; - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); } return result; @@ -1943,11 +1958,11 @@ empty_playlist(playlist, true); - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); playlist->control_fd = open(playlist->control_filename, O_RDWR); if (playlist->control_fd < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } playlist->control_created = true; @@ -1955,7 +1970,7 @@ control_file_size = filesize(playlist->control_fd); if (control_file_size <= 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } @@ -1964,7 +1979,7 @@ PLAYLIST_COMMAND_SIZE= control_file_size) { /* no newline at end of control file */ - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_INVALID)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_INVALID)); return -1; } @@ -2367,6 +2382,7 @@ start_current = true; } + cond_talk_ids(LANG_WAIT); gui_syncsplash(0, true, str(LANG_PLAYLIST_SHUFFLE)); randomise_playlist(playlist, random_seed, start_current, true); @@ -2859,7 +2875,7 @@ if (check_control(playlist) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } @@ -2890,7 +2906,7 @@ if (check_control(playlist) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } @@ -2903,9 +2919,9 @@ } if (queue) - count_str = str(LANG_PLAYLIST_QUEUE_COUNT); + count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); else - count_str = str(LANG_PLAYLIST_INSERT_COUNT); + count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT); display_playlist_count(0, count_str); @@ -2956,14 +2972,14 @@ if (check_control(playlist) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } fd = open(filename, O_RDONLY); if (fd < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); return -1; } @@ -2977,9 +2993,9 @@ dir = "/"; if (queue) - count_str = str(LANG_PLAYLIST_QUEUE_COUNT); + count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); else - count_str = str(LANG_PLAYLIST_INSERT_COUNT); + count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT); display_playlist_count(count, count_str); @@ -3076,7 +3092,7 @@ if (check_control(playlist) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } @@ -3111,7 +3127,7 @@ if (check_control(playlist) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); return -1; } @@ -3374,7 +3390,7 @@ if (playlist->buffer_size < (int)(playlist->amount * sizeof(int))) { /* not enough buffer space to store updated indices */ - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); return -1; } @@ -3390,11 +3406,11 @@ fd = open(path, O_CREAT|O_WRONLY|O_TRUNC); if (fd < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); return -1; } - display_playlist_count(count, str(LANG_PLAYLIST_SAVE_COUNT)); + display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT)); cpu_boost(true); @@ -3431,7 +3447,7 @@ if (fdprintf(fd, "%s\n", tmp_buf) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); result = -1; break; } @@ -3518,7 +3534,7 @@ if (ft_load(tc, dirname) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); *(tc->dirfilter) = old_dirfilter; return -1; } Index: apps/tree.c =================================================================== --- apps/tree.c (revision 12799) +++ apps/tree.c (working copy) @@ -366,7 +366,7 @@ (tc.dirfull || tc.filesindir == global_settings.max_files_in_dir) ) { - gui_syncsplash(HZ, true, str(LANG_SHOWDIR_BUFFER_FULL)); + gui_syncsplash(HZ, true, ID2P(LANG_SHOWDIR_BUFFER_FULL)); } } #ifdef HAVE_TAGCACHE Index: apps/settings.c =================================================================== --- apps/settings.c (revision 12799) +++ apps/settings.c (working copy) @@ -578,6 +578,7 @@ screens[i].update(); #endif } + cond_talk_ids_fq(LANG_SETTINGS_SAVE_RECORDER); sleep(HZ*2); return -1; } @@ -596,15 +597,15 @@ break; } else { - gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL)); + gui_syncsplash(HZ, true, ID2P(LANG_MENU_SETTING_CANCEL)); return false; } } if (settings_write_config(filename, options)) - gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED)); + gui_syncsplash(HZ, true, ID2P(LANG_SETTINGS_SAVED)); else - gui_syncsplash(HZ, true, str(LANG_FAILED)); + gui_syncsplash(HZ, true, ID2P(LANG_FAILED)); return true; } @@ -1142,7 +1143,7 @@ { if (*(int*)variable != oldvalue) { - gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL)); + gui_syncsplash(HZ/2,true,ID2P(LANG_MENU_SETTING_CANCEL)); *(int*)variable = oldvalue; } } @@ -1150,7 +1151,7 @@ { if (*(bool*)variable != (bool)oldvalue) { - gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL)); + gui_syncsplash(HZ/2,true,ID2P(LANG_MENU_SETTING_CANCEL)); *(bool*)variable = (bool)oldvalue; } } Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 12799) +++ apps/lang/english.lang (working copy) @@ -152,7 +152,7 @@ *: "Shutting down..." - *: "" + *: "Shutting down" @@ -194,7 +194,7 @@ *: "Cancelled" - *: "" + *: "Cancelled" @@ -208,7 +208,7 @@ *: "Failed" - *: "" + *: "Failed" @@ -852,7 +852,7 @@ *: "Are You Sure?" - *: "" + *: "Are You Sure?" @@ -920,7 +920,7 @@ *: "Cleared" - *: "" + *: "Settings Cleared" @@ -934,7 +934,7 @@ *: "Cancelled" - *: "" + *: "Canceled" @@ -962,7 +962,7 @@ *: "Save Failed" - *: "" + *: "Save Failed" @@ -1186,7 +1186,7 @@ *: "Peak Filter %d" - *: "Peak filter" + *: "" @@ -1760,7 +1760,7 @@ *: "Updating in background" - *: "" + *: "Updating in background" @@ -4129,7 +4129,7 @@ *: "File/directory exists. Overwrite?" - *: "" + *: "File or directory exists. Overwrite?" @@ -4185,7 +4185,7 @@ *: "Delete?" - *: "" + *: "Really delete?" @@ -4199,7 +4199,7 @@ *: "Deleted" - *: "" + *: "Deleted" @@ -4849,7 +4849,7 @@ *: "Load Last Bookmark?" - *: "" + *: "Load Last Bookmark?" @@ -4863,7 +4863,7 @@ *: "Create a Bookmark?" - *: "" + *: "Create a Bookmark?" @@ -4877,7 +4877,7 @@ *: "Bookmark Created" - *: "" + *: "Bookmark Created" @@ -4891,7 +4891,7 @@ *: "Bookmark Failed!" - *: "" + *: "Bookmark Failed!" @@ -4905,7 +4905,7 @@ *: "Bookmark Empty" - *: "" + *: "Bookmark Empty" @@ -7281,7 +7281,7 @@ *: "Playlist Buffer Full" - *: "" + *: "Playlist Buffer Full" @@ -7309,7 +7309,7 @@ *: "End of Song List" - *: "" + *: "End of Song List" @@ -7337,7 +7337,7 @@ *: "Inserted %d tracks (%s)" - *: "" + *: "Inserted tracks so far" @@ -7351,7 +7351,7 @@ *: "Queued %d tracks (%s)" - *: "" + *: "Queued tracks so far" @@ -7365,7 +7365,7 @@ *: "Saved %d tracks (%s)" - *: "" + *: "Tracks saved" @@ -7379,7 +7379,7 @@ *: "Recursively?" - *: "" + *: "Recursively?" @@ -7393,7 +7393,7 @@ *: "Erase dynamic playlist?" - *: "" + *: "Erase dynamic playlist?" @@ -7407,7 +7407,7 @@ *: "Nothing to resume" - *: "" + *: "Nothing to resume" @@ -7421,7 +7421,7 @@ *: "Error updating playlist control file" - *: "" + *: "Error updating playlist control file" @@ -7435,7 +7435,7 @@ *: "Error accessing playlist file" - *: "" + *: "Error accessing palylist file" @@ -7449,7 +7449,7 @@ *: "Error accessing playlist control file" - *: "" + *: "Error accessing playlist control file" @@ -7463,7 +7463,7 @@ *: "Error accessing directory" - *: "" + *: "Error accessing directory" @@ -7477,7 +7477,7 @@ *: "Playlist control file is invalid" - *: "" + *: "Playlist control file is invalid" @@ -7841,7 +7841,7 @@ *: "Dir Buffer is Full!" - *: "" + *: "Directory Buffer is Full!" @@ -7855,7 +7855,7 @@ *: "New Language" - *: "" + *: "New Language" @@ -7869,7 +7869,7 @@ *: "Settings Loaded" - *: "" + *: "Settings Loaded" @@ -7883,7 +7883,7 @@ *: "Settings Saved" - *: "" + *: "Settings Saved" @@ -7961,7 +7961,7 @@ *: "No files" - *: "" + *: "No files" @@ -8003,7 +8003,7 @@ *: "New Keyboard" - *: "" + *: "New Keyboard" @@ -8171,7 +8171,7 @@ *: "Move Failed" - *: "" + *: "Move Failed" @@ -8339,7 +8339,7 @@ *: "Extension array full" - *: "" + *: "Extension array full" @@ -8353,7 +8353,7 @@ *: "Filetype array full" - *: "" + *: "Filetype array full" @@ -8367,7 +8367,7 @@ *: "Plugin name too long" - *: "" + *: "Plugin name too long" @@ -8381,7 +8381,7 @@ *: "Filetype string buffer empty" - *: "" + *: "Filetype string buffer empty" @@ -8726,7 +8726,7 @@ *: "%s doesn't exist" - *: "" + *: "Playlist directory doesn't exist" @@ -8740,7 +8740,7 @@ *: "No Playlists" - *: "" + *: "No Playlists" @@ -10052,7 +10052,7 @@ *: "Please reboot to enable" - *: "" + *: "Please Reboot to enable the cache" @@ -10272,7 +10272,7 @@ *: "WARNING! Low Battery!" - *: "" + *: "WARNING! Low Battery!" @@ -10286,7 +10286,7 @@ *: "Battery empty! RECHARGE!" - *: "" + *: "Battery empty! RECHARGE!" Index: apps/onplay.c =================================================================== --- apps/onplay.c (revision 12799) +++ apps/onplay.c (working copy) @@ -168,12 +168,12 @@ { bool new_playlist = !(audio_status() & AUDIO_STATUS_PLAY); char *lines[] = { - (char *)str(LANG_RECURSE_DIRECTORY_QUESTION), + ID2P(LANG_RECURSE_DIRECTORY_QUESTION), selected_file }; struct text_message message={lines, 2}; - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if (new_playlist) playlist_create(NULL, NULL); @@ -476,11 +476,11 @@ static bool delete_handler(bool is_dir) { char *lines[]={ - (char *)str(LANG_REALLY_DELETE), + ID2P(LANG_REALLY_DELETE), selected_file }; char *yes_lines[]={ - (char *)str(LANG_DELETED), + ID2P(LANG_DELETED), selected_file }; @@ -546,6 +546,7 @@ lcd_puts(0,0,str(LANG_RENAME)); lcd_puts(0,1,str(LANG_FAILED)); lcd_update(); + cond_talk_ids_fq(LANG_RENAME, LANG_FAILED); sleep(HZ*2); } else @@ -575,6 +576,7 @@ rc = mkdir(dirname); if (rc < 0) { + cond_talk_ids_fq(LANG_CREATE_DIR, LANG_FAILED); gui_syncsplash(HZ, true, (unsigned char *)"%s %s", str(LANG_CREATE_DIR), str(LANG_FAILED)); } else { @@ -794,7 +796,7 @@ bool success; int target_fd; - unsigned char *lines[]={str(LANG_REALLY_OVERWRITE)}; + unsigned char *lines[]={ID2P(LANG_REALLY_OVERWRITE)}; struct text_message message={(char **)lines, 1}; /* Get the name of the current directory */ @@ -849,6 +851,7 @@ /* Force reload of the current directory */ onplay_result = ONPLAY_RELOAD_DIR; } else { + cond_talk_ids_fq(LANG_PASTE, LANG_FAILED); gui_syncsplash(HZ, true, (unsigned char *)"%s %s", str(LANG_PASTE), str(LANG_FAILED)); } Index: apps/gui/splash.c =================================================================== --- apps/gui/splash.c (revision 12799) +++ apps/gui/splash.c (working copy) @@ -22,6 +22,9 @@ #include "stdio.h" #include "kernel.h" #include "screen_access.h" +#include "lang.h" +#include "settings.h" +#include "talk.h" #ifndef MAX #define MAX(a, b) (((a)>(b))?(a):(b)) @@ -211,6 +214,15 @@ { va_list ap; 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 ); FOR_NB_SCREENS(i) splash(&(screens[i]), center, fmt, ap); Index: apps/gui/yesno.c =================================================================== --- apps/gui/yesno.c (revision 12799) +++ apps/gui/yesno.c (working copy) @@ -23,6 +23,7 @@ #include "misc.h" #include "lang.h" #include "action.h" +#include "talk.h" /* * Initializes the yesno asker @@ -95,7 +96,28 @@ gui_textarea_put_message(yn->display, message, 0); return(true); } + #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; linenb_lines; line++) { + long id = P2ID((unsigned char *)m->message_lines[line]); + if(id>=0 && imessage_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, struct text_message * yes_message, struct text_message * no_message) @@ -105,6 +127,13 @@ int result=-1; bool result_displayed; 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) { gui_yesno_init(&(yn[i]), main_message, yes_message, no_message); @@ -114,7 +143,14 @@ action_signalscreenchange(); while (result==-1) { - button = get_action(CONTEXT_YESNOSCREEN,TIMEOUT_BLOCK); + /* Repeat the question every 5secs (more or less) */ + if (global_settings.talk_menu + && (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) { case ACTION_YESNO_ACCEPT: @@ -131,6 +167,13 @@ action_signalscreenchange(); FOR_NB_SCREENS(i) 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 (global_settings.talk_menu) + { + talk_idarray(voice_ids, false); + talk_force_enqueue_next(); + } if(result_displayed) sleep(HZ); return(result); Index: apps/menus/recording_menu.c =================================================================== --- apps/menus/recording_menu.c (revision 12799) +++ apps/menus/recording_menu.c (working copy) @@ -638,7 +638,7 @@ switch (button) { case ACTION_STD_CANCEL: - gui_syncsplash(50, true, str(LANG_MENU_SETTING_CANCEL)); + gui_syncsplash(50, true, ID2P(LANG_MENU_SETTING_CANCEL)); global_settings.rec_start_thres = old_start_thres; global_settings.rec_start_duration = old_start_duration; global_settings.rec_prerecord_time = old_prerecord_time; Index: apps/menus/settings_menu.c =================================================================== --- apps/menus/settings_menu.c (revision 12799) +++ apps/menus/settings_menu.c (working copy) @@ -49,13 +49,13 @@ static void tagcache_rebuild_with_splash(void) { tagcache_rebuild(); - gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); + gui_syncsplash(HZ*2, true, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); } static void tagcache_update_with_splash(void) { tagcache_update(); - gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); + gui_syncsplash(HZ*2, true, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); } #ifdef HAVE_TC_RAMCACHE @@ -163,7 +163,7 @@ { case true: if (!dircache_is_enabled()) - gui_syncsplash(HZ*2, true, str(LANG_PLEASE_REBOOT)); + gui_syncsplash(HZ*2, true, ID2P(LANG_PLEASE_REBOOT)); break; case false: if (dircache_is_enabled()) Index: apps/playlist_viewer.c =================================================================== --- apps/playlist_viewer.c (revision 12799) +++ apps/playlist_viewer.c (working copy) @@ -635,6 +635,7 @@ if (!viewer.playlist && !(audio_status() & AUDIO_STATUS_PLAY)) { /* Play has stopped */ + cond_talk_ids_fq(LANG_END_PLAYLIST_RECORDER); #ifdef HAVE_LCD_CHARCELLS gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_PLAYER)); #else @@ -696,7 +697,7 @@ ret = playlist_move(viewer.playlist, viewer.move_track, current_track->index); if (ret < 0) - gui_syncsplash(HZ, true, str(LANG_MOVE_FAILED)); + gui_syncsplash(HZ, true, ID2P(LANG_MOVE_FAILED)); update_playlist(true); viewer.move_track = -1; Index: apps/talk.c =================================================================== --- apps/talk.c (revision 12799) +++ apps/talk.c (working copy) @@ -116,6 +116,8 @@ static struct voicefile* p_voicefile; /* loaded voicefile */ static bool has_voicefile; /* a voicefile file is present */ 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_read; /* read index of queue, by ISR context */ static int sent; /* how many bytes handed over to playback, owned by ISR */ @@ -132,7 +134,6 @@ static void load_voicefile(void); static void mp3_callback(unsigned char** start, int* size); -static int shutup(void); static int queue_clip(unsigned char* buf, long size, bool enqueue); static int open_voicefile(void); static unsigned char* get_clip(long id, long* p_size); @@ -260,6 +261,13 @@ } +/* Are more voice clips queued and waiting? */ +bool is_voice_queued() +{ + return !!QUEUE_LEVEL; +} + + /* called in ISR context if mp3 data got consumed */ static void mp3_callback(unsigned char** start, int* size) { @@ -314,7 +322,7 @@ } /* stop the playback and the pending clips */ -static int shutup(void) +int do_shutup(void) { #if CONFIG_CODEC != SWCODEC unsigned char* pos; @@ -380,6 +388,13 @@ return 0; } +/* Shutup the voice, except if force_enqueue_next is set. */ +int shutup(void) +{ + if (!force_enqueue_next) + return do_shutup(); + return 0; +} /* schedule a clip, at the end or discard the existing queue */ static int queue_clip(unsigned char* buf, long size, bool enqueue) @@ -388,6 +403,9 @@ if (!enqueue) 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) return 0; /* safety check */ @@ -612,7 +630,27 @@ 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 */ int talk_file(const char* filename, bool enqueue) { Index: apps/filetree.c =================================================================== --- apps/filetree.c (revision 12799) +++ apps/filetree.c (working copy) @@ -360,21 +360,21 @@ switch ( file->attr & TREE_ATTR_MASK ) { case TREE_ATTR_M3U: if (global_settings.party_mode) { - gui_syncsplash(HZ, true, str(LANG_PARTY_MODE)); + gui_syncsplash(HZ, true, ID2P(LANG_PARTY_MODE)); break; } if (bookmark_autoload(buf)) break; - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); /* about to create a new current playlist... allow user to cancel the operation */ if (global_settings.warnon_erase_dynplaylist && playlist_modified(NULL)) { - char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; + char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; struct text_message message={lines, 1}; if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) @@ -395,7 +395,7 @@ if (bookmark_autoload(c->currdir)) break; - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); /* about to create a new current playlist... allow user to cancel the operation */ @@ -403,7 +403,7 @@ !global_settings.party_mode && playlist_modified(NULL)) { - char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; + char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; struct text_message message={lines, 1}; if(gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) @@ -414,7 +414,7 @@ { playlist_insert_track(NULL, buf, PLAYLIST_INSERT_LAST, true, true); - gui_syncsplash(HZ, true, str(LANG_QUEUE_LAST)); + gui_syncsplash(HZ, true, ID2P(LANG_QUEUE_LAST)); } else if (playlist_create(c->currdir, NULL) != -1) { @@ -439,7 +439,7 @@ /* fmr preset file */ case TREE_ATTR_FMR: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); /* Preset inside the default folder. */ if(!strncasecmp(FMPRESET_PATH, buf, strlen(FMPRESET_PATH))) @@ -466,7 +466,7 @@ /* wps config file */ case TREE_ATTR_WPS: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); #if LCD_DEPTH > 1 unload_wps_backdrop(); #endif @@ -478,7 +478,7 @@ #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) /* remote-wps config file */ case TREE_ATTR_RWPS: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); wps_data_load(gui_wps[1].data, buf, true); set_file(buf, (char *)global_settings.rwps_file, MAX_FILENAME); @@ -486,39 +486,39 @@ #endif case TREE_ATTR_CFG: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if (!settings_load_config(buf,true)) break; - gui_syncsplash(HZ, true, str(LANG_SETTINGS_LOADED)); + gui_syncsplash(HZ, true, ID2P(LANG_SETTINGS_LOADED)); break; case TREE_ATTR_BMARK: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); bookmark_load(buf, false); reload_dir = true; break; case TREE_ATTR_LNG: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if(!lang_load(buf)) { set_file(buf, (char *)global_settings.lang_file, MAX_FILENAME); talk_init(); /* use voice of same language */ - gui_syncsplash(HZ, true, str(LANG_LANGUAGE_LOADED)); + gui_syncsplash(HZ, true, ID2P(LANG_LANGUAGE_LOADED)); } break; #ifdef HAVE_LCD_BITMAP case TREE_ATTR_FONT: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); font_load(buf); set_file(buf, (char *)global_settings.font_file, MAX_FILENAME); break; case TREE_ATTR_KBD: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if (!load_kbd(buf)) - gui_syncsplash(HZ, true, str(LANG_KEYBOARD_LOADED)); + gui_syncsplash(HZ, true, ID2P(LANG_KEYBOARD_LOADED)); set_file(buf, (char *)global_settings.kbd_file, MAX_FILENAME); break; #endif @@ -526,7 +526,7 @@ #ifndef SIMULATOR /* firmware file */ case TREE_ATTR_MOD: - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); rolo_load(buf); break; #endif @@ -534,11 +534,11 @@ /* plugin file */ case TREE_ATTR_ROCK: if (global_settings.party_mode) { - gui_syncsplash(HZ, true, str(LANG_PARTY_MODE)); + gui_syncsplash(HZ, true, ID2P(LANG_PARTY_MODE)); break; } - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if (plugin_load(buf,NULL) == PLUGIN_USB_CONNECTED) { @@ -560,7 +560,7 @@ char* plugin; if (global_settings.party_mode) { - gui_syncsplash(HZ, true, str(LANG_PARTY_MODE)); + gui_syncsplash(HZ, true, ID2P(LANG_PARTY_MODE)); break; } Index: apps/talk.h =================================================================== --- apps/talk.h (revision 12799) +++ apps/talk.h (working copy) @@ -66,10 +66,46 @@ int talk_get_bufsize(void); /* get the loaded voice file size */ /* 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 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_file(const char* filename, bool enqueue); /* play a thumbnail from file */ int talk_number(long n, bool enqueue); /* say a number */ int talk_value(long n, int unit, bool enqueue); /* say a numeric value */ int talk_spell(const char* spell, bool enqueue); /* spell a string */ +/* 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 (global_settings.talk_menu) \ + talk_ids(false, ids); \ + } while(0) +/* And a version that takes the array parameter... */ +#define cond_talk_idarray(idarray) do { \ + if (global_settings.talk_menu) \ + 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 (global_settings.talk_menu) { \ + talk_ids(false, ids); \ + talk_force_enqueue_next(); \ + } \ + }while(0) + #endif /* __TALK_H__ */ Index: apps/playback.c =================================================================== --- apps/playback.c (revision 12799) +++ apps/playback.c (working copy) @@ -874,7 +874,22 @@ #endif } /* voice_stop */ +/* Is voice still speaking */ +/* Unfortunately only reliable when music is not also playing. */ +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(1); +} /* --- Routines called from multiple threads --- */ static void set_current_codec(int codec_idx) Index: apps/playback.h =================================================================== --- apps/playback.h (revision 12799) +++ apps/playback.h (working copy) @@ -66,6 +66,8 @@ bool last_track)); void voice_init(void); void voice_stop(void); +bool is_voice_speaking(void); +void voice_wait(void); #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ extern void audio_next_dir(void); Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 12799) +++ apps/plugin.c (working copy) @@ -526,7 +526,7 @@ plugin_loaded = false; } - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); strcpy(current_plugin,p); #ifdef SIMULATOR Index: apps/filetypes.c =================================================================== --- apps/filetypes.c (revision 12799) +++ apps/filetypes.c (working copy) @@ -340,14 +340,14 @@ /* exttypes[] full, bail out */ if (cnt_exttypes >= MAX_EXTTYPES) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_EXTENSION_FULL)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_EXTENSION_FULL)); break; } /* filetypes[] full, bail out */ if (cnt_filetypes >= MAX_FILETYPES) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_FULL)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_FULL)); break; } @@ -380,7 +380,7 @@ /* filter out to long filenames */ if (strlen((char *)entry->d_name) > MAX_PLUGIN_LENGTH + 5) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_PLUGIN_NAME_LONG)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_PLUGIN_NAME_LONG)); continue; } @@ -561,13 +561,13 @@ { if (cnt_exttypes >= MAX_EXTTYPES) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_EXTENSION_FULL)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_EXTENSION_FULL)); break; } if (cnt_filetypes >= MAX_FILETYPES) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_FULL)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_FULL)); break; } @@ -636,7 +636,7 @@ { if (strlen(str[plugin]) > MAX_PLUGIN_LENGTH) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_PLUGIN_NAME_LONG)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_PLUGIN_NAME_LONG)); str[plugin] = NULL; continue; } @@ -736,7 +736,7 @@ (unsigned long) string_buffer - (unsigned long) next_free_string) < ICON_LENGTH) { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_STRING_BUFFER_EMPTY)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_STRING_BUFFER_EMPTY)); return NULL; } @@ -792,7 +792,7 @@ } else { - gui_syncsplash(HZ, true, str(LANG_FILETYPES_STRING_BUFFER_EMPTY)); + gui_syncsplash(HZ, true, ID2P(LANG_FILETYPES_STRING_BUFFER_EMPTY)); return NULL; } } Index: apps/bookmark.c =================================================================== --- apps/bookmark.c (revision 12799) +++ apps/bookmark.c (working copy) @@ -171,10 +171,10 @@ return write_bookmark(false); } #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}; #else - unsigned char *lines[]={str(LANG_AUTO_BOOKMARK_QUERY), + unsigned char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY), str(LANG_RESUME_CONFIRM_PLAYER)}; struct text_message message={(char **)lines, 2}; #endif @@ -226,8 +226,8 @@ } } - gui_syncsplash(HZ, true, str(success ? LANG_BOOKMARK_CREATE_SUCCESS - : LANG_BOOKMARK_CREATE_FAILURE)); + gui_syncsplash(HZ, true, success ? ID2P(LANG_BOOKMARK_CREATE_SUCCESS) + : ID2P(LANG_BOOKMARK_CREATE_FAILURE)); return true; } @@ -403,6 +403,7 @@ screens[i].puts(0,1,str(LANG_RESUME_CONFIRM_PLAYER)); #endif } + cond_talk_ids(LANG_BOOKMARK_AUTOLOAD_QUERY); /* Wait for a key to be pushed */ key = get_action(CONTEXT_BOOKMARKSCREEN,TIMEOUT_BLOCK); @@ -520,7 +521,7 @@ /* if there were no bookmarks in the file, delete the file and exit. */ if(bookmark_id <= 0) { - gui_syncsplash(HZ, true, str(LANG_BOOKMARK_LOAD_EMPTY)); + gui_syncsplash(HZ, true, ID2P(LANG_BOOKMARK_LOAD_EMPTY)); remove(bookmark_file_name); action_signalscreenchange(); return NULL; Index: apps/root_menu.c =================================================================== --- apps/root_menu.c (revision 12799) +++ apps/root_menu.c (working copy) @@ -231,7 +231,7 @@ } else { - gui_syncsplash(HZ*2, true, str(LANG_NOTHING_TO_RESUME)); + gui_syncsplash(HZ*2, true, ID2P(LANG_NOTHING_TO_RESUME)); } #if LCD_DEPTH > 1 show_main_backdrop(); Index: apps/misc.c =================================================================== --- apps/misc.c (revision 12799) +++ apps/misc.c (working copy) @@ -60,6 +60,7 @@ #include "gui/gwps-common.h" #include "misc.h" +#include "playback.h" /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" @@ -608,23 +609,27 @@ x5_backlight_shutdown(); #endif if (!battery_level_safe()) + { + cond_talk_ids(LANG_WARNING_BATTERY_EMPTY, LANG_SHUTTINGDOWN); gui_syncsplash(3*HZ, true, "%s %s", str(LANG_WARNING_BATTERY_EMPTY), str(LANG_SHUTTINGDOWN)); - else if (battery_level_critical()) + } else if (battery_level_critical()) + { + cond_talk_ids(LANG_WARNING_BATTERY_LOW, LANG_SHUTTINGDOWN); gui_syncsplash(3*HZ, true, "%s %s", str(LANG_WARNING_BATTERY_LOW), str(LANG_SHUTTINGDOWN)); - else { + } else { #ifdef HAVE_TAGCACHE if (!tagcache_prepare_shutdown()) { cancel_shutdown(); - gui_syncsplash(HZ, true, str(LANG_TAGCACHE_BUSY)); + gui_syncsplash(HZ, true, ID2P(LANG_TAGCACHE_BUSY)); return false; } #endif - gui_syncsplash(0, true, str(LANG_SHUTTINGDOWN)); + gui_syncsplash(0, true, ID2P(LANG_SHUTTINGDOWN)); } if (global_settings.fade_on_stop @@ -648,7 +653,11 @@ audio_stop(); while (audio_status()) sleep(1); - + +#if CONFIG_CODEC == SWCODEC + voice_wait(); +#endif + if (callback != NULL) callback(parameter); Index: apps/playlist_catalog.c =================================================================== --- apps/playlist_catalog.c (revision 12799) +++ apps/playlist_catalog.c (working copy) @@ -37,6 +37,7 @@ #include "sprintf.h" #include "tree.h" #include "yesno.h" +#include "talk.h" #define PLAYLIST_CATALOG_CFG ROCKBOX_DIR "/playlist_catalog.config" #define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists" @@ -112,7 +113,7 @@ if (!playlist_dir_exists) { if (mkdir(playlist_dir) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_CATALOG_NO_DIRECTORY), + gui_syncsplash(HZ*2, true, ID2P(LANG_CATALOG_NO_DIRECTORY), playlist_dir); return -1; } @@ -146,7 +147,7 @@ if (ft_load(tc, playlist_dir) < 0) { - gui_syncsplash(HZ*2, true, str(LANG_CATALOG_NO_DIRECTORY), + gui_syncsplash(HZ*2, true, ID2P(LANG_CATALOG_NO_DIRECTORY), playlist_dir); goto exit; } @@ -231,7 +232,7 @@ if (num_playlists <= 0) { - gui_syncsplash(HZ*2, true, str(LANG_CATALOG_NO_PLAYLISTS)); + gui_syncsplash(HZ*2, true, ID2P(LANG_CATALOG_NO_PLAYLISTS)); return -1; } @@ -319,6 +320,15 @@ insert */ static void display_insert_count(int count) { + static long talked_tick = 0; + if(count && (talked_tick == 0 + || TIME_AFTER(current_tick, talked_tick+5*HZ))) + { + talked_tick = current_tick; + talk_number(count, false); + talk_id(LANG_PLAYLIST_INSERT_COUNT, true); + } + gui_syncsplash(0, true, str(LANG_PLAYLIST_INSERT_COUNT), count, #if CONFIG_KEYPAD == PLAYER_PAD str(LANG_STOP_ABORT) @@ -403,7 +413,7 @@ /* search directory for tracks and append to playlist */ bool recurse = false; char *lines[] = { - (char *)str(LANG_RECURSE_DIRECTORY_QUESTION), + ID2P(LANG_RECURSE_DIRECTORY_QUESTION), sel }; struct text_message message={lines, 2}; Index: apps/tagtree.c =================================================================== --- apps/tagtree.c (revision 12799) +++ apps/tagtree.c (working copy) @@ -676,7 +676,7 @@ gui_syncsplash(0, true, str(LANG_CREATING)); if (!tagcache_create_changelog(&tcs)) { - gui_syncsplash(HZ*2, true, str(LANG_FAILED)); + gui_syncsplash(HZ*2, true, ID2P(LANG_FAILED)); } return false; @@ -684,10 +684,10 @@ bool tagtree_import(void) { - gui_syncsplash(0, true, str(LANG_WAIT)); + gui_syncsplash(0, true, ID2P(LANG_WAIT)); if (!tagcache_import_changelog()) { - gui_syncsplash(HZ*2, true, str(LANG_FAILED)); + gui_syncsplash(HZ*2, true, ID2P(LANG_FAILED)); } return false; @@ -1200,7 +1200,7 @@ if (!sort && (sort_inverse || sort_limit)) { - gui_syncsplash(HZ*4, true, str(LANG_SHOWDIR_BUFFER_FULL), total_count); + gui_syncsplash(HZ*4, true, ID2P(LANG_SHOWDIR_BUFFER_FULL), total_count); logf("Too small dir buffer"); return 0; } @@ -1391,7 +1391,7 @@ !global_settings.party_mode && playlist_modified(NULL)) { - char *lines[]={str(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; + char *lines[]={ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; struct text_message message={lines, 1}; if (gui_syncyesno_run(&message, NULL, NULL) != YESNO_YES) @@ -1468,7 +1468,7 @@ cpu_boost(true); if (!tagcache_search(&tcs, tag_filename)) { - gui_syncsplash(HZ, true, str(LANG_TAGCACHE_BUSY)); + gui_syncsplash(HZ, true, ID2P(LANG_TAGCACHE_BUSY)); cpu_boost(false); return false; } @@ -1571,12 +1571,12 @@ } if (tc->filesindir <= 0) - gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_PLAYER)); + gui_syncsplash(HZ, true, ID2P(LANG_END_PLAYLIST_PLAYER)); else { logf("insert_all_playlist"); if (!insert_all_playlist(tc, position, queue)) - gui_syncsplash(HZ*2, true, str(LANG_FAILED)); + gui_syncsplash(HZ*2, true, ID2P(LANG_FAILED)); } /* Finally return the dirlevel to its original value. */