From 3eb76d053db78be1f0b50f70134aa5a3b46ba77d Mon Sep 17 00:00:00 2001 From: Stéphane Doyon Date: Tue, 15 Jul 2008 14:55:31 +0000 Subject: 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 --- apps/lang/english.lang | 14 +++++++ apps/talk.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++- apps/talk.h | 12 +++++- apps/tree.c | 50 +++++++--------------- 4 files changed, 150 insertions(+), 36 deletions(-) (limited to 'apps') 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 @@ + + id: VOICE_CHAR_SLASH + desc: spoken only, for spelling + user: + + *: "" + + + *: "" + + + *: "slash" + + 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) } /* play a thumbnail from file */ -int talk_file(const char* filename, bool enqueue) +/* Returns size of spoken thumbnail, so >0 means something is spoken, + <=0 means something went wrong. */ +static int _talk_file(const char* filename, long *prefix_ids, bool enqueue) { int fd; int size; @@ -713,6 +715,11 @@ int talk_file(const char* filename, bool enqueue) #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) bitswap(p_thumbnail, size); #endif + if(prefix_ids) + /* prefix thumbnail by speaking these ids, but only now + that we know there's actually a thumbnail to be + spoken. */ + talk_idarray(prefix_ids, true); talk_queue_lock(); thumbnail_buf_used = thumb_used +size; talk_queue_unlock(); @@ -722,6 +729,105 @@ int talk_file(const char* filename, bool enqueue) return size; } +int +talk_file(const char *root, const char *dir, const char *file, + const char *ext, long *prefix_ids, bool enqueue) +/* Play a thumbnail file */ +{ + char buf[MAX_PATH]; + /* Does root end with a slash */ + char *slash = (root && root[0] + && root[strlen(root)-1] != '/') ? "/" : ""; + snprintf(buf, MAX_PATH, "%s%s%s%s%s%s", + root ? root : "", slash, + dir ? dir : "", dir ? "/" : "", + file ? file : "", + ext ? ext : ""); + return _talk_file(buf, prefix_ids, enqueue); +} + +static int +talk_spell_basename(const char *path, + long *prefix_ids, bool enqueue) +{ + if(prefix_ids) + { + talk_idarray(prefix_ids, enqueue); + enqueue = true; + } + char buf[MAX_PATH]; + /* Spell only the path component after the last slash */ + strncpy(buf, path, MAX_PATH); + if(strlen(buf) >1 && buf[strlen(buf)-1] == '/') + /* strip trailing slash */ + buf[strlen(buf)-1] = '\0'; + char *ptr = strrchr(buf, '/'); + if(ptr && strlen(buf) >1) + ++ptr; + else ptr = buf; + return talk_spell(ptr, enqueue); +} + +/* Play a file's .talk thumbnail, fallback to spelling the filename, or + go straight to spelling depending on settings. */ +int talk_file_or_spell(const char *dirname, const char *filename, + long *prefix_ids, bool enqueue) +{ + if (global_settings.talk_file_clip) + { /* .talk clips enabled */ + if(talk_file(dirname, NULL, filename, file_thumbnail_ext, + prefix_ids, enqueue) >0) + return 0; + } + if (global_settings.talk_file == 2) + /* Either .talk clips are disabled, or as a fallback */ + return talk_spell_basename(filename, prefix_ids, enqueue); + return 0; +} + +/* Play a directory's .talk thumbnail, fallback to spelling the filename, or + go straight to spelling depending on settings. */ +int talk_dir_or_spell(const char* dirname, + long *prefix_ids, bool enqueue) +{ + if (global_settings.talk_dir_clip) + { /* .talk clips enabled */ + if(talk_file(dirname, NULL, dir_thumbnail_name, NULL, + prefix_ids, enqueue) >0) + return 0; + } + if (global_settings.talk_dir == 2) + /* Either .talk clips disabled or as a fallback */ + return talk_spell_basename(dirname, prefix_ids, enqueue); + return 0; +} + +/* Speak thumbnail for each component of a full path, again falling + back or going straight to spelling depending on settings. */ +int talk_fullpath(const char* path, bool enqueue) +{ + if (!enqueue) + talk_shutup(); + if(path[0] != '/') + /* path ought to start with /... */ + return talk_spell(path, true); + talk_id(VOICE_CHAR_SLASH, true); + char buf[MAX_PATH]; + strncpy(buf, path, MAX_PATH); + char *start = buf+1; /* start of current component */ + char *ptr = strchr(start, '/'); /* end of current component */ + while(ptr) { /* There are more slashes ahead */ + /* temporarily poke a NULL at end of component to truncate string */ + *ptr = '\0'; + talk_dir_or_spell(buf, NULL, true); + *ptr = '/'; /* restore string */ + talk_id(VOICE_CHAR_SLASH, true); + start = ptr+1; /* setup for next component */ + ptr = strchr(start, '/'); + } + /* no more slashes, final component is a filename */ + return talk_file_or_spell(NULL, buf, NULL, true); +} /* say a numeric value, this word ordering works for english, but not necessarily for other languages (e.g. german) */ @@ -964,6 +1070,8 @@ int talk_spell(const char* spell, bool enqueue) talk_id(VOICE_DOT, true); else if (c == ' ') talk_id(VOICE_PAUSE, true); + else if (c == '/') + talk_id(VOICE_CHAR_SLASH, true); } 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 */ void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ -int talk_file(const char* filename, bool enqueue); /* play a thumbnail from file */ +/* play a thumbnail from file */ +int talk_file(const char *root, const char *dir, const char *file, + const char *ext, long *prefix_ids, bool enqueue); +/* play file's thumbnail or spell name */ +int talk_file_or_spell(const char *dirname, const char* filename, + long *prefix_ids, bool enqueue); +/* play dir's thumbnail or spell name */ +int talk_dir_or_spell(const char* filename, + long *prefix_ids, bool enqueue); +/* play thumbnails for each components of full path, or spell */ +int talk_fullpath(const char* path, bool enqueue); int talk_number(long n, bool enqueue); /* say a number */ int talk_value(long n, int unit, bool enqueue); /* say a numeric value */ 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) static int ft_play_dirname(char* name) { - char dirname_mp3_filename[MAX_PATH+1]; - #if CONFIG_CODEC != SWCODEC if (audio_status() & AUDIO_STATUS_PLAY) return 0; #endif - snprintf(dirname_mp3_filename, sizeof(dirname_mp3_filename), "%s/%s/%s", - tc.currdir[1] ? tc.currdir : "" , name, - dir_thumbnail_name); - - DEBUGF("Checking for %s\n", dirname_mp3_filename); - - if (!file_exists(dirname_mp3_filename)) + if(talk_file(tc.currdir, name, dir_thumbnail_name, NULL, + NULL, false)) { - DEBUGF("Failed to find: %s\n", dirname_mp3_filename); - return -1; + if(global_settings.talk_filetype) + talk_id(VOICE_DIR, true); + return 1; } - - DEBUGF("Found: %s\n", dirname_mp3_filename); - - talk_file(dirname_mp3_filename, false); - if(global_settings.talk_filetype) - talk_id(VOICE_DIR, true); - return 1; + else + return -1; } static void ft_play_filename(char *dir, char *file) { - char name_mp3_filename[MAX_PATH+1]; - #if CONFIG_CODEC != SWCODEC if (audio_status() & AUDIO_STATUS_PLAY) return; #endif - if (strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)], - file_thumbnail_ext)) - { /* file has no .talk extension */ - snprintf(name_mp3_filename, sizeof(name_mp3_filename), - "%s/%s%s", dir, file, file_thumbnail_ext); - - talk_file(name_mp3_filename, false); - } + if (strlen(file) > strlen(file_thumbnail_ext) + && strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)], + file_thumbnail_ext)) + /* file has no .talk extension */ + talk_file(dir, NULL, file, file_thumbnail_ext, + NULL, false); else - { /* it already is a .talk file, play this directly */ - snprintf(name_mp3_filename, sizeof(name_mp3_filename), - "%s/%s", dir, file); - talk_id(LANG_VOICE_DIR_HOVER, false); /* prefix it */ - talk_file(name_mp3_filename, true); - } + /* it already is a .talk file, play this directly, but prefix it. */ + talk_file(dir, NULL, file, NULL, + TALK_IDARRAY(LANG_VOICE_DIR_HOVER), false); } /* These two functions are called by the USB and shutdown handlers */ -- cgit v1.2.3