Add Invalid Voice Announcement to the voice system FS#13216
When a voice file is invalid or fails to load the voice system splash a message 'Invalid Voice' Now we supply a single voice file (currently only english is used) the support for other languages is in but I haven't set it up to look for anything but InvalidVoice_english.talk Also adds a one time kill voice thread function ie. it doesn't allow re-init after killing the voice thread & queue Change-Id: I7b43f340c3cc65c65110190f0e0075b31218a7ac
This commit is contained in:
parent
c528c01312
commit
2ffe87902d
9 changed files with 90 additions and 12 deletions
BIN
apps/lang/InvalidVoice_english.talk
Normal file
BIN
apps/lang/InvalidVoice_english.talk
Normal file
Binary file not shown.
|
@ -46,3 +46,4 @@ hindi.lang
|
||||||
japanese.lang
|
japanese.lang
|
||||||
korean.lang
|
korean.lang
|
||||||
thai.lang
|
thai.lang
|
||||||
|
InvalidVoice_english.talk
|
||||||
|
|
|
@ -54,6 +54,10 @@ $(BUILDDIR)/%.lng $(BUILDDIR)/%.vstrings: $(ROOTDIR)/%.lang $(BUILDDIR)/apps/gen
|
||||||
$(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/lang/$(ENGLISH).lang -t=$(MODELNAME):`cat $(BUILDDIR)/apps/genlang-features` -i=$(TARGET_ID) -b=$*.lng -c=$*.vstrings $@.tmp
|
$(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/lang/$(ENGLISH).lang -t=$(MODELNAME):`cat $(BUILDDIR)/apps/genlang-features` -i=$(TARGET_ID) -b=$*.lng -c=$*.vstrings $@.tmp
|
||||||
$(SILENT)rm -f $@.tmp
|
$(SILENT)rm -f $@.tmp
|
||||||
|
|
||||||
$(BUILDDIR)/apps/lang/voicestrings.zip: $(VOICEOBJ)
|
$(BUILDDIR)/apps/lang/voicestrings.zip: $(VOICEOBJ) $(wildcard $(BUILDDIR)/apps/lang/*.talk)
|
||||||
$(call PRINTS,ZIP $(subst $(BUILDDIR)/,,$@))
|
$(call PRINTS,ZIP $(subst $(BUILDDIR)/,,$@))
|
||||||
$(SILENT)zip -9 -q $@ $(subst $(BUILDDIR)/,,$^)
|
$(SILENT)zip -9 -q $@ $(subst $(BUILDDIR)/,,$^)
|
||||||
|
|
||||||
|
#copy any included talk files to the /lang directory
|
||||||
|
$(BUILDDIR)/apps/lang/%.talk: $(ROOTDIR)/apps/lang/%.talk
|
||||||
|
$(call PRINTS,CP $(subst $(ROOTDIR)/,,$<))cp $< $(BUILDDIR)/apps/lang
|
||||||
|
|
|
@ -372,7 +372,7 @@ static void init(void)
|
||||||
scrobbler_init();
|
scrobbler_init();
|
||||||
|
|
||||||
audio_init();
|
audio_init();
|
||||||
|
talk_announce_voice_invalid(); /* notify user w/ voice prompt if voice file invalid */
|
||||||
settings_apply_skins();
|
settings_apply_skins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,6 +631,7 @@ static void init(void)
|
||||||
CHART(">audio_init");
|
CHART(">audio_init");
|
||||||
audio_init();
|
audio_init();
|
||||||
CHART("<audio_init");
|
CHART("<audio_init");
|
||||||
|
talk_announce_voice_invalid(); /* notify user w/ voice prompt if voice file invalid */
|
||||||
|
|
||||||
/* runtime database has to be initialized after audio_init() */
|
/* runtime database has to be initialized after audio_init() */
|
||||||
cpu_boost(false);
|
cpu_boost(false);
|
||||||
|
|
65
apps/talk.c
65
apps/talk.c
|
@ -535,7 +535,6 @@ static bool load_header(int fd, struct voicefile_header *hdr)
|
||||||
|
|
||||||
static bool create_clip_buffer(size_t max_size)
|
static bool create_clip_buffer(size_t max_size)
|
||||||
{
|
{
|
||||||
size_t alloc_size;
|
|
||||||
/* just allocate, populate on an as-needed basis later */
|
/* just allocate, populate on an as-needed basis later */
|
||||||
talk_handle = core_alloc_ex("voice data", max_size, &talk_ops);
|
talk_handle = core_alloc_ex("voice data", max_size, &talk_ops);
|
||||||
if (talk_handle < 0)
|
if (talk_handle < 0)
|
||||||
|
@ -543,16 +542,12 @@ static bool create_clip_buffer(size_t max_size)
|
||||||
|
|
||||||
buflib_init(&clip_ctx, core_get_data(talk_handle), max_size);
|
buflib_init(&clip_ctx, core_get_data(talk_handle), max_size);
|
||||||
|
|
||||||
/* the first alloc is the clip metadata table */
|
|
||||||
alloc_size = max_clips * sizeof(struct clip_cache_metadata);
|
|
||||||
metadata_table_handle = buflib_alloc(&clip_ctx, alloc_size);
|
|
||||||
memset(buflib_get_data(&clip_ctx, metadata_table_handle), 0, alloc_size);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
alloc_err:
|
alloc_err:
|
||||||
talk_status = TALK_STATUS_ERR_ALLOC;
|
talk_status = TALK_STATUS_ERR_ALLOC;
|
||||||
index_handle = core_free(index_handle);
|
if (index_handle > 0)
|
||||||
|
index_handle = core_free(index_handle);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,6 +603,7 @@ static bool load_voicefile_data(int fd)
|
||||||
* other allocs succeed without disabling voice which would require
|
* other allocs succeed without disabling voice which would require
|
||||||
* reloading the voice from disk (as we do not shrink our buffer when
|
* reloading the voice from disk (as we do not shrink our buffer when
|
||||||
* other code attempts new allocs these would fail) */
|
* other code attempts new allocs these would fail) */
|
||||||
|
size_t metadata_alloc_size;
|
||||||
ssize_t cap = MIN(MAX_CLIP_BUFFER_SIZE, audio_buffer_available() - (64<<10));
|
ssize_t cap = MIN(MAX_CLIP_BUFFER_SIZE, audio_buffer_available() - (64<<10));
|
||||||
if (UNLIKELY(cap < 0))
|
if (UNLIKELY(cap < 0))
|
||||||
{
|
{
|
||||||
|
@ -625,6 +621,11 @@ static bool load_voicefile_data(int fd)
|
||||||
if (!create_clip_buffer(voicebuf_size))
|
if (!create_clip_buffer(voicebuf_size))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* the first alloc is the clip metadata table */
|
||||||
|
metadata_alloc_size = max_clips * sizeof(struct clip_cache_metadata);
|
||||||
|
metadata_table_handle = buflib_alloc(&clip_ctx, metadata_alloc_size);
|
||||||
|
memset(buflib_get_data(&clip_ctx, metadata_table_handle), 0, metadata_alloc_size);
|
||||||
|
|
||||||
load_initial_clips(fd);
|
load_initial_clips(fd);
|
||||||
/* make sure to have the silence clip, if available return value can
|
/* make sure to have the silence clip, if available return value can
|
||||||
* be cached globally even for TALK_PROGRESSIVE_LOAD because the
|
* be cached globally even for TALK_PROGRESSIVE_LOAD because the
|
||||||
|
@ -1499,6 +1500,56 @@ void talk_time(const struct tm *tm, bool enqueue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void talk_announce_voice_invalid(void)
|
||||||
|
{
|
||||||
|
int voice_fd;
|
||||||
|
int voice_sz;
|
||||||
|
int buf_handle;
|
||||||
|
struct queue_entry qe;
|
||||||
|
|
||||||
|
const char talkfile[] =
|
||||||
|
LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
|
||||||
|
|
||||||
|
if (global_settings.talk_menu && talk_status != TALK_STATUS_OK && !button_hold())
|
||||||
|
{
|
||||||
|
talk_temp_disable_count = 0xFF; /* don't let anyone else use voice sys */
|
||||||
|
|
||||||
|
voice_fd = open(talkfile, O_RDONLY);
|
||||||
|
if (voice_fd < 0)
|
||||||
|
return; /* can't open */
|
||||||
|
|
||||||
|
voice_sz= lseek(voice_fd, 0, SEEK_END);
|
||||||
|
if (voice_sz == 0 || voice_sz > (64<<10))
|
||||||
|
return; /* nothing here or too big */
|
||||||
|
|
||||||
|
lseek(voice_fd, 0, SEEK_SET);
|
||||||
|
/* add a bit extra for buflib overhead (2K) */
|
||||||
|
if (!create_clip_buffer(ALIGN_UP(voice_sz, sizeof(long)) + (2<<10)))
|
||||||
|
return;
|
||||||
|
mutex_lock(&read_buffer_mutex);
|
||||||
|
buf_handle = buflib_alloc(&clip_ctx, ALIGN_UP(voice_sz, sizeof(long)));
|
||||||
|
|
||||||
|
if (buf_handle < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (read_to_handle_ex(voice_fd, &clip_ctx, buf_handle, 0, voice_sz) > 0)
|
||||||
|
{
|
||||||
|
voice_thread_init();
|
||||||
|
qe.handle = buf_handle;
|
||||||
|
qe.length = qe.remaining = voice_sz;
|
||||||
|
queue_clip(&qe, false);
|
||||||
|
voice_wait();
|
||||||
|
voice_thread_kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&read_buffer_mutex);
|
||||||
|
close(voice_fd);
|
||||||
|
|
||||||
|
buf_handle = buflib_free(&clip_ctx, buf_handle);
|
||||||
|
talk_handle = core_free(talk_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool talk_get_debug_data(struct talk_debug_data *data)
|
bool talk_get_debug_data(struct talk_debug_data *data)
|
||||||
{
|
{
|
||||||
char* p_lang = DEFAULT_VOICE_LANG; /* default */
|
char* p_lang = DEFAULT_VOICE_LANG; /* default */
|
||||||
|
|
|
@ -186,6 +186,8 @@ struct talk_debug_data {
|
||||||
enum talk_status status;
|
enum talk_status status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void talk_announce_voice_invalid(void);
|
||||||
|
|
||||||
bool talk_get_debug_data(struct talk_debug_data *data);
|
bool talk_get_debug_data(struct talk_debug_data *data);
|
||||||
|
|
||||||
#endif /* __TALK_H__ */
|
#endif /* __TALK_H__ */
|
||||||
|
|
|
@ -106,6 +106,7 @@ enum voice_state
|
||||||
VOICE_STATE_MESSAGE = 0,
|
VOICE_STATE_MESSAGE = 0,
|
||||||
VOICE_STATE_DECODE,
|
VOICE_STATE_DECODE,
|
||||||
VOICE_STATE_BUFFER_INSERT,
|
VOICE_STATE_BUFFER_INSERT,
|
||||||
|
VOICE_STATE_QUIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A delay to not bring audio back to normal level too soon */
|
/* A delay to not bring audio back to normal level too soon */
|
||||||
|
@ -115,6 +116,7 @@ enum voice_thread_messages
|
||||||
{
|
{
|
||||||
Q_VOICE_PLAY = 0, /* Play a clip */
|
Q_VOICE_PLAY = 0, /* Play a clip */
|
||||||
Q_VOICE_STOP, /* Stop current clip */
|
Q_VOICE_STOP, /* Stop current clip */
|
||||||
|
Q_VOICE_KILL, /* Kill voice thread till restart*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Structure to store clip data callback info */
|
/* Structure to store clip data callback info */
|
||||||
|
@ -383,7 +385,9 @@ static enum voice_state voice_message(struct voice_thread_data *td)
|
||||||
speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);
|
speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);
|
||||||
|
|
||||||
return VOICE_STATE_DECODE;
|
return VOICE_STATE_DECODE;
|
||||||
|
case Q_VOICE_KILL:
|
||||||
|
queue_delete(&voice_queue);
|
||||||
|
return VOICE_STATE_QUIT;
|
||||||
case SYS_TIMEOUT:
|
case SYS_TIMEOUT:
|
||||||
if (voice_unplayed_frames())
|
if (voice_unplayed_frames())
|
||||||
{
|
{
|
||||||
|
@ -512,7 +516,7 @@ static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Voice thread entrypoint */
|
/* Voice thread entrypoint */
|
||||||
static void NORETURN_ATTR voice_thread(void)
|
static void voice_thread(void)
|
||||||
{
|
{
|
||||||
struct voice_thread_data td;
|
struct voice_thread_data td;
|
||||||
enum voice_state state = VOICE_STATE_MESSAGE;
|
enum voice_state state = VOICE_STATE_MESSAGE;
|
||||||
|
@ -532,8 +536,20 @@ static void NORETURN_ATTR voice_thread(void)
|
||||||
case VOICE_STATE_BUFFER_INSERT:
|
case VOICE_STATE_BUFFER_INSERT:
|
||||||
state = voice_buffer_insert(&td);
|
state = voice_buffer_insert(&td);
|
||||||
break;
|
break;
|
||||||
|
case VOICE_STATE_QUIT:
|
||||||
|
logf("Exiting voice thread");
|
||||||
|
core_free(voice_buf_hid);
|
||||||
|
voice_buf_hid = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* kill voice thread and dont allow re-init*/
|
||||||
|
void voice_thread_kill(void)
|
||||||
|
{
|
||||||
|
queue_send(&voice_queue, Q_VOICE_KILL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize buffers, all synchronization objects and create the thread */
|
/* Initialize buffers, all synchronization objects and create the thread */
|
||||||
|
|
|
@ -36,6 +36,8 @@ void voice_wait(void);
|
||||||
void voice_stop(void);
|
void voice_stop(void);
|
||||||
|
|
||||||
void voice_thread_init(void);
|
void voice_thread_init(void);
|
||||||
|
void voice_thread_kill(void);
|
||||||
|
|
||||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||||
void voice_thread_set_priority(int priority);
|
void voice_thread_set_priority(int priority);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -614,8 +614,9 @@ sub buildzip {
|
||||||
copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt");
|
copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt");
|
||||||
|
|
||||||
# copy the already built lng files
|
# copy the already built lng files
|
||||||
glob_copy('apps/lang/*lng', "$temp_dir/langs/");
|
glob_copy('apps/lang/*.lng', "$temp_dir/langs/");
|
||||||
glob_copy('apps/lang/*.zip', "$temp_dir/langs/");
|
glob_copy('apps/lang/*.zip', "$temp_dir/langs/");
|
||||||
|
glob_copy('apps/lang/*.talk', "$temp_dir/langs/");
|
||||||
|
|
||||||
# copy the .lua files
|
# copy the .lua files
|
||||||
glob_mkdir("$temp_dir/rocks/viewers/lua/");
|
glob_mkdir("$temp_dir/rocks/viewers/lua/");
|
||||||
|
|
Loading…
Reference in a new issue