diff --git a/apps/alarm_menu.c b/apps/alarm_menu.c index 5709c5ad4a..391558a34e 100644 --- a/apps/alarm_menu.c +++ b/apps/alarm_menu.c @@ -44,7 +44,7 @@ static void speak_time(int hours, int minutes, bool speak_hours) { - if (talk_menus_enabled()){ + if (global_settings.talk_menu){ if(speak_hours) { talk_value(hours, UNIT_HOUR, false); talk_value(minutes, UNIT_MIN, true); @@ -86,7 +86,7 @@ bool alarm_screen(void) screens[i].puts(0, 3, str(LANG_ALARM_MOD_KEYS)); } /* Talk when entering the wakeup screen */ - if (talk_menus_enabled()) + if (global_settings.talk_menu) { talk_value(h, UNIT_HOUR, true); talk_value(m, UNIT_MIN, true); @@ -113,7 +113,7 @@ bool alarm_screen(void) rtc_init(); rtc_set_alarm(h,m); rtc_enable_alarm(true); - if (talk_menus_enabled()) + if (global_settings.talk_menu) { talk_id(LANG_ALARM_MOD_TIME_TO_GO, true); talk_value(togo / 60, UNIT_HOUR, true); @@ -164,7 +164,7 @@ bool alarm_screen(void) case ACTION_STD_NEXTREPEAT: h = (h+1) % 24; - if (talk_menus_enabled()) + if (global_settings.talk_menu) talk_value(h, UNIT_HOUR, false); break; @@ -173,7 +173,7 @@ bool alarm_screen(void) case ACTION_STD_PREVREPEAT: h = (h+23) % 24; - if (talk_menus_enabled()) + if (global_settings.talk_menu) talk_value(h, UNIT_HOUR, false); break; diff --git a/apps/bookmark.c b/apps/bookmark.c index 4522859f57..184281ba87 100644 --- a/apps/bookmark.c +++ b/apps/bookmark.c @@ -667,7 +667,7 @@ static char* select_bookmark(const char* bookmark_file_name, bool show_dont_resu item--; } - if (item != last_item && talk_menus_enabled()) + if (item != last_item && global_settings.talk_menu) { last_item = item; diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index 4f446fc8de..3b26ab12d2 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c @@ -133,7 +133,7 @@ static char *option_get_valuestring(struct settings_list *setting, static void option_talk(struct settings_list *setting, int temp_var) { - if (!talk_menus_enabled()) + if (!global_settings.talk_menu) return; if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) { diff --git a/apps/gui/yesno.c b/apps/gui/yesno.c index 7c8afb3245..4e86b017ca 100644 --- a/apps/gui/yesno.c +++ b/apps/gui/yesno.c @@ -145,7 +145,7 @@ enum yesno_res gui_syncyesno_run(struct text_message * main_message, while (result==-1) { /* Repeat the question every 5secs (more or less) */ - if (talk_menus_enabled() + if (global_settings.talk_menu && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5))) { talked_tick = current_tick; @@ -175,7 +175,7 @@ enum yesno_res gui_syncyesno_run(struct text_message * main_message, FOR_NB_SCREENS(i) result_displayed=gui_yesno_draw_result(&(yn[i]), result); - if (talk_menus_enabled()) + if (global_settings.talk_menu) { talk_idarray(voice_ids, false); talk_force_enqueue_next(); diff --git a/apps/main.c b/apps/main.c index e4fd6bc614..366fed9585 100644 --- a/apps/main.c +++ b/apps/main.c @@ -225,7 +225,7 @@ static void init_tagcache(void) /* hwcodec can't use voice here, as the database commit * uses the audio buffer. */ static long talked_tick = 0; - if(talk_menus_enabled() + if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { diff --git a/apps/menu.c b/apps/menu.c index 1dedc42a5c..55f1938b80 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -225,7 +225,7 @@ static void talk_menu_item(const struct menu_item_ex *menu, unsigned char *str; int sel; - if (talk_menus_enabled()) + if (global_settings.talk_menu) { sel = get_menu_selection(gui_synclist_get_sel_pos(lists),menu); if ((menu->flags&MENU_TYPE_MASK) == MT_MENU) diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c index 2e9d0d08d9..1940c14511 100644 --- a/apps/menus/main_menu.c +++ b/apps/menus/main_menu.c @@ -161,7 +161,7 @@ static bool show_info(void) size2 = 0; #endif - if (talk_menus_enabled()) + if (global_settings.talk_menu) { /* say whatever is reasonable, no real connection to the screen */ bool enqueue = false; /* enqueue all but the first */ diff --git a/apps/misc.c b/apps/misc.c index 3a47d2f1c9..3c6ffd3032 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -685,7 +685,7 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter) audio_close_recording(); #endif - if(talk_menus_enabled()) + if(global_settings.talk_menu) { bool enqueue = false; if(msg_id != -1) diff --git a/apps/playback.c b/apps/playback.c index c0a8c5ade0..5443ef5b24 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -677,7 +677,7 @@ void audio_play(long offset) #ifdef PLAYBACK_VOICE /* Truncate any existing voice output so we don't have spelling * etc. over the first part of the played track */ - do_shutup(); + talk_force_shutup(); #endif /* Start playback */ @@ -960,7 +960,7 @@ static void voice_stop(void) if (!voice_codec_loaded) return; - do_shutup(); + talk_force_shutup(); /* Loop until voice empties it's queue, stops and picks up on the new track; the voice thread must be stopped and waiting for messages diff --git a/apps/player/keyboard.c b/apps/player/keyboard.c index c89161c8ca..dad8fc0f55 100644 --- a/apps/player/keyboard.c +++ b/apps/player/keyboard.c @@ -74,7 +74,7 @@ static unsigned short *kbd_setupkeys(int page, int* len) /* helper function to spell a char if voice UI is enabled */ static void kbd_spellchar(char c) { - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ { unsigned char tmp[5]; /* store char to pass to talk_spell */ @@ -90,7 +90,7 @@ static void kbd_spellchar(char c) static void say_edit(void) { - if (talk_menus_enabled()) + if (global_settings.talk_menu) talk_id(VOICE_EDIT, false); } @@ -112,7 +112,7 @@ int kbd_input(char* text, int buflen) editpos = utf8length(text); - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, true); /* spell initial text */ while (!done) @@ -284,7 +284,7 @@ int kbd_input(char* text, int buflen) editpos++; } } - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, false); /* speak revised text */ break; diff --git a/apps/playlist.c b/apps/playlist.c index 025e07d8a7..ad60c84d38 100644 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -1664,7 +1664,7 @@ static void display_playlist_count(int count, const unsigned char *fmt, { static long talked_tick = 0; long id = P2ID(fmt); - if(talk_menus_enabled() && id>=0) + if(global_settings.talk_menu && id>=0) { if(final || (count && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+5*HZ)))) diff --git a/apps/plugin.c b/apps/plugin.c index c06ae257e4..bbb6d6feb2 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -468,8 +468,7 @@ static const struct plugin_api rockbox_api = { #endif &global_settings, &global_status, - talk_disable_menus, - talk_enable_menus, + talk_disable, #if CONFIG_CODEC == SWCODEC codec_load_file, get_codec_filename, diff --git a/apps/plugin.h b/apps/plugin.h index e36c99c5fd..ee58687bf0 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -112,12 +112,12 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 83 +#define PLUGIN_API_VERSION 84 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define PLUGIN_MIN_API_VERSION 83 +#define PLUGIN_MIN_API_VERSION 84 /* plugin return codes */ enum plugin_status { @@ -579,8 +579,7 @@ struct plugin_api { #endif struct user_settings* global_settings; struct system_status *global_status; - void (*talk_disable_menus)(void); - void (*talk_enable_menus)(void); + void (*talk_disable)(bool disable); #if CONFIG_CODEC == SWCODEC int (*codec_load_file)(const char* codec, struct codec_api *api); const char *(*get_codec_filename)(int cod_spec); diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 8b6d1e20bd..37ac1fa78c 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -1170,7 +1170,7 @@ static int button_loop(void) str_send_msg(&video_str, STREAM_QUIT, 0); audio_str.status = STREAM_STOPPED; } - } + } } quit: return audio_str.status; @@ -2227,6 +2227,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) api->splash(HZ*2, "No File"); return PLUGIN_ERROR; } + api->talk_disable(true); /* Initialize IRAM - stops audio and voice as well */ PLUGIN_IRAM_INIT(api) @@ -2253,6 +2254,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) audiosize -= graysize; if (grayscales < 33 || audiosize <= 0) { + rb->talk_disable(false); rb->splash(HZ, "gray buf error"); return PLUGIN_ERROR; } @@ -2261,7 +2263,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) /* Initialise our malloc buffer */ audiosize = mpeg_alloc_init(audiobuf,audiosize, LIBMPEG2BUFFER_SIZE); if (audiosize == 0) + { + rb->talk_disable(false); return PLUGIN_ERROR; + } /* Set disk pointers to NULL */ disk_buf_end = disk_buf_start = NULL; @@ -2275,13 +2280,21 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) disk_buf_start = mpeg_malloc(disk_buf_size,-1); if (disk_buf_start == NULL) + { + rb->talk_disable(false); return PLUGIN_ERROR; + } if (!init_mpabuf()) + { + rb->talk_disable(false); return PLUGIN_ERROR; - + } if (!init_pcmbuf()) + { + rb->talk_disable(false); return PLUGIN_ERROR; + } /* The remaining buffer is for use by libmpeg2 */ @@ -2290,6 +2303,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) if (in_file < 0){ DEBUGF("Could not open %s\n",(char*)parameter); + rb->talk_disable(false); return PLUGIN_ERROR; } filename = (char*)parameter; @@ -2322,6 +2336,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) switch (result) { case MPEG_START_QUIT: + rb->talk_disable(false); return 0; default: start_time = settings.resume_time; @@ -2336,7 +2351,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) /* Turn off backlight timeout */ backlight_force_on(rb); /* backlight control in lib/helper.c */ - rb->talk_disable_menus(); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); @@ -2463,8 +2477,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) n = rb->read(in_file, disk_buf_tail,bytes_to_read); if (n==0) rb->splash(30,"buffer fill error"); - } - + } bytes_to_read -= n; file_remaining -= n; @@ -2531,7 +2544,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ - rb->talk_enable_menus(); - + rb->talk_disable(false); return status; } diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c index 9c35f288ff..6c75d07a65 100644 --- a/apps/recorder/keyboard.c +++ b/apps/recorder/keyboard.c @@ -191,7 +191,7 @@ int load_kbd(unsigned char* filename) /* helper function to spell a char if voice UI is enabled */ static void kbd_spellchar(unsigned short c) { - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ { unsigned char tmp[5]; /* store char to pass to talk_spell */ @@ -208,7 +208,7 @@ static void kbd_spellchar(unsigned short c) #ifdef KBD_MODES static void say_edit(void) { - if(talk_menus_enabled()) + if(global_settings.talk_menu) talk_id(VOICE_EDIT, false); } #endif @@ -527,7 +527,7 @@ int kbd_input(char* text, int buflen) /* Initial edit position is after last character */ editpos = utf8length(text); - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, true); /* spell initial text */ @@ -832,7 +832,7 @@ int kbd_input(char* text, int buflen) kbd_spellchar(text[c]); } #if CONFIG_CODEC == SWCODEC - else if (talk_menus_enabled()) + else if (global_settings.talk_menu) pcmbuf_beep(1000, 150, 1500); #endif } @@ -877,7 +877,7 @@ int kbd_input(char* text, int buflen) kbd_spellchar(text[c]); } #if CONFIG_CODEC == SWCODEC - else if (talk_menus_enabled()) + else if (global_settings.talk_menu) pcmbuf_beep(1000, 150, 1500); #endif } @@ -1124,7 +1124,7 @@ int kbd_input(char* text, int buflen) kbd_inschar(text, buflen, &editpos, ch); } - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, false); /* speak revised text */ @@ -1153,7 +1153,7 @@ int kbd_input(char* text, int buflen) kbd_inschar(text, buflen, &editpos, ch); } - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, false); /* speak revised text */ break; @@ -1166,7 +1166,7 @@ int kbd_input(char* text, int buflen) kbd_spellchar(text[c]); } #if CONFIG_CODEC == SWCODEC - else if (talk_menus_enabled()) + else if (global_settings.talk_menu) pcmbuf_beep(1000, 150, 1500); #endif break; @@ -1180,7 +1180,7 @@ int kbd_input(char* text, int buflen) kbd_spellchar(text[c]); } #if CONFIG_CODEC == SWCODEC - else if (talk_menus_enabled()) + else if (global_settings.talk_menu) pcmbuf_beep(1000, 150, 1500); #endif break; @@ -1212,7 +1212,7 @@ int kbd_input(char* text, int buflen) param[l].hangul = false; kbd_inschar(text, buflen, &editpos, morse_alphabets[j]); - if (talk_menus_enabled()) /* voice UI? */ + if (global_settings.talk_menu) /* voice UI? */ talk_spell(text, false); /* speak revised text */ } #endif /* KBD_MORSE_INPUT */ diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index 3b706e1a6d..84207c77ab 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -889,7 +889,7 @@ bool recording_screen(bool no_source) #if CONFIG_CODEC == SWCODEC /* recording_menu gets messed up: so prevent manus talking */ - talk_disable_menus(); + talk_disable(true); /* audio_init_recording stops anything playing when it takes the audio buffer */ #else @@ -1873,8 +1873,8 @@ bool recording_screen(bool no_source) /* Go back to playback mode */ rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); - /* restore talk_menu setting */ - talk_enable_menus(); + /* restore talking */ + talk_disable(false); #else /* !SWCODEC */ audio_init_playback(); #endif /* CONFIG_CODEC == SWCODEC */ diff --git a/apps/root_menu.c b/apps/root_menu.c index 1c6c868bfc..5acaabeec6 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -160,7 +160,7 @@ static int browser(void* param) /* Display building progress */ static long talked_tick = 0; - if(talk_menus_enabled() && + if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { @@ -238,7 +238,7 @@ static int wpsscrn(void* param) (void)param; if (audio_status()) { - shutup(); + talk_shutup(); ret_val = gui_wps_show(); } else if ( global_status.resume_index != -1 ) diff --git a/apps/screens.c b/apps/screens.c index ce62911624..8cdacd706f 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -158,7 +158,7 @@ int mmc_remove_request(void) FOR_NB_SCREENS(i) screens[i].clear_display(); gui_syncsplash(1, str(LANG_REMOVE_MMC)); - if (talk_menus_enabled()) + if (global_settings.talk_menu) talk_id(LANG_REMOVE_MMC, false); while (1) @@ -822,7 +822,7 @@ static void say_time(int cursorpos, const struct tm *tm) static const int unit[] = { UNIT_HOUR, UNIT_MIN, UNIT_SEC, 0, 0, 0 }; int value = 0; - if (!talk_menus_enabled()) + if (!global_settings.talk_menu) return; switch(cursorpos) diff --git a/apps/settings.c b/apps/settings.c index 6656b84552..add2b24c75 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -949,7 +949,7 @@ const struct settings_list* find_setting(void* variable, int *id) void talk_setting(void *global_settings_variable) { const struct settings_list *setting; - if (!talk_menus_enabled()) + if (!global_settings.talk_menu) return; setting = find_setting(global_settings_variable, NULL); if (setting == NULL) diff --git a/apps/talk.c b/apps/talk.c index 47410121ba..ede0aff66b 100644 --- a/apps/talk.c +++ b/apps/talk.c @@ -80,10 +80,6 @@ const char* const file_thumbnail_ext = ".talk"; #define MAX_THUMBNAIL_BUFSIZE 0x10000 #endif -#ifndef SIMULATOR -extern bool audio_is_initialized; -#endif - /***************** Data types *****************/ struct clip_entry /* one entry of the index table */ @@ -118,8 +114,7 @@ static long size_for_thumbnail; /* leftover buffer size for it */ 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 bool force_enqueue_next; /* enqueue next utterance even if enqueue is false */ 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 */ @@ -131,16 +126,8 @@ static unsigned char* p_lastclip; /* address of latest clip, for silence add */ static unsigned long voicefile_size = 0; /* size of the loaded voice file */ static unsigned char last_lang[MAX_FILENAME+1]; /* name of last used lang file (in talk_init) */ static bool talk_initialized; /* true if talk_init has been called */ -static int talk_menu_disable; /* if non-zero, temporarily disable voice UI (not saved) */ +static int talk_temp_disable_count; /* if positive, temporarily disable voice UI (not saved) */ -/***************** Private prototypes *****************/ - -static void load_voicefile(void); -static void mp3_callback(unsigned char** start, size_t* size); -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); -int shutup(void); /* Interrupt voice, as when enqueue is false */ /***************** Private implementation *****************/ @@ -161,6 +148,50 @@ static int open_voicefile(void) } +/* fetch a clip from the voice file */ +static unsigned char* get_clip(long id, long* p_size) +{ + long clipsize; + unsigned char* clipbuf; + + if (id > VOICEONLY_DELIMITER) + { /* voice-only entries use the second part of the table */ + id -= VOICEONLY_DELIMITER + 1; + if (id >= p_voicefile->id2_max) + return NULL; /* must be newer than we have */ + id += p_voicefile->id1_max; /* table 2 is behind table 1 */ + } + else + { /* normal use of the first table */ + if (id >= p_voicefile->id1_max) + return NULL; /* must be newer than we have */ + } + + clipsize = p_voicefile->index[id].size; + if (clipsize == 0) /* clip not included in voicefile */ + return NULL; + clipbuf = (unsigned char *) p_voicefile + p_voicefile->index[id].offset; + +#ifdef HAVE_MMC /* dynamic loading, on demand */ + if (!(clipsize & LOADED_MASK)) + { /* clip used for the first time, needs loading */ + lseek(filehandle, p_voicefile->index[id].offset, SEEK_SET); + if (read(filehandle, clipbuf, clipsize) != clipsize) + return NULL; /* read error */ + + p_voicefile->index[id].size |= LOADED_MASK; /* mark as loaded */ + } + else + { /* clip is in memory already */ + clipsize &= ~LOADED_MASK; /* without the extra bit gives true size */ + } +#endif + + *p_size = clipsize; + return clipbuf; +} + + /* load the voice file into the mp3 buffer */ static void load_voicefile(void) { @@ -252,7 +283,7 @@ load_err: /* Are more voice clips queued and waiting? */ bool is_voice_queued() { - return !!QUEUE_LEVEL; + return (QUEUE_LEVEL != 0); } @@ -280,7 +311,7 @@ static void mp3_callback(unsigned char** start, size_t* size) re_check: - if (QUEUE_LEVEL) /* queue is not empty? */ + if (QUEUE_LEVEL != 0) /* queue is not empty? */ { /* start next clip */ #if CONFIG_CODEC != SWCODEC sent = MIN(queue[queue_read].len, 0xFFFF); @@ -309,26 +340,22 @@ re_check: } } +/***************** Public routines *****************/ + /* stop the playback and the pending clips */ -int do_shutup(void) +void talk_force_shutup(void) { + /* Most of this is MAS only */ #if CONFIG_CODEC != SWCODEC unsigned char* pos; unsigned char* search; unsigned char* end; -#endif - if (QUEUE_LEVEL == 0) /* has ended anyway */ - { -#if CONFIG_CODEC == SWCODEC - mp3_play_stop(); -#endif - return 0; - } -#if CONFIG_CODEC != SWCODEC + return; + #if CONFIG_CPU == SH7034 CHCR3 &= ~0x0001; /* disable the DMA (and therefore the interrupt also) */ -#endif +#endif /* CONFIG_CPU == SH7034 */ /* search next frame boundary and continue up to there */ pos = search = mp3_get_pos(); end = queue[queue_read].buf + queue[queue_read].len; @@ -362,41 +389,38 @@ int do_shutup(void) #if CONFIG_CPU == SH7034 DTCR3 = sent; /* let the DMA finish this frame */ CHCR3 |= 0x0001; /* re-enable DMA */ -#endif - return 0; +#endif /* CONFIG_CPU == SH7034 */ + return; } } -#endif +#endif /* CONFIG_CODEC != SWCODEC */ - /* nothing to do, was frame boundary or not our clip */ + /* Either SWCODEC, or MAS had nothing to do (was frame boundary or not our clip) */ mp3_play_stop(); - queue_write = queue_read = 0; /* reset the queue */ - - return 0; + return; } /* Shutup the voice, except if force_enqueue_next is set. */ -int shutup(void) +void talk_shutup(void) { if (!force_enqueue_next) - return do_shutup(); - return 0; + talk_force_shutup(); } /* schedule a clip, at the end or discard the existing queue */ -static int queue_clip(unsigned char* buf, long size, bool enqueue) +static void queue_clip(unsigned char* buf, long size, bool enqueue) { int queue_level; if (!enqueue) - shutup(); /* cut off all the pending stuff */ + talk_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 */ + return; /* safety check */ #if CONFIG_CPU == SH7034 /* disable the DMA temporarily, to be safe of race condition */ CHCR3 &= ~0x0001; @@ -431,50 +455,7 @@ static int queue_clip(unsigned char* buf, long size, bool enqueue) #endif } - return 0; -} - -/* fetch a clip from the voice file */ -static unsigned char* get_clip(long id, long* p_size) -{ - long clipsize; - unsigned char* clipbuf; - - if (id > VOICEONLY_DELIMITER) - { /* voice-only entries use the second part of the table */ - id -= VOICEONLY_DELIMITER + 1; - if (id >= p_voicefile->id2_max) - return NULL; /* must be newer than we have */ - id += p_voicefile->id1_max; /* table 2 is behind table 1 */ - } - else - { /* normal use of the first table */ - if (id >= p_voicefile->id1_max) - return NULL; /* must be newer than we have */ - } - - clipsize = p_voicefile->index[id].size; - if (clipsize == 0) /* clip not included in voicefile */ - return NULL; - clipbuf = (unsigned char *) p_voicefile + p_voicefile->index[id].offset; - -#ifdef HAVE_MMC /* dynamic loading, on demand */ - if (!(clipsize & LOADED_MASK)) - { /* clip used for the first time, needs loading */ - lseek(filehandle, p_voicefile->index[id].offset, SEEK_SET); - if (read(filehandle, clipbuf, clipsize) != clipsize) - return NULL; /* read error */ - - p_voicefile->index[id].size |= LOADED_MASK; /* mark as loaded */ - } - else - { /* clip is in memory already */ - clipsize &= ~LOADED_MASK; /* without the extra bit gives true size */ - } -#endif - - *p_size = clipsize; - return clipbuf; + return; } @@ -500,11 +481,12 @@ static void reset_state(void) p_silence = NULL; /* pause clip not accessible */ } + /***************** Public implementation *****************/ void talk_init(void) { - talk_menu_disable = 0; + talk_temp_disable_count = 0; if (talk_initialized && !strcasecmp(last_lang, global_settings.lang_file)) { /* not a new file, nothing to do */ @@ -558,7 +540,7 @@ int talk_get_bufsize(void) } /* somebody else claims the mp3 buffer, e.g. for regular play/record */ -int talk_buffer_steal(void) +void talk_buffer_steal(void) { #if CONFIG_CODEC != SWCODEC mp3_play_stop(); @@ -570,9 +552,7 @@ int talk_buffer_steal(void) filehandle = -1; } #endif - reset_state(); - - return 0; + reset_state();; } @@ -583,6 +563,8 @@ int talk_id(long id, bool enqueue) unsigned char* clipbuf; int unit; + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ #if CONFIG_CODEC != SWCODEC if (audio_status()) /* busy, buffer in use */ return -1; @@ -644,6 +626,8 @@ int talk_file(const char* filename, bool enqueue) int size; struct mp3entry info; + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ #if CONFIG_CODEC != SWCODEC if (audio_status()) /* busy, buffer in use */ return -1; @@ -689,13 +673,15 @@ int talk_number(long n, bool enqueue) int level = 2; /* mille count */ long mil = 1000000000; /* highest possible "-illion" */ + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ #if CONFIG_CODEC != SWCODEC if (audio_status()) /* busy, buffer in use */ return -1; #endif if (!enqueue) - shutup(); /* cut off all the pending stuff */ + talk_shutup(); /* cut off all the pending stuff */ if (n==0) { /* special case */ @@ -785,6 +771,8 @@ int talk_value(long n, int unit, bool enqueue) = VOICE_PM_UNITS_PER_TICK, }; + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ #if CONFIG_CODEC != SWCODEC if (audio_status()) /* busy, buffer in use */ return -1; @@ -819,13 +807,15 @@ int talk_spell(const char* spell, bool enqueue) { char c; /* currently processed char */ + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ #if CONFIG_CODEC != SWCODEC if (audio_status()) /* busy, buffer in use */ return -1; #endif if (!enqueue) - shutup(); /* cut off all the pending stuff */ + talk_shutup(); /* cut off all the pending stuff */ while ((c = *spell++) != '\0') { @@ -849,26 +839,18 @@ int talk_spell(const char* spell, bool enqueue) return 0; } -bool talk_menus_enabled(void) +void talk_disable(bool disable) { - return (global_settings.talk_menu && talk_menu_disable == 0); -} - - -void talk_disable_menus(void) -{ - talk_menu_disable++; -} - -void talk_enable_menus(void) -{ - talk_menu_disable--; + if (disable) + talk_temp_disable_count++; + else + talk_temp_disable_count--; } #if CONFIG_RTC void talk_date_time(struct tm *tm, bool speak_current_time_string) { - if(talk_menus_enabled ()) + if(global_settings.talk_menu) { if(speak_current_time_string) talk_id(VOICE_CURRENT_TIME, true); diff --git a/apps/talk.h b/apps/talk.h index e25a11c702..a939c1f3d1 100644 --- a/apps/talk.h +++ b/apps/talk.h @@ -66,19 +66,16 @@ void talk_init(void); bool talk_voice_required(void); /* returns true if voice codec required */ #endif 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 */ +void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ 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 */ -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_enable_menus(void); /* re-enable voice menus */ -int do_shutup(void); /* kill voice unconditionally */ -int shutup(void); /* Interrupt voice, as when enqueue is false */ +void talk_disable(bool disable); /* temporarily disable (or re-enable) talking (temporarily, not persisted) */ +void talk_force_shutup(void); /* kill voice unconditionally */ +void talk_shutup(void); /* Interrupt voice, as when enqueue is false */ #if CONFIG_RTC /* this is in talk.c which isnt compiled for hwcodec simulator */ @@ -94,12 +91,14 @@ void talk_date_time(struct tm *time, bool speak_current_time_string); /* We don't build talk.c for hwcodec sims so we need to define these as empty */ #if defined(SIMULATOR) && !(CONFIG_CODEC == SWCODEC) +#define talk_init(...) +#define talk_buffer_steal(...) +#define talk_shutup(...) #define talk_force_enqueue_next(...) #define talk_idarray(...) #define talk_ids(...) #define cond_talk_ids(...) #define cond_talk_ids_fq(...) -#define shutup(...) #else /* Enqueue next utterance even if enqueue parameter is false: don't @@ -116,18 +115,18 @@ int talk_idarray(long *idarray, bool 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()) \ + 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 (talk_menus_enabled() \ + 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 (talk_menus_enabled()) { \ + if (global_settings.talk_menu) { \ talk_ids(false, ids); \ talk_force_enqueue_next(); \ } \ diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c index 840b1421c0..00716b39c6 100644 --- a/uisimulator/common/stubs.c +++ b/uisimulator/common/stubs.c @@ -302,14 +302,6 @@ void button_set_flip(bool yesno) } #if CONFIG_CODEC != SWCODEC -void talk_init(void) -{ -} - -int talk_buffer_steal(void) -{ - return 0; -} int talk_id(int id, bool enqueue) { @@ -347,17 +339,9 @@ int talk_spell(char* spell, bool enqueue) return 0; } -bool talk_menus_enabled(void) -{ - return false; -} - -void talk_enable_menus(void) -{ -} - -void talk_disable_menus(void) +void talk_disable(bool disable) { + (void) disable; } const char* const dir_thumbnail_name = "_dirname.talk";