summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/talk.c110
-rw-r--r--apps/talk.h12
-rw-r--r--apps/tree.c50
4 files changed, 150 insertions, 36 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 3815edb656..92e02e13b8 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -11835,3 +11835,17 @@
11835 </voice> 11835 </voice>
11836</phrase> 11836</phrase>
11837 11837
11838<phrase>
11839 id: VOICE_CHAR_SLASH
11840 desc: spoken only, for spelling
11841 user:
11842 <source>
11843 *: ""
11844 </source>
11845 <dest>
11846 *: ""
11847 </dest>
11848 <voice>
11849 *: "slash"
11850 </voice>
11851</phrase>
diff --git a/apps/talk.c b/apps/talk.c
index f84ecd0ef5..601b7b4b88 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -655,7 +655,9 @@ void talk_force_enqueue_next(void)
655} 655}
656 656
657/* play a thumbnail from file */ 657/* play a thumbnail from file */
658int talk_file(const char* filename, bool enqueue) 658/* Returns size of spoken thumbnail, so >0 means something is spoken,
659 <=0 means something went wrong. */
660static int _talk_file(const char* filename, long *prefix_ids, bool enqueue)
659{ 661{
660 int fd; 662 int fd;
661 int size; 663 int size;
@@ -713,6 +715,11 @@ int talk_file(const char* filename, bool enqueue)
713#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) 715#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
714 bitswap(p_thumbnail, size); 716 bitswap(p_thumbnail, size);
715#endif 717#endif
718 if(prefix_ids)
719 /* prefix thumbnail by speaking these ids, but only now
720 that we know there's actually a thumbnail to be
721 spoken. */
722 talk_idarray(prefix_ids, true);
716 talk_queue_lock(); 723 talk_queue_lock();
717 thumbnail_buf_used = thumb_used +size; 724 thumbnail_buf_used = thumb_used +size;
718 talk_queue_unlock(); 725 talk_queue_unlock();
@@ -722,6 +729,105 @@ int talk_file(const char* filename, bool enqueue)
722 return size; 729 return size;
723} 730}
724 731
732int
733talk_file(const char *root, const char *dir, const char *file,
734 const char *ext, long *prefix_ids, bool enqueue)
735/* Play a thumbnail file */
736{
737 char buf[MAX_PATH];
738 /* Does root end with a slash */
739 char *slash = (root && root[0]
740 && root[strlen(root)-1] != '/') ? "/" : "";
741 snprintf(buf, MAX_PATH, "%s%s%s%s%s%s",
742 root ? root : "", slash,
743 dir ? dir : "", dir ? "/" : "",
744 file ? file : "",
745 ext ? ext : "");
746 return _talk_file(buf, prefix_ids, enqueue);
747}
748
749static int
750talk_spell_basename(const char *path,
751 long *prefix_ids, bool enqueue)
752{
753 if(prefix_ids)
754 {
755 talk_idarray(prefix_ids, enqueue);
756 enqueue = true;
757 }
758 char buf[MAX_PATH];
759 /* Spell only the path component after the last slash */
760 strncpy(buf, path, MAX_PATH);
761 if(strlen(buf) >1 && buf[strlen(buf)-1] == '/')
762 /* strip trailing slash */
763 buf[strlen(buf)-1] = '\0';
764 char *ptr = strrchr(buf, '/');
765 if(ptr && strlen(buf) >1)
766 ++ptr;
767 else ptr = buf;
768 return talk_spell(ptr, enqueue);
769}
770
771/* Play a file's .talk thumbnail, fallback to spelling the filename, or
772 go straight to spelling depending on settings. */
773int talk_file_or_spell(const char *dirname, const char *filename,
774 long *prefix_ids, bool enqueue)
775{
776 if (global_settings.talk_file_clip)
777 { /* .talk clips enabled */
778 if(talk_file(dirname, NULL, filename, file_thumbnail_ext,
779 prefix_ids, enqueue) >0)
780 return 0;
781 }
782 if (global_settings.talk_file == 2)
783 /* Either .talk clips are disabled, or as a fallback */
784 return talk_spell_basename(filename, prefix_ids, enqueue);
785 return 0;
786}
787
788/* Play a directory's .talk thumbnail, fallback to spelling the filename, or
789 go straight to spelling depending on settings. */
790int talk_dir_or_spell(const char* dirname,
791 long *prefix_ids, bool enqueue)
792{
793 if (global_settings.talk_dir_clip)
794 { /* .talk clips enabled */
795 if(talk_file(dirname, NULL, dir_thumbnail_name, NULL,
796 prefix_ids, enqueue) >0)
797 return 0;
798 }
799 if (global_settings.talk_dir == 2)
800 /* Either .talk clips disabled or as a fallback */
801 return talk_spell_basename(dirname, prefix_ids, enqueue);
802 return 0;
803}
804
805/* Speak thumbnail for each component of a full path, again falling
806 back or going straight to spelling depending on settings. */
807int talk_fullpath(const char* path, bool enqueue)
808{
809 if (!enqueue)
810 talk_shutup();
811 if(path[0] != '/')
812 /* path ought to start with /... */
813 return talk_spell(path, true);
814 talk_id(VOICE_CHAR_SLASH, true);
815 char buf[MAX_PATH];
816 strncpy(buf, path, MAX_PATH);
817 char *start = buf+1; /* start of current component */
818 char *ptr = strchr(start, '/'); /* end of current component */
819 while(ptr) { /* There are more slashes ahead */
820 /* temporarily poke a NULL at end of component to truncate string */
821 *ptr = '\0';
822 talk_dir_or_spell(buf, NULL, true);
823 *ptr = '/'; /* restore string */
824 talk_id(VOICE_CHAR_SLASH, true);
825 start = ptr+1; /* setup for next component */
826 ptr = strchr(start, '/');
827 }
828 /* no more slashes, final component is a filename */
829 return talk_file_or_spell(NULL, buf, NULL, true);
830}
725 831
726/* say a numeric value, this word ordering works for english, 832/* say a numeric value, this word ordering works for english,
727 but not necessarily for other languages (e.g. german) */ 833 but not necessarily for other languages (e.g. german) */
@@ -964,6 +1070,8 @@ int talk_spell(const char* spell, bool enqueue)
964 talk_id(VOICE_DOT, true); 1070 talk_id(VOICE_DOT, true);
965 else if (c == ' ') 1071 else if (c == ' ')
966 talk_id(VOICE_PAUSE, true); 1072 talk_id(VOICE_PAUSE, true);
1073 else if (c == '/')
1074 talk_id(VOICE_CHAR_SLASH, true);
967 } 1075 }
968 1076
969 return 0; 1077 return 0;
diff --git a/apps/talk.h b/apps/talk.h
index e73164486d..b0a26c3053 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -84,7 +84,17 @@ int talk_get_bufsize(void); /* get the loaded voice file size */
84void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ 84void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
85bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ 85bool is_voice_queued(void); /* Are there more voice clips to be spoken? */
86int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ 86int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */
87int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */ 87/* play a thumbnail from file */
88int talk_file(const char *root, const char *dir, const char *file,
89 const char *ext, long *prefix_ids, bool enqueue);
90/* play file's thumbnail or spell name */
91int talk_file_or_spell(const char *dirname, const char* filename,
92 long *prefix_ids, bool enqueue);
93/* play dir's thumbnail or spell name */
94int talk_dir_or_spell(const char* filename,
95 long *prefix_ids, bool enqueue);
96/* play thumbnails for each components of full path, or spell */
97int talk_fullpath(const char* path, bool enqueue);
88int talk_number(long n, bool enqueue); /* say a number */ 98int talk_number(long n, bool enqueue); /* say a number */
89int talk_value(long n, int unit, bool enqueue); /* say a numeric value */ 99int talk_value(long n, int unit, bool enqueue); /* say a numeric value */
90int talk_value_decimal(long n, int unit, int decimals, bool enqueue); 100int talk_value_decimal(long n, int unit, int decimals, bool enqueue);
diff --git a/apps/tree.c b/apps/tree.c
index 54f3b8997c..603500cef4 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -1049,57 +1049,39 @@ static void say_filetype(int attr)
1049 1049
1050static int ft_play_dirname(char* name) 1050static int ft_play_dirname(char* name)
1051{ 1051{
1052 char dirname_mp3_filename[MAX_PATH+1];
1053
1054#if CONFIG_CODEC != SWCODEC 1052#if CONFIG_CODEC != SWCODEC
1055 if (audio_status() & AUDIO_STATUS_PLAY) 1053 if (audio_status() & AUDIO_STATUS_PLAY)
1056 return 0; 1054 return 0;
1057#endif 1055#endif
1058 1056
1059 snprintf(dirname_mp3_filename, sizeof(dirname_mp3_filename), "%s/%s/%s", 1057 if(talk_file(tc.currdir, name, dir_thumbnail_name, NULL,
1060 tc.currdir[1] ? tc.currdir : "" , name, 1058 NULL, false))
1061 dir_thumbnail_name);
1062
1063 DEBUGF("Checking for %s\n", dirname_mp3_filename);
1064
1065 if (!file_exists(dirname_mp3_filename))
1066 { 1059 {
1067 DEBUGF("Failed to find: %s\n", dirname_mp3_filename); 1060 if(global_settings.talk_filetype)
1068 return -1; 1061 talk_id(VOICE_DIR, true);
1062 return 1;
1069 } 1063 }
1070 1064 else
1071 DEBUGF("Found: %s\n", dirname_mp3_filename); 1065 return -1;
1072
1073 talk_file(dirname_mp3_filename, false);
1074 if(global_settings.talk_filetype)
1075 talk_id(VOICE_DIR, true);
1076 return 1;
1077} 1066}
1078 1067
1079static void ft_play_filename(char *dir, char *file) 1068static void ft_play_filename(char *dir, char *file)
1080{ 1069{
1081 char name_mp3_filename[MAX_PATH+1];
1082
1083#if CONFIG_CODEC != SWCODEC 1070#if CONFIG_CODEC != SWCODEC
1084 if (audio_status() & AUDIO_STATUS_PLAY) 1071 if (audio_status() & AUDIO_STATUS_PLAY)
1085 return; 1072 return;
1086#endif 1073#endif
1087 1074
1088 if (strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)], 1075 if (strlen(file) > strlen(file_thumbnail_ext)
1089 file_thumbnail_ext)) 1076 && strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)],
1090 { /* file has no .talk extension */ 1077 file_thumbnail_ext))
1091 snprintf(name_mp3_filename, sizeof(name_mp3_filename), 1078 /* file has no .talk extension */
1092 "%s/%s%s", dir, file, file_thumbnail_ext); 1079 talk_file(dir, NULL, file, file_thumbnail_ext,
1093 1080 NULL, false);
1094 talk_file(name_mp3_filename, false);
1095 }
1096 else 1081 else
1097 { /* it already is a .talk file, play this directly */ 1082 /* it already is a .talk file, play this directly, but prefix it. */
1098 snprintf(name_mp3_filename, sizeof(name_mp3_filename), 1083 talk_file(dir, NULL, file, NULL,
1099 "%s/%s", dir, file); 1084 TALK_IDARRAY(LANG_VOICE_DIR_HOVER), false);
1100 talk_id(LANG_VOICE_DIR_HOVER, false); /* prefix it */
1101 talk_file(name_mp3_filename, true);
1102 }
1103} 1085}
1104 1086
1105/* These two functions are called by the USB and shutdown handlers */ 1087/* These two functions are called by the USB and shutdown handlers */