summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2022-11-19 02:12:09 -0500
committerWilliam Wilgus <wilgus.william@gmail.com>2022-11-19 02:12:09 -0500
commitb0ccb1b95fa703e13eccec3fe873dde28e0176e9 (patch)
treebc40c888155a15d1f0f429f1e4c20cf8029b69f2
parent38687821b20dee54bc52718b49b851de5485351d (diff)
downloadrockbox-b0ccb1b95fa703e13eccec3fe873dde28e0176e9.tar.gz
rockbox-b0ccb1b95fa703e13eccec3fe873dde28e0176e9.zip
talk.c clean up
Change-Id: Ie06859c80e9ca14bf3e4a23b82d3d1c76263b2b8
-rw-r--r--apps/talk.c291
-rw-r--r--apps/talk.h7
2 files changed, 148 insertions, 150 deletions
diff --git a/apps/talk.c b/apps/talk.c
index 777c0f5a01..37a4482556 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -97,7 +97,7 @@ struct voicefile_header /* file format of our voice file */
97#define MAX_CLIP_BUFFER_SIZE (1<<30) 97#define MAX_CLIP_BUFFER_SIZE (1<<30)
98#endif 98#endif
99#define THUMBNAIL_RESERVE (50000) 99#define THUMBNAIL_RESERVE (50000)
100 100#define NULL_TERMINATED ((size_t)-1)
101/* Multiple thumbnails can be loaded back-to-back in this buffer. */ 101/* Multiple thumbnails can be loaded back-to-back in this buffer. */
102static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in 102static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in
103 thumbnail buffer */ 103 thumbnail buffer */
@@ -118,6 +118,7 @@ static unsigned char last_lang[MAX_FILENAME+1]; /* name of last used lang file (
118static bool talk_initialized; /* true if talk_init has been called */ 118static bool talk_initialized; /* true if talk_init has been called */
119static bool give_buffer_away; /* true if we should give the buffers away in shrink_callback if requested */ 119static bool give_buffer_away; /* true if we should give the buffers away in shrink_callback if requested */
120static int talk_temp_disable_count; /* if positive, temporarily disable voice UI (not saved) */ 120static int talk_temp_disable_count; /* if positive, temporarily disable voice UI (not saved) */
121
121 /* size of the voice data in the voice file and the actually allocated buffer 122 /* size of the voice data in the voice file and the actually allocated buffer
122 * for it. voicebuf_size is always smaller or equal to voicefile_size */ 123 * for it. voicebuf_size is always smaller or equal to voicefile_size */
123static unsigned long voicefile_size, voicebuf_size; 124static unsigned long voicefile_size, voicebuf_size;
@@ -306,14 +307,15 @@ static int free_oldest_clip(void)
306 unsigned i; 307 unsigned i;
307 int oldest = 0; 308 int oldest = 0;
308 bool thumb = false; 309 bool thumb = false;
309 long age, now; 310 long age, now, next_age;
310 struct clip_entry* clipbuf; 311 struct clip_entry* clipbuf;
311 struct clip_cache_metadata *cc = buflib_get_data(&clip_ctx, metadata_table_handle); 312 struct clip_cache_metadata *cc = buflib_get_data(&clip_ctx, metadata_table_handle);
312 for(age = i = 0, now = current_tick; i < max_clips; i++) 313 for(age = i = 0, now = current_tick; i < max_clips; i++)
313 { 314 {
314 if (cc[i].handle) 315 if (cc[i].handle)
315 { 316 {
316 if (thumb && cc[i].voice_id == VOICEONLY_DELIMITER && (now - cc[i].tick) > age) 317 next_age = (now - cc[i].tick);
318 if (thumb && cc[i].voice_id == VOICEONLY_DELIMITER && next_age > age)
317 { 319 {
318 /* thumb clips are freed first */ 320 /* thumb clips are freed first */
319 age = now - cc[i].tick; 321 age = now - cc[i].tick;
@@ -323,14 +325,14 @@ static int free_oldest_clip(void)
323 { 325 {
324 if (cc[i].voice_id == VOICEONLY_DELIMITER) 326 if (cc[i].voice_id == VOICEONLY_DELIMITER)
325 { 327 {
326 age = now - cc[i].tick; 328 age = next_age;
327 oldest = i; 329 oldest = i;
328 thumb = true; 330 thumb = true;
329 } 331 }
330 else if ((now - cc[i].tick) > age && cc[i].voice_id != VOICE_PAUSE) 332 else if (next_age > age && cc[i].voice_id != VOICE_PAUSE)
331 { 333 {
332 /* find the last-used clip but never consider silence */ 334 /* find the last-used clip but never consider silence */
333 age = now - cc[i].tick; 335 age = next_age;
334 oldest = i; 336 oldest = i;
335 } 337 }
336 } 338 }
@@ -348,7 +350,6 @@ static int free_oldest_clip(void)
348 return oldest; 350 return oldest;
349} 351}
350 352
351
352/* common code for load_initial_clips() and get_clip() */ 353/* common code for load_initial_clips() and get_clip() */
353static void add_cache_entry(int clip_handle, int table_index, int id) 354static void add_cache_entry(int clip_handle, int table_index, int id)
354{ 355{
@@ -549,12 +550,14 @@ alloc_err:
549 index_handle = core_free(index_handle); 550 index_handle = core_free(index_handle);
550 return false; 551 return false;
551} 552}
553
552static inline int load_voicefile_failure(int fd) 554static inline int load_voicefile_failure(int fd)
553{ 555{
554 if (fd >= 0) 556 if (fd >= 0)
555 close(fd); 557 close(fd);
556 return -1; 558 return -1;
557} 559}
560
558/* load the voice file into the mp3 buffer */ 561/* load the voice file into the mp3 buffer */
559static bool load_voicefile_index(int fd) 562static bool load_voicefile_index(int fd)
560{ 563{
@@ -719,6 +722,99 @@ static void mp3_callback(const void** start, size_t* size)
719 talk_queue_unlock(); 722 talk_queue_unlock();
720} 723}
721 724
725/***************** Private routines *****************/
726
727/* return if a voice codec is required or not */
728static bool talk_voice_required(void)
729{
730 return (has_voicefile) /* Voice file is available */
731 || (global_settings.talk_dir_clip) /* Thumbnail clips are required */
732 || (global_settings.talk_file_clip);
733}
734
735static bool talk_is_disabled(void)
736{
737 if (talk_temp_disable_count > 0 || (!check_audio_status()))
738 return true;
739 return false;
740}
741
742static void do_enqueue(bool enqueue)
743{
744 if (!enqueue)
745 talk_shutup(); /* cut off all the pending stuff */
746}
747
748/* spell a string */
749static int _talk_spell(const char* spell, size_t len, bool enqueue)
750{
751 char c; /* currently processed char */
752
753 if (talk_is_disabled())
754 return -1;
755
756 do_enqueue(enqueue); /* cut off all the pending stuff */
757
758 size_t len0 = len - 1;
759
760 while ((c = *spell++) != '\0' && len0-- < len)
761 {
762 /* if this grows into too many cases, I should use a table */
763 if (c >= 'A' && c <= 'Z')
764 talk_id(VOICE_CHAR_A + c - 'A', true);
765 else if (c >= 'a' && c <= 'z')
766 talk_id(VOICE_CHAR_A + c - 'a', true);
767 else if (c >= '0' && c <= '9')
768 talk_id(VOICE_ZERO + c - '0', true);
769 else if (c == '-')
770 talk_id(VOICE_MINUS, true);
771 else if (c == '+')
772 talk_id(VOICE_PLUS, true);
773 else if (c == '.')
774 talk_id(VOICE_DOT, true);
775 else if (c == ' ')
776 talk_id(VOICE_PAUSE, true);
777 else if (c == '/')
778 talk_id(VOICE_CHAR_SLASH, true);
779 }
780 return 0;
781}
782
783static int talk_spell_basename(const char *path,
784 const long *prefix_ids, bool enqueue)
785{
786 if(prefix_ids)
787 {
788 talk_idarray(prefix_ids, enqueue);
789 enqueue = true;
790 }
791 const char *basename;
792 size_t len = path_basename(path, &basename);
793
794 return _talk_spell(basename, len, enqueue);
795}
796
797/* Say year like "nineteen ninety nine" instead of "one thousand 9
798 hundred ninety nine". */
799static int talk_year(long year, bool enqueue)
800{
801 int rem;
802 if(year < 1100 || (year >=2000 && year < 2100))
803 /* just say it as a regular number */
804 return talk_number(year, enqueue);
805 /* Say century */
806 talk_number(year/100, enqueue);
807 rem = year%100;
808 if(rem == 0)
809 /* as in 1900 */
810 return talk_id(VOICE_HUNDRED, true);
811 if(rem <10)
812 /* as in 1905 */
813 talk_id(VOICE_ZERO, true);
814 /* sub-century year */
815 return talk_number(rem, true);
816}
817
722/***************** Public routines *****************/ 818/***************** Public routines *****************/
723 819
724/* stop the playback and the pending clips */ 820/* stop the playback and the pending clips */
@@ -746,8 +842,8 @@ static void queue_clip(struct queue_entry *clip, bool enqueue)
746 struct queue_entry *qe; 842 struct queue_entry *qe;
747 int queue_level; 843 int queue_level;
748 844
749 if (!enqueue) 845 do_enqueue(enqueue); /* cut off all the pending stuff */
750 talk_shutup(); /* cut off all the pending stuff */ 846
751 /* Something is being enqueued, force_enqueue_next override is no 847 /* Something is being enqueued, force_enqueue_next override is no
752 longer in effect. */ 848 longer in effect. */
753 force_enqueue_next = false; 849 force_enqueue_next = false;
@@ -781,14 +877,6 @@ static void queue_clip(struct queue_entry *clip, bool enqueue)
781 return; 877 return;
782} 878}
783 879
784/* return if a voice codec is required or not */
785static bool talk_voice_required(void)
786{
787 return (has_voicefile) /* Voice file is available */
788 || (global_settings.talk_dir_clip) /* Thumbnail clips are required */
789 || (global_settings.talk_file_clip);
790}
791
792/***************** Public implementation *****************/ 880/***************** Public implementation *****************/
793 881
794void talk_init(void) 882void talk_init(void)
@@ -885,6 +973,7 @@ out:
885/* somebody else claims the mp3 buffer, e.g. for regular play/record */ 973/* somebody else claims the mp3 buffer, e.g. for regular play/record */
886void talk_buffer_set_policy(int policy) 974void talk_buffer_set_policy(int policy)
887{ 975{
976#ifdef DEBUG
888 switch(policy) 977 switch(policy)
889 { 978 {
890 case TALK_BUFFER_DEFAULT: 979 case TALK_BUFFER_DEFAULT:
@@ -892,6 +981,9 @@ void talk_buffer_set_policy(int policy)
892 case TALK_BUFFER_LOOSE: give_buffer_away = true; break; 981 case TALK_BUFFER_LOOSE: give_buffer_away = true; break;
893 default: DEBUGF("Ignoring unknown policy\n"); break; 982 default: DEBUGF("Ignoring unknown policy\n"); break;
894 } 983 }
984#else
985 give_buffer_away = (policy == TALK_BUFFER_LOOSE);
986#endif
895} 987}
896 988
897/* play a voice ID from voicefile */ 989/* play a voice ID from voicefile */
@@ -903,10 +995,8 @@ int talk_id(int32_t id, bool enqueue)
903 bool isloaded = true; 995 bool isloaded = true;
904 996
905 if (!has_voicefile) 997 if (!has_voicefile)
906 return 0; /* no voicefile loaded, not an error -> pretent success */ 998 return 0; /* no voicefile loaded, not an error -> pretend success */
907 if (talk_temp_disable_count > 0) 999 if (talk_is_disabled())
908 return -1; /* talking has been disabled */
909 if (!check_audio_status())
910 return -1; 1000 return -1;
911 1001
912 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */ 1002 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */
@@ -948,6 +1038,7 @@ int talk_id(int32_t id, bool enqueue)
948 1038
949 return 0; 1039 return 0;
950} 1040}
1041
951/* Speaks zero or more IDs (from an array). */ 1042/* Speaks zero or more IDs (from an array). */
952int talk_idarray(const long *ids, bool enqueue) 1043int talk_idarray(const long *ids, bool enqueue)
953{ 1044{
@@ -981,9 +1072,7 @@ static int _talk_file(const char* filename,
981 int oldest = -1; 1072 int oldest = -1;
982 1073
983 /* reload needed? */ 1074 /* reload needed? */
984 if (talk_temp_disable_count > 0) 1075 if (talk_is_disabled())
985 return -1; /* talking has been disabled */
986 if (!check_audio_status())
987 return -1; 1076 return -1;
988 if (talk_handle <= 0 || index_handle <= 0) 1077 if (talk_handle <= 0 || index_handle <= 0)
989 { 1078 {
@@ -994,9 +1083,7 @@ static int _talk_file(const char* filename,
994 close(fd); 1083 close(fd);
995 } 1084 }
996 1085
997 if (!enqueue) 1086 do_enqueue(enqueue); /* shutup now to free the thumbnail buffer */
998 /* shutup now to free the thumbnail buffer */
999 talk_shutup();
1000 1087
1001 fd = open(filename, O_RDONLY); 1088 fd = open(filename, O_RDONLY);
1002 if (fd < 0) /* failed to open */ 1089 if (fd < 0) /* failed to open */
@@ -1045,45 +1132,18 @@ int talk_file(const char *root, const char *dir, const char *file,
1045/* Play a thumbnail file */ 1132/* Play a thumbnail file */
1046{ 1133{
1047 char buf[MAX_PATH]; 1134 char buf[MAX_PATH];
1135 const char *fmt = "%s%s%s%s%s";
1048 /* Does root end with a slash */ 1136 /* Does root end with a slash */
1049 char *slash = (root && root[0] 1137 if(root && root[0] && root[strlen(root)-1] != '/')
1050 && root[strlen(root)-1] != '/') ? "/" : ""; 1138 fmt = "%s/%s%s%s%s";
1051 snprintf(buf, MAX_PATH, "%s%s%s%s%s%s", 1139 snprintf(buf, MAX_PATH, fmt,
1052 root ? root : "", slash, 1140 root ? root : "",
1053 dir ? dir : "", dir ? "/" : "", 1141 dir ? dir : "", dir ? "/" : "",
1054 file ? file : "", 1142 file ? file : "",
1055 ext ? ext : ""); 1143 ext ? ext : "");
1056 return _talk_file(buf, prefix_ids, enqueue); 1144 return _talk_file(buf, prefix_ids, enqueue);
1057} 1145}
1058 1146
1059static int talk_spell_basename(const char *path,
1060 const long *prefix_ids, bool enqueue)
1061{
1062 if(prefix_ids)
1063 {
1064 talk_idarray(prefix_ids, enqueue);
1065 enqueue = true;
1066 }
1067 char buf[MAX_PATH];
1068 /* Spell only the path component after the last slash */
1069 char *end = strmemccpy(buf, path, sizeof(buf));
1070
1071 if (!end)
1072 return 0;
1073
1074 size_t len = end - buf - 1;
1075 if(len >1 && buf[len-1] == '/')
1076 buf[--len] = '\0'; /* strip trailing slash */
1077
1078 char *ptr = strrchr(buf, '/');
1079 if(ptr && len >1)
1080 ++ptr;
1081 else
1082 ptr = buf;
1083
1084 return talk_spell(ptr, enqueue);
1085}
1086
1087/* Play a file's .talk thumbnail, fallback to spelling the filename, or 1147/* Play a file's .talk thumbnail, fallback to spelling the filename, or
1088 go straight to spelling depending on settings. */ 1148 go straight to spelling depending on settings. */
1089int talk_file_or_spell(const char *dirname, const char *filename, 1149int talk_file_or_spell(const char *dirname, const char *filename,
@@ -1095,7 +1155,7 @@ int talk_file_or_spell(const char *dirname, const char *filename,
1095 prefix_ids, enqueue) >0) 1155 prefix_ids, enqueue) >0)
1096 return 0; 1156 return 0;
1097 } 1157 }
1098 if (global_settings.talk_file == 2) 1158 if (global_settings.talk_file == TALK_SPEAK_SPELL)
1099 /* Either .talk clips are disabled, or as a fallback */ 1159 /* Either .talk clips are disabled, or as a fallback */
1100 return talk_spell_basename(filename, prefix_ids, enqueue); 1160 return talk_spell_basename(filename, prefix_ids, enqueue);
1101 return 0; 1161 return 0;
@@ -1112,7 +1172,7 @@ int talk_dir_or_spell(const char* dirname,
1112 prefix_ids, enqueue) >0) 1172 prefix_ids, enqueue) >0)
1113 return 0; 1173 return 0;
1114 } 1174 }
1115 if (global_settings.talk_dir == 2) 1175 if (global_settings.talk_dir == TALK_SPEAK_SPELL)
1116 /* Either .talk clips disabled or as a fallback */ 1176 /* Either .talk clips disabled or as a fallback */
1117 return talk_spell_basename(dirname, prefix_ids, enqueue); 1177 return talk_spell_basename(dirname, prefix_ids, enqueue);
1118 return 0; 1178 return 0;
@@ -1122,8 +1182,8 @@ int talk_dir_or_spell(const char* dirname,
1122 back or going straight to spelling depending on settings. */ 1182 back or going straight to spelling depending on settings. */
1123int talk_fullpath(const char* path, bool enqueue) 1183int talk_fullpath(const char* path, bool enqueue)
1124{ 1184{
1125 if (!enqueue) 1185 do_enqueue(enqueue); /* cut off all the pending stuff */
1126 talk_shutup(); 1186
1127 if(path[0] != '/') 1187 if(path[0] != '/')
1128 /* path ought to start with /... */ 1188 /* path ought to start with /... */
1129 return talk_spell(path, true); 1189 return talk_spell(path, true);
@@ -1152,13 +1212,10 @@ int talk_number(long n, bool enqueue)
1152 int level = 2; /* mille count */ 1212 int level = 2; /* mille count */
1153 long mil = 1000000000; /* highest possible "-illion" */ 1213 long mil = 1000000000; /* highest possible "-illion" */
1154 1214
1155 if (talk_temp_disable_count > 0) 1215 if (talk_is_disabled())
1156 return -1; /* talking has been disabled */
1157 if (!check_audio_status())
1158 return -1; 1216 return -1;
1159 1217
1160 if (!enqueue) 1218 do_enqueue(enqueue); /* cut off all the pending stuff */
1161 talk_shutup(); /* cut off all the pending stuff */
1162 1219
1163 if (n==0) 1220 if (n==0)
1164 { /* special case */ 1221 { /* special case */
@@ -1243,27 +1300,6 @@ int talk_number(long n, bool enqueue)
1243 return 0; 1300 return 0;
1244} 1301}
1245 1302
1246/* Say year like "nineteen ninety nine" instead of "one thousand 9
1247 hundred ninety nine". */
1248static int talk_year(long year, bool enqueue)
1249{
1250 int rem;
1251 if(year < 1100 || (year >=2000 && year < 2100))
1252 /* just say it as a regular number */
1253 return talk_number(year, enqueue);
1254 /* Say century */
1255 talk_number(year/100, enqueue);
1256 rem = year%100;
1257 if(rem == 0)
1258 /* as in 1900 */
1259 return talk_id(VOICE_HUNDRED, true);
1260 if(rem <10)
1261 /* as in 1905 */
1262 talk_id(VOICE_ZERO, true);
1263 /* sub-century year */
1264 return talk_number(rem, true);
1265}
1266
1267/* Say time duration/interval. Input is time in seconds, 1303/* Say time duration/interval. Input is time in seconds,
1268 say hours,minutes,seconds. */ 1304 say hours,minutes,seconds. */
1269static int talk_time_unit(long secs, bool enqueue) 1305static int talk_time_unit(long secs, bool enqueue)
@@ -1336,9 +1372,7 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue)
1336 char tbuf[8]; 1372 char tbuf[8];
1337 char fmt[] = "%0nd"; 1373 char fmt[] = "%0nd";
1338 1374
1339 if (talk_temp_disable_count > 0) 1375 if (talk_is_disabled())
1340 return -1; /* talking has been disabled */
1341 if (!check_audio_status())
1342 return -1; 1376 return -1;
1343 1377
1344 /* special pronounciation for year number */ 1378 /* special pronounciation for year number */
@@ -1389,15 +1423,19 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue)
1389 return 0; 1423 return 0;
1390} 1424}
1391 1425
1426static inline void talk_time_value(long n, int unit, bool enqueue)
1427{
1428 if (n != 0)
1429 talk_value_decimal(n, unit, 0, enqueue);
1430}
1431
1392/* Say time duration/interval. Input is time unit specifies base unit, 1432/* Say time duration/interval. Input is time unit specifies base unit,
1393 say hours,minutes,seconds, milliseconds. or any combination thereof */ 1433 say hours,minutes,seconds, milliseconds. or any combination thereof */
1394int talk_time_intervals(long time, int unit_idx, bool enqueue) 1434int talk_time_intervals(long time, int unit_idx, bool enqueue)
1395{ 1435{
1396 unsigned long units_in[UNIT_IDX_TIME_COUNT]; 1436 unsigned long units_in[UNIT_IDX_TIME_COUNT];
1397 1437
1398 if (talk_temp_disable_count > 0) 1438 if (talk_is_disabled())
1399 return -1; /* talking has been disabled */
1400 if (!check_audio_status())
1401 return -1; 1439 return -1;
1402 1440
1403 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */ 1441 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */
@@ -1409,8 +1447,7 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
1409 close(fd); 1447 close(fd);
1410 } 1448 }
1411 1449
1412 if (!enqueue) 1450 do_enqueue(enqueue); /* cut off all the pending stuff */
1413 talk_shutup(); /* cut off all the pending stuff */
1414 1451
1415 time_split_units(unit_idx, labs(time), &units_in); 1452 time_split_units(unit_idx, labs(time), &units_in);
1416 1453
@@ -1421,22 +1458,10 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
1421 talk_value(0, unit_idx, true); 1458 talk_value(0, unit_idx, true);
1422 else 1459 else
1423 { 1460 {
1424 if (units_in[UNIT_IDX_HR] != 0) 1461 talk_time_value(units_in[UNIT_IDX_HR], UNIT_HOUR, true);
1425 { 1462 talk_time_value(units_in[UNIT_IDX_MIN], UNIT_MIN, true);
1426 talk_value(units_in[UNIT_IDX_HR], UNIT_HOUR, true); 1463 talk_time_value(units_in[UNIT_IDX_SEC], UNIT_SEC, true);
1427 } 1464 talk_time_value(units_in[UNIT_IDX_MS], UNIT_MS, true);
1428 if (units_in[UNIT_IDX_MIN] != 0)
1429 {
1430 talk_value(units_in[UNIT_IDX_MIN], UNIT_MIN, true);
1431 }
1432 if (units_in[UNIT_IDX_SEC] != 0)
1433 {
1434 talk_value(units_in[UNIT_IDX_SEC], UNIT_SEC, true);
1435 }
1436 if (units_in[UNIT_IDX_MS] != 0)
1437 {
1438 talk_value(units_in[UNIT_IDX_MS], UNIT_MS, true);
1439 }
1440 } 1465 }
1441 1466
1442 return -1; 1467 return -1;
@@ -1445,38 +1470,7 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
1445/* spell a string */ 1470/* spell a string */
1446int talk_spell(const char* spell, bool enqueue) 1471int talk_spell(const char* spell, bool enqueue)
1447{ 1472{
1448 char c; /* currently processed char */ 1473 return _talk_spell(spell, NULL_TERMINATED, enqueue);
1449
1450 if (talk_temp_disable_count > 0)
1451 return -1; /* talking has been disabled */
1452 if (!check_audio_status())
1453 return -1;
1454
1455 if (!enqueue)
1456 talk_shutup(); /* cut off all the pending stuff */
1457
1458 while ((c = *spell++) != '\0')
1459 {
1460 /* if this grows into too many cases, I should use a table */
1461 if (c >= 'A' && c <= 'Z')
1462 talk_id(VOICE_CHAR_A + c - 'A', true);
1463 else if (c >= 'a' && c <= 'z')
1464 talk_id(VOICE_CHAR_A + c - 'a', true);
1465 else if (c >= '0' && c <= '9')
1466 talk_id(VOICE_ZERO + c - '0', true);
1467 else if (c == '-')
1468 talk_id(VOICE_MINUS, true);
1469 else if (c == '+')
1470 talk_id(VOICE_PLUS, true);
1471 else if (c == '.')
1472 talk_id(VOICE_DOT, true);
1473 else if (c == ' ')
1474 talk_id(VOICE_PAUSE, true);
1475 else if (c == '/')
1476 talk_id(VOICE_CHAR_SLASH, true);
1477 }
1478
1479 return 0;
1480} 1474}
1481 1475
1482void talk_disable(bool disable) 1476void talk_disable(bool disable)
@@ -1499,14 +1493,12 @@ void talk_setting(const void *global_settings_variable)
1499 talk_id(setting->lang_id,false); 1493 talk_id(setting->lang_id,false);
1500} 1494}
1501 1495
1502
1503void talk_date(const struct tm *tm, bool enqueue) 1496void talk_date(const struct tm *tm, bool enqueue)
1504{ 1497{
1505 const char *format = str(LANG_VOICED_DATE_FORMAT); 1498 const char *format = str(LANG_VOICED_DATE_FORMAT);
1506 const char *ptr; 1499 const char *ptr;
1507 1500
1508 if (!enqueue) 1501 do_enqueue(enqueue); /* cut off all the pending stuff */
1509 talk_shutup(); /* cut off all the pending stuff */
1510 1502
1511 for (ptr = format ; *ptr ; ptr++) { 1503 for (ptr = format ; *ptr ; ptr++) {
1512 switch(*ptr) { 1504 switch(*ptr) {
@@ -1586,8 +1578,7 @@ void talk_announce_voice_invalid(void)
1586 int buf_handle; 1578 int buf_handle;
1587 struct queue_entry qe; 1579 struct queue_entry qe;
1588 1580
1589 const char talkfile[] = 1581 const char talkfile[] = LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
1590 LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
1591 1582
1592 if (global_settings.talk_menu && talk_status != TALK_STATUS_OK) 1583 if (global_settings.talk_menu && talk_status != TALK_STATUS_OK)
1593 { 1584 {
diff --git a/apps/talk.h b/apps/talk.h
index d5f3bb2996..6139b9ec46 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -64,6 +64,13 @@ enum talk_status {
64 TALK_STATUS_ERR_INCOMPATIBLE 64 TALK_STATUS_ERR_INCOMPATIBLE
65}; 65};
66 66
67enum talk_speakmode {
68 /* voice mode: 0=off, 1=number, 2=spell */
69 TALK_SPEAK_OFF = 0,
70 TALK_SPEAK_NUMBER,
71 TALK_SPEAK_SPELL
72};
73
67#define UNIT_SHIFT (32-5) /* this many bits left from UNIT_xx enum */ 74#define UNIT_SHIFT (32-5) /* this many bits left from UNIT_xx enum */
68 75
69#define DECIMAL_SHIFT (32 - 8) 76#define DECIMAL_SHIFT (32 - 8)