mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
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
This commit is contained in:
parent
d3cb2aca44
commit
3eb76d053d
4 changed files with 150 additions and 36 deletions
|
@ -11835,3 +11835,17 @@
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
|
||||||
|
<phrase>
|
||||||
|
id: VOICE_CHAR_SLASH
|
||||||
|
desc: spoken only, for spelling
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: ""
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: ""
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "slash"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
110
apps/talk.c
110
apps/talk.c
|
@ -655,7 +655,9 @@ void talk_force_enqueue_next(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* play a thumbnail from file */
|
/* 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 fd;
|
||||||
int size;
|
int size;
|
||||||
|
@ -713,6 +715,11 @@ int talk_file(const char* filename, bool enqueue)
|
||||||
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
|
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
|
||||||
bitswap(p_thumbnail, size);
|
bitswap(p_thumbnail, size);
|
||||||
#endif
|
#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();
|
talk_queue_lock();
|
||||||
thumbnail_buf_used = thumb_used +size;
|
thumbnail_buf_used = thumb_used +size;
|
||||||
talk_queue_unlock();
|
talk_queue_unlock();
|
||||||
|
@ -722,6 +729,105 @@ int talk_file(const char* filename, bool enqueue)
|
||||||
return size;
|
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,
|
/* say a numeric value, this word ordering works for english,
|
||||||
but not necessarily for other languages (e.g. german) */
|
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);
|
talk_id(VOICE_DOT, true);
|
||||||
else if (c == ' ')
|
else if (c == ' ')
|
||||||
talk_id(VOICE_PAUSE, true);
|
talk_id(VOICE_PAUSE, true);
|
||||||
|
else if (c == '/')
|
||||||
|
talk_id(VOICE_CHAR_SLASH, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
12
apps/talk.h
12
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 */
|
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? */
|
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_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_number(long n, bool enqueue); /* say a number */
|
||||||
int talk_value(long n, int unit, bool enqueue); /* say a numeric value */
|
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);
|
int talk_value_decimal(long n, int unit, int decimals, bool enqueue);
|
||||||
|
|
44
apps/tree.c
44
apps/tree.c
|
@ -1049,57 +1049,39 @@ static void say_filetype(int attr)
|
||||||
|
|
||||||
static int ft_play_dirname(char* name)
|
static int ft_play_dirname(char* name)
|
||||||
{
|
{
|
||||||
char dirname_mp3_filename[MAX_PATH+1];
|
|
||||||
|
|
||||||
#if CONFIG_CODEC != SWCODEC
|
#if CONFIG_CODEC != SWCODEC
|
||||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(dirname_mp3_filename, sizeof(dirname_mp3_filename), "%s/%s/%s",
|
if(talk_file(tc.currdir, name, dir_thumbnail_name, NULL,
|
||||||
tc.currdir[1] ? tc.currdir : "" , name,
|
NULL, false))
|
||||||
dir_thumbnail_name);
|
|
||||||
|
|
||||||
DEBUGF("Checking for %s\n", dirname_mp3_filename);
|
|
||||||
|
|
||||||
if (!file_exists(dirname_mp3_filename))
|
|
||||||
{
|
{
|
||||||
DEBUGF("Failed to find: %s\n", dirname_mp3_filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGF("Found: %s\n", dirname_mp3_filename);
|
|
||||||
|
|
||||||
talk_file(dirname_mp3_filename, false);
|
|
||||||
if(global_settings.talk_filetype)
|
if(global_settings.talk_filetype)
|
||||||
talk_id(VOICE_DIR, true);
|
talk_id(VOICE_DIR, true);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void ft_play_filename(char *dir, char *file)
|
static void ft_play_filename(char *dir, char *file)
|
||||||
{
|
{
|
||||||
char name_mp3_filename[MAX_PATH+1];
|
|
||||||
|
|
||||||
#if CONFIG_CODEC != SWCODEC
|
#if CONFIG_CODEC != SWCODEC
|
||||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)],
|
if (strlen(file) > strlen(file_thumbnail_ext)
|
||||||
|
&& strcasecmp(&file[strlen(file) - strlen(file_thumbnail_ext)],
|
||||||
file_thumbnail_ext))
|
file_thumbnail_ext))
|
||||||
{ /* file has no .talk extension */
|
/* file has no .talk extension */
|
||||||
snprintf(name_mp3_filename, sizeof(name_mp3_filename),
|
talk_file(dir, NULL, file, file_thumbnail_ext,
|
||||||
"%s/%s%s", dir, file, file_thumbnail_ext);
|
NULL, false);
|
||||||
|
|
||||||
talk_file(name_mp3_filename, false);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{ /* it already is a .talk file, play this directly */
|
/* it already is a .talk file, play this directly, but prefix it. */
|
||||||
snprintf(name_mp3_filename, sizeof(name_mp3_filename),
|
talk_file(dir, NULL, file, NULL,
|
||||||
"%s/%s", dir, file);
|
TALK_IDARRAY(LANG_VOICE_DIR_HOVER), false);
|
||||||
talk_id(LANG_VOICE_DIR_HOVER, false); /* prefix it */
|
|
||||||
talk_file(name_mp3_filename, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These two functions are called by the USB and shutdown handlers */
|
/* These two functions are called by the USB and shutdown handlers */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue