diff options
author | William Wilgus <wilgus.william@gmail.com> | 2022-11-19 02:12:09 -0500 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2022-11-19 02:12:09 -0500 |
commit | b0ccb1b95fa703e13eccec3fe873dde28e0176e9 (patch) | |
tree | bc40c888155a15d1f0f429f1e4c20cf8029b69f2 /apps | |
parent | 38687821b20dee54bc52718b49b851de5485351d (diff) | |
download | rockbox-b0ccb1b95fa703e13eccec3fe873dde28e0176e9.tar.gz rockbox-b0ccb1b95fa703e13eccec3fe873dde28e0176e9.zip |
talk.c clean up
Change-Id: Ie06859c80e9ca14bf3e4a23b82d3d1c76263b2b8
Diffstat (limited to 'apps')
-rw-r--r-- | apps/talk.c | 291 | ||||
-rw-r--r-- | apps/talk.h | 7 |
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. */ |
102 | static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in | 102 | static 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 ( | |||
118 | static bool talk_initialized; /* true if talk_init has been called */ | 118 | static bool talk_initialized; /* true if talk_init has been called */ |
119 | static bool give_buffer_away; /* true if we should give the buffers away in shrink_callback if requested */ | 119 | static bool give_buffer_away; /* true if we should give the buffers away in shrink_callback if requested */ |
120 | static int talk_temp_disable_count; /* if positive, temporarily disable voice UI (not saved) */ | 120 | static 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 */ |
123 | static unsigned long voicefile_size, voicebuf_size; | 124 | static 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() */ |
353 | static void add_cache_entry(int clip_handle, int table_index, int id) | 354 | static 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 | |||
552 | static inline int load_voicefile_failure(int fd) | 554 | static 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 */ |
559 | static bool load_voicefile_index(int fd) | 562 | static 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 */ | ||
728 | static 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 | |||
735 | static bool talk_is_disabled(void) | ||
736 | { | ||
737 | if (talk_temp_disable_count > 0 || (!check_audio_status())) | ||
738 | return true; | ||
739 | return false; | ||
740 | } | ||
741 | |||
742 | static void do_enqueue(bool enqueue) | ||
743 | { | ||
744 | if (!enqueue) | ||
745 | talk_shutup(); /* cut off all the pending stuff */ | ||
746 | } | ||
747 | |||
748 | /* spell a string */ | ||
749 | static 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 | |||
783 | static 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". */ | ||
799 | static 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 */ | ||
785 | static 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 | ||
794 | void talk_init(void) | 882 | void 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 */ |
886 | void talk_buffer_set_policy(int policy) | 974 | void 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). */ |
952 | int talk_idarray(const long *ids, bool enqueue) | 1043 | int 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 | ||
1059 | static 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. */ |
1089 | int talk_file_or_spell(const char *dirname, const char *filename, | 1149 | int 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. */ |
1123 | int talk_fullpath(const char* path, bool enqueue) | 1183 | int 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". */ | ||
1248 | static 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. */ |
1269 | static int talk_time_unit(long secs, bool enqueue) | 1305 | static 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 | ||
1426 | static 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 */ |
1394 | int talk_time_intervals(long time, int unit_idx, bool enqueue) | 1434 | int 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 */ |
1446 | int talk_spell(const char* spell, bool enqueue) | 1471 | int 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 | ||
1482 | void talk_disable(bool disable) | 1476 | void 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 | |||
1503 | void talk_date(const struct tm *tm, bool enqueue) | 1496 | void 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 | ||
67 | enum 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) |