summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2020-09-20 13:29:02 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2020-09-20 16:08:49 -0400
commit2ffe87902dc72b4c26032c94e8250ff92d2888dc (patch)
tree9a6cf73d37a5a5e3f93813b44720c1bd5604ddd9
parentc528c01312d85e2d177bcc05ce82a29c97b803cc (diff)
downloadrockbox-2ffe879.tar.gz
rockbox-2ffe879.zip
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
-rw-r--r--apps/lang/InvalidVoice_english.talkbin0 -> 2707 bytes
-rw-r--r--apps/lang/SOURCES1
-rw-r--r--apps/lang/lang.make6
-rw-r--r--apps/main.c3
-rw-r--r--apps/talk.c65
-rw-r--r--apps/talk.h2
-rw-r--r--apps/voice_thread.c20
-rw-r--r--apps/voice_thread.h2
-rwxr-xr-xtools/buildzip.pl3
9 files changed, 90 insertions, 12 deletions
diff --git a/apps/lang/InvalidVoice_english.talk b/apps/lang/InvalidVoice_english.talk
new file mode 100644
index 0000000000..e40f227c33
--- /dev/null
+++ b/apps/lang/InvalidVoice_english.talk
Binary files differ
diff --git a/apps/lang/SOURCES b/apps/lang/SOURCES
index 276d1bff1c..3faa5d5add 100644
--- a/apps/lang/SOURCES
+++ b/apps/lang/SOURCES
@@ -46,3 +46,4 @@ hindi.lang
japanese.lang
korean.lang
thai.lang
+InvalidVoice_english.talk
diff --git a/apps/lang/lang.make b/apps/lang/lang.make
index 807ac0f53f..73b6dce3de 100644
--- a/apps/lang/lang.make
+++ b/apps/lang/lang.make
@@ -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)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)/,,$@))
$(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
diff --git a/apps/main.c b/apps/main.c
index e1eccc0fa9..3c549a8e63 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -372,7 +372,7 @@ static void init(void)
scrobbler_init();
audio_init();
-
+ talk_announce_voice_invalid(); /* notify user w/ voice prompt if voice file invalid */
settings_apply_skins();
}
@@ -631,6 +631,7 @@ static void init(void)
CHART(">audio_init");
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() */
cpu_boost(false);
diff --git a/apps/talk.c b/apps/talk.c
index 5d292b05d1..29f1331983 100644
--- a/apps/talk.c
+++ b/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)
{
- size_t alloc_size;
/* just allocate, populate on an as-needed basis later */
talk_handle = core_alloc_ex("voice data", max_size, &talk_ops);
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);
- /* 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;
alloc_err:
talk_status = TALK_STATUS_ERR_ALLOC;
- index_handle = core_free(index_handle);
+ if (index_handle > 0)
+ index_handle = core_free(index_handle);
return false;
}
@@ -608,6 +603,7 @@ static bool load_voicefile_data(int fd)
* other allocs succeed without disabling voice which would require
* reloading the voice from disk (as we do not shrink our buffer when
* 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));
if (UNLIKELY(cap < 0))
{
@@ -625,6 +621,11 @@ static bool load_voicefile_data(int fd)
if (!create_clip_buffer(voicebuf_size))
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);
/* make sure to have the silence clip, if available return value can
* 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)
{
char* p_lang = DEFAULT_VOICE_LANG; /* default */
diff --git a/apps/talk.h b/apps/talk.h
index bfd8e496af..b4aa344916 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -186,6 +186,8 @@ struct talk_debug_data {
enum talk_status status;
};
+void talk_announce_voice_invalid(void);
+
bool talk_get_debug_data(struct talk_debug_data *data);
#endif /* __TALK_H__ */
diff --git a/apps/voice_thread.c b/apps/voice_thread.c
index 171902d10f..08c7fd6b0b 100644
--- a/apps/voice_thread.c
+++ b/apps/voice_thread.c
@@ -106,6 +106,7 @@ enum voice_state
VOICE_STATE_MESSAGE = 0,
VOICE_STATE_DECODE,
VOICE_STATE_BUFFER_INSERT,
+ VOICE_STATE_QUIT,
};
/* 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_STOP, /* Stop current clip */
+ Q_VOICE_KILL, /* Kill voice thread till restart*/
};
/* 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);
return VOICE_STATE_DECODE;
-
+ case Q_VOICE_KILL:
+ queue_delete(&voice_queue);
+ return VOICE_STATE_QUIT;
case SYS_TIMEOUT:
if (voice_unplayed_frames())
{
@@ -512,7 +516,7 @@ static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
}
/* Voice thread entrypoint */
-static void NORETURN_ATTR voice_thread(void)
+static void voice_thread(void)
{
struct voice_thread_data td;
enum voice_state state = VOICE_STATE_MESSAGE;
@@ -532,8 +536,20 @@ static void NORETURN_ATTR voice_thread(void)
case VOICE_STATE_BUFFER_INSERT:
state = voice_buffer_insert(&td);
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 */
diff --git a/apps/voice_thread.h b/apps/voice_thread.h
index d662aaee33..81b11eea37 100644
--- a/apps/voice_thread.h
+++ b/apps/voice_thread.h
@@ -36,6 +36,8 @@ void voice_wait(void);
void voice_stop(void);
void voice_thread_init(void);
+void voice_thread_kill(void);
+
#ifdef HAVE_PRIORITY_SCHEDULING
void voice_thread_set_priority(int priority);
#endif
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 4b15771333..f53f16a674 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -614,8 +614,9 @@ sub buildzip {
copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt");
# 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/*.talk', "$temp_dir/langs/");
# copy the .lua files
glob_mkdir("$temp_dir/rocks/viewers/lua/");