summaryrefslogtreecommitdiff
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-2ffe87902dc72b4c26032c94e8250ff92d2888dc.tar.gz
rockbox-2ffe87902dc72b4c26032c94e8250ff92d2888dc.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
46japanese.lang 46japanese.lang
47korean.lang 47korean.lang
48thai.lang 48thai.lang
49InvalidVoice_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
54 $(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/lang/$(ENGLISH).lang -t=$(MODELNAME):`cat $(BUILDDIR)/apps/genlang-features` -i=$(TARGET_ID) -b=$*.lng -c=$*.vstrings $@.tmp 54 $(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/lang/$(ENGLISH).lang -t=$(MODELNAME):`cat $(BUILDDIR)/apps/genlang-features` -i=$(TARGET_ID) -b=$*.lng -c=$*.vstrings $@.tmp
55 $(SILENT)rm -f $@.tmp 55 $(SILENT)rm -f $@.tmp
56 56
57$(BUILDDIR)/apps/lang/voicestrings.zip: $(VOICEOBJ) 57$(BUILDDIR)/apps/lang/voicestrings.zip: $(VOICEOBJ) $(wildcard $(BUILDDIR)/apps/lang/*.talk)
58 $(call PRINTS,ZIP $(subst $(BUILDDIR)/,,$@)) 58 $(call PRINTS,ZIP $(subst $(BUILDDIR)/,,$@))
59 $(SILENT)zip -9 -q $@ $(subst $(BUILDDIR)/,,$^) 59 $(SILENT)zip -9 -q $@ $(subst $(BUILDDIR)/,,$^)
60
61#copy any included talk files to the /lang directory
62$(BUILDDIR)/apps/lang/%.talk: $(ROOTDIR)/apps/lang/%.talk
63 $(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)
372 scrobbler_init(); 372 scrobbler_init();
373 373
374 audio_init(); 374 audio_init();
375 375 talk_announce_voice_invalid(); /* notify user w/ voice prompt if voice file invalid */
376 settings_apply_skins(); 376 settings_apply_skins();
377} 377}
378 378
@@ -631,6 +631,7 @@ static void init(void)
631 CHART(">audio_init"); 631 CHART(">audio_init");
632 audio_init(); 632 audio_init();
633 CHART("<audio_init"); 633 CHART("<audio_init");
634 talk_announce_voice_invalid(); /* notify user w/ voice prompt if voice file invalid */
634 635
635 /* runtime database has to be initialized after audio_init() */ 636 /* runtime database has to be initialized after audio_init() */
636 cpu_boost(false); 637 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)
535 535
536static bool create_clip_buffer(size_t max_size) 536static bool create_clip_buffer(size_t max_size)
537{ 537{
538 size_t alloc_size;
539 /* just allocate, populate on an as-needed basis later */ 538 /* just allocate, populate on an as-needed basis later */
540 talk_handle = core_alloc_ex("voice data", max_size, &talk_ops); 539 talk_handle = core_alloc_ex("voice data", max_size, &talk_ops);
541 if (talk_handle < 0) 540 if (talk_handle < 0)
@@ -543,16 +542,12 @@ static bool create_clip_buffer(size_t max_size)
543 542
544 buflib_init(&clip_ctx, core_get_data(talk_handle), max_size); 543 buflib_init(&clip_ctx, core_get_data(talk_handle), max_size);
545 544
546 /* the first alloc is the clip metadata table */
547 alloc_size = max_clips * sizeof(struct clip_cache_metadata);
548 metadata_table_handle = buflib_alloc(&clip_ctx, alloc_size);
549 memset(buflib_get_data(&clip_ctx, metadata_table_handle), 0, alloc_size);
550
551 return true; 545 return true;
552 546
553alloc_err: 547alloc_err:
554 talk_status = TALK_STATUS_ERR_ALLOC; 548 talk_status = TALK_STATUS_ERR_ALLOC;
555 index_handle = core_free(index_handle); 549 if (index_handle > 0)
550 index_handle = core_free(index_handle);
556 return false; 551 return false;
557} 552}
558 553
@@ -608,6 +603,7 @@ static bool load_voicefile_data(int fd)
608 * other allocs succeed without disabling voice which would require 603 * other allocs succeed without disabling voice which would require
609 * reloading the voice from disk (as we do not shrink our buffer when 604 * reloading the voice from disk (as we do not shrink our buffer when
610 * other code attempts new allocs these would fail) */ 605 * other code attempts new allocs these would fail) */
606 size_t metadata_alloc_size;
611 ssize_t cap = MIN(MAX_CLIP_BUFFER_SIZE, audio_buffer_available() - (64<<10)); 607 ssize_t cap = MIN(MAX_CLIP_BUFFER_SIZE, audio_buffer_available() - (64<<10));
612 if (UNLIKELY(cap < 0)) 608 if (UNLIKELY(cap < 0))
613 { 609 {
@@ -625,6 +621,11 @@ static bool load_voicefile_data(int fd)
625 if (!create_clip_buffer(voicebuf_size)) 621 if (!create_clip_buffer(voicebuf_size))
626 return false; 622 return false;
627 623
624 /* the first alloc is the clip metadata table */
625 metadata_alloc_size = max_clips * sizeof(struct clip_cache_metadata);
626 metadata_table_handle = buflib_alloc(&clip_ctx, metadata_alloc_size);
627 memset(buflib_get_data(&clip_ctx, metadata_table_handle), 0, metadata_alloc_size);
628
628 load_initial_clips(fd); 629 load_initial_clips(fd);
629 /* make sure to have the silence clip, if available return value can 630 /* make sure to have the silence clip, if available return value can
630 * be cached globally even for TALK_PROGRESSIVE_LOAD because the 631 * be cached globally even for TALK_PROGRESSIVE_LOAD because the
@@ -1499,6 +1500,56 @@ void talk_time(const struct tm *tm, bool enqueue)
1499 } 1500 }
1500} 1501}
1501 1502
1503void talk_announce_voice_invalid(void)
1504{
1505 int voice_fd;
1506 int voice_sz;
1507 int buf_handle;
1508 struct queue_entry qe;
1509
1510 const char talkfile[] =
1511 LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
1512
1513 if (global_settings.talk_menu && talk_status != TALK_STATUS_OK && !button_hold())
1514 {
1515 talk_temp_disable_count = 0xFF; /* don't let anyone else use voice sys */
1516
1517 voice_fd = open(talkfile, O_RDONLY);
1518 if (voice_fd < 0)
1519 return; /* can't open */
1520
1521 voice_sz= lseek(voice_fd, 0, SEEK_END);
1522 if (voice_sz == 0 || voice_sz > (64<<10))
1523 return; /* nothing here or too big */
1524
1525 lseek(voice_fd, 0, SEEK_SET);
1526 /* add a bit extra for buflib overhead (2K) */
1527 if (!create_clip_buffer(ALIGN_UP(voice_sz, sizeof(long)) + (2<<10)))
1528 return;
1529 mutex_lock(&read_buffer_mutex);
1530 buf_handle = buflib_alloc(&clip_ctx, ALIGN_UP(voice_sz, sizeof(long)));
1531
1532 if (buf_handle < 0)
1533 return;
1534
1535 if (read_to_handle_ex(voice_fd, &clip_ctx, buf_handle, 0, voice_sz) > 0)
1536 {
1537 voice_thread_init();
1538 qe.handle = buf_handle;
1539 qe.length = qe.remaining = voice_sz;
1540 queue_clip(&qe, false);
1541 voice_wait();
1542 voice_thread_kill();
1543 }
1544
1545 mutex_unlock(&read_buffer_mutex);
1546 close(voice_fd);
1547
1548 buf_handle = buflib_free(&clip_ctx, buf_handle);
1549 talk_handle = core_free(talk_handle);
1550 }
1551}
1552
1502bool talk_get_debug_data(struct talk_debug_data *data) 1553bool talk_get_debug_data(struct talk_debug_data *data)
1503{ 1554{
1504 char* p_lang = DEFAULT_VOICE_LANG; /* default */ 1555 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 {
186 enum talk_status status; 186 enum talk_status status;
187}; 187};
188 188
189void talk_announce_voice_invalid(void);
190
189bool talk_get_debug_data(struct talk_debug_data *data); 191bool talk_get_debug_data(struct talk_debug_data *data);
190 192
191#endif /* __TALK_H__ */ 193#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
106 VOICE_STATE_MESSAGE = 0, 106 VOICE_STATE_MESSAGE = 0,
107 VOICE_STATE_DECODE, 107 VOICE_STATE_DECODE,
108 VOICE_STATE_BUFFER_INSERT, 108 VOICE_STATE_BUFFER_INSERT,
109 VOICE_STATE_QUIT,
109}; 110};
110 111
111/* A delay to not bring audio back to normal level too soon */ 112/* A delay to not bring audio back to normal level too soon */
@@ -115,6 +116,7 @@ enum voice_thread_messages
115{ 116{
116 Q_VOICE_PLAY = 0, /* Play a clip */ 117 Q_VOICE_PLAY = 0, /* Play a clip */
117 Q_VOICE_STOP, /* Stop current clip */ 118 Q_VOICE_STOP, /* Stop current clip */
119 Q_VOICE_KILL, /* Kill voice thread till restart*/
118}; 120};
119 121
120/* Structure to store clip data callback info */ 122/* Structure to store clip data callback info */
@@ -383,7 +385,9 @@ static enum voice_state voice_message(struct voice_thread_data *td)
383 speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead); 385 speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);
384 386
385 return VOICE_STATE_DECODE; 387 return VOICE_STATE_DECODE;
386 388 case Q_VOICE_KILL:
389 queue_delete(&voice_queue);
390 return VOICE_STATE_QUIT;
387 case SYS_TIMEOUT: 391 case SYS_TIMEOUT:
388 if (voice_unplayed_frames()) 392 if (voice_unplayed_frames())
389 { 393 {
@@ -512,7 +516,7 @@ static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
512} 516}
513 517
514/* Voice thread entrypoint */ 518/* Voice thread entrypoint */
515static void NORETURN_ATTR voice_thread(void) 519static void voice_thread(void)
516{ 520{
517 struct voice_thread_data td; 521 struct voice_thread_data td;
518 enum voice_state state = VOICE_STATE_MESSAGE; 522 enum voice_state state = VOICE_STATE_MESSAGE;
@@ -532,8 +536,20 @@ static void NORETURN_ATTR voice_thread(void)
532 case VOICE_STATE_BUFFER_INSERT: 536 case VOICE_STATE_BUFFER_INSERT:
533 state = voice_buffer_insert(&td); 537 state = voice_buffer_insert(&td);
534 break; 538 break;
539 case VOICE_STATE_QUIT:
540 logf("Exiting voice thread");
541 core_free(voice_buf_hid);
542 voice_buf_hid = 0;
543 return;
535 } 544 }
536 } 545 }
546 return;
547}
548
549/* kill voice thread and dont allow re-init*/
550void voice_thread_kill(void)
551{
552 queue_send(&voice_queue, Q_VOICE_KILL, 0);
537} 553}
538 554
539/* Initialize buffers, all synchronization objects and create the thread */ 555/* 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);
36void voice_stop(void); 36void voice_stop(void);
37 37
38void voice_thread_init(void); 38void voice_thread_init(void);
39void voice_thread_kill(void);
40
39#ifdef HAVE_PRIORITY_SCHEDULING 41#ifdef HAVE_PRIORITY_SCHEDULING
40void voice_thread_set_priority(int priority); 42void voice_thread_set_priority(int priority);
41#endif 43#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 {
614 copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt"); 614 copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt");
615 615
616 # copy the already built lng files 616 # copy the already built lng files
617 glob_copy('apps/lang/*lng', "$temp_dir/langs/"); 617 glob_copy('apps/lang/*.lng', "$temp_dir/langs/");
618 glob_copy('apps/lang/*.zip', "$temp_dir/langs/"); 618 glob_copy('apps/lang/*.zip', "$temp_dir/langs/");
619 glob_copy('apps/lang/*.talk', "$temp_dir/langs/");
619 620
620 # copy the .lua files 621 # copy the .lua files
621 glob_mkdir("$temp_dir/rocks/viewers/lua/"); 622 glob_mkdir("$temp_dir/rocks/viewers/lua/");