summaryrefslogtreecommitdiffstats
path: root/apps/talk.c
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 /apps/talk.c
parentc528c01312d85e2d177bcc05ce82a29c97b803cc (diff)
downloadrockbox-2ffe87902d.tar.gz
rockbox-2ffe87902d.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
Diffstat (limited to 'apps/talk.c')
-rw-r--r--apps/talk.c65
1 files changed, 58 insertions, 7 deletions
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 */