Index: trunk/apps/talk.c
===================================================================
--- trunk.orig/apps/talk.c
+++ trunk/apps/talk.c
@@ -639,7 +639,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. */
+int talk_file(const char* filename, long *prefix_ids, bool enqueue)
{
int fd;
int size;
@@ -699,6 +701,11 @@ int talk_file(const char* filename, bool
#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);
queue_lock();
thumbnail_buf_used = thumb_used +size;
queue_unlock();
@@ -708,6 +715,109 @@ int talk_file(const char* filename, bool
return size;
}
+/* Play a file's .talk thumbnail, fallback to spelling the filename, or
+ go straight to spelling depending on settings.
+ If dirname is non-NULL, it is prepended to the filename, otherwise
+ the filename should be a full path name. */
+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 */
+ char buf[MAX_PATH];
+ /* Does dirname end with a slash */
+ char *slash = (dirname && strlen(dirname) >1
+ && dirname[strlen(dirname)-1] != '/') ? "/" : "";
+ snprintf(buf, MAX_PATH, "%s%s%s%s",
+ dirname ? dirname : "",
+ slash,
+ filename,
+ file_thumbnail_ext);
+ if(talk_file(buf, prefix_ids, enqueue) > 0)
+ return 0;
+ }
+ if (global_settings.talk_file == 2)
+ { /* Either .talk clips are disabled, or as a fallback */
+ if(prefix_ids)
+ {
+ talk_idarray(prefix_ids, enqueue);
+ enqueue = true;
+ }
+ /* Spelling is slow, so speak only the basename (after the
+ last slash ) */
+ const char *ptr = strrchr(filename, '/');
+ if(ptr)
+ ++ptr;
+ else ptr = filename;
+ return talk_spell(ptr, 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 */
+ char buf[MAX_PATH];
+ /* Does directory name end in slash? */
+ char *slash = (strlen(dirname) >1
+ && dirname[strlen(dirname)-1] != '/') ? "/" : "";
+ snprintf(buf, MAX_PATH, "%s%s%s",
+ dirname, slash, dir_thumbnail_name);
+ if(talk_file(buf, prefix_ids, enqueue) > 0)
+ return 0;
+ }
+ if (global_settings.talk_file == 2)
+ { /* Either .talk clips disabled or as a fallback */
+ 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, dirname, 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);
+ }
+ 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 */
+ start = ptr+1; /* setup for next component */
+ ptr = strchr(start, '/');
+ talk_id(VOICE_CHAR_SLASH, true);
+ }
+ /* 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) */
@@ -905,6 +1015,8 @@ int talk_spell(const char* spell, bool e
talk_id(VOICE_DOT, true);
else if (c == ' ')
talk_id(VOICE_PAUSE, true);
+ else if (c == '/')
+ talk_id(VOICE_CHAR_SLASH, true);
}
return 0;
Index: trunk/apps/tree.c
===================================================================
--- trunk.orig/apps/tree.c
+++ trunk/apps/tree.c
@@ -1225,7 +1225,7 @@ static int ft_play_dirname(char* name)
DEBUGF("Found: %s\n", dirname_mp3_filename);
- talk_file(dirname_mp3_filename, false);
+ talk_file(dirname_mp3_filename, NULL, false);
if(global_settings.talk_filetype)
talk_id(VOICE_DIR, true);
return 1;
@@ -1246,14 +1246,15 @@ static void ft_play_filename(char *dir,
snprintf(name_mp3_filename, sizeof(name_mp3_filename),
"%s/%s%s", dir, file, file_thumbnail_ext);
- talk_file(name_mp3_filename, false);
+ talk_file(name_mp3_filename, 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);
+ talk_file(name_mp3_filename, TALK_IDARRAY(LANG_VOICE_DIR_HOVER),
+ false);
}
}
Index: trunk/apps/talk.h
===================================================================
--- trunk.orig/apps/talk.h
+++ trunk/apps/talk.h
@@ -74,7 +74,16 @@ int talk_get_bufsize(void); /* get the l
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* filename, 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_spell(const char* spell, bool enqueue); /* spell a string */
Index: trunk/apps/lang/english.lang
===================================================================
--- trunk.orig/apps/lang/english.lang
+++ trunk/apps/lang/english.lang
@@ -9845,24 +9845,38 @@
user:
*: ""
*: ""
*: "dot"
+ id: VOICE_CHAR_SLASH
+ desc: spoken only, for spelling
+ user:
+
+ *: ""
+
+
+ *: ""
+
+
+ *: "slash"
+
+
+
id: VOICE_PAUSE
desc: spoken only, for spelling, a split second of silence (difficult to author)
user:
*: ""
*: ""
*: " "