diff options
author | Stéphane Doyon <s.doyon@videotron.ca> | 2008-07-15 14:55:31 +0000 |
---|---|---|
committer | Stéphane Doyon <s.doyon@videotron.ca> | 2008-07-15 14:55:31 +0000 |
commit | 3eb76d053db78be1f0b50f70134aa5a3b46ba77d (patch) | |
tree | 84caa006d3d69d97a665de17710c3c335bb3afd2 /apps | |
parent | d3cb2aca444ab7006dba9379ee0fff1195a7baff (diff) | |
download | rockbox-3eb76d053db78be1f0b50f70134aa5a3b46ba77d.tar.gz rockbox-3eb76d053db78be1f0b50f70134aa5a3b46ba77d.zip |
talk.c helper functions to voice a filename, in a more generic way
than from tree.c
Voice a file or dir's thumbnail from path components,
or spell last path component. Ability to prefix the thumbnail or
spelling with some talk ids.
This is the talk_file patch from FS#6323, just refactored a bit.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18048 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/talk.c | 110 | ||||
-rw-r--r-- | apps/talk.h | 12 | ||||
-rw-r--r-- | apps/tree.c | 50 |
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 */ |
658 | int 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. */ | ||
660 | static 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 | ||
732 | int | ||
733 | talk_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 | |||
749 | static int | ||
750 | talk_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. */ | ||
773 | int 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. */ | ||
790 | int 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. */ | ||
807 | int 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 */ | |||
84 | void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ | 84 | void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ |
85 | bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ | 85 | bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ |
86 | int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ | 86 | int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ |
87 | int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */ | 87 | /* play a thumbnail from file */ |
88 | int 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 */ | ||
91 | int talk_file_or_spell(const char *dirname, const char* filename, | ||
92 | long *prefix_ids, bool enqueue); | ||
93 | /* play dir's thumbnail or spell name */ | ||
94 | int talk_dir_or_spell(const char* filename, | ||
95 | long *prefix_ids, bool enqueue); | ||
96 | /* play thumbnails for each components of full path, or spell */ | ||
97 | int talk_fullpath(const char* path, bool enqueue); | ||
88 | int talk_number(long n, bool enqueue); /* say a number */ | 98 | int talk_number(long n, bool enqueue); /* say a number */ |
89 | int talk_value(long n, int unit, bool enqueue); /* say a numeric value */ | 99 | int talk_value(long n, int unit, bool enqueue); /* say a numeric value */ |
90 | int talk_value_decimal(long n, int unit, int decimals, bool enqueue); | 100 | int 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 | ||
1050 | static int ft_play_dirname(char* name) | 1050 | static 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 | ||
1079 | static void ft_play_filename(char *dir, char *file) | 1068 | static 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 */ |