patch #978765 by Carsten Tschach, new option for voice filenames: every file may have an optional .talk companion, with a filename clip. While at it, I removed the "on enter" directory talking, nobody used it.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5194 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
6f9a7eb2c7
commit
d48442039e
6 changed files with 112 additions and 69 deletions
|
@ -2390,16 +2390,16 @@ voice: "als Zahl"
|
|||
new: "als Zahl"
|
||||
|
||||
id: LANG_VOICE_DIR_ENTER
|
||||
desc: "talkbox" mode for directories
|
||||
eng: "on enter"
|
||||
voice: "beim Betreten"
|
||||
new: "beim Betreten"
|
||||
desc: DEPRECATED
|
||||
eng: ""
|
||||
voice: ""
|
||||
new: ""
|
||||
|
||||
id: LANG_VOICE_DIR_HOVER
|
||||
desc: "talkbox" mode for directories
|
||||
eng: "while hovering"
|
||||
voice: "mit Zeiger"
|
||||
new: "mit Cursor"
|
||||
desc: "talkbox" mode for directories + files
|
||||
eng: ".talk mp3 clip"
|
||||
voice: "Sprachdatei"
|
||||
new: ".talk mp3 Datei"
|
||||
|
||||
id: VOICE_FILE
|
||||
desc: spoken only, prefix for file number
|
||||
|
|
|
@ -2404,15 +2404,15 @@ voice: "Numbers"
|
|||
new:
|
||||
|
||||
id: LANG_VOICE_DIR_ENTER
|
||||
desc: "talkbox" mode for directories
|
||||
eng: "on enter"
|
||||
voice: "on enter"
|
||||
desc: DEPRECATED
|
||||
eng: ""
|
||||
voice: ""
|
||||
new:
|
||||
|
||||
id: LANG_VOICE_DIR_HOVER
|
||||
desc: "talkbox" mode for directories
|
||||
eng: "while hovering"
|
||||
voice: "while hovering"
|
||||
desc: "talkbox" mode for directories + files
|
||||
eng: ".talk mp3 clip"
|
||||
voice: "talk mp3 clip"
|
||||
new:
|
||||
|
||||
id: VOICE_FILE
|
||||
|
|
|
@ -71,7 +71,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
|
|||
|
||||
|
||||
|
||||
#define CONFIG_BLOCK_VERSION 16
|
||||
#define CONFIG_BLOCK_VERSION 17
|
||||
#define CONFIG_BLOCK_SIZE 512
|
||||
#define RTC_BLOCK_SIZE 44
|
||||
|
||||
|
@ -150,6 +150,7 @@ Rest of config block, only saved to disk:
|
|||
static const char off_on[] = "off,on";
|
||||
static const char off_on_ask[] = "off,on,ask";
|
||||
static const char graphic_numeric[] = "graphic,numeric";
|
||||
static const char off_number_spell_hover[] = "off,number,spell,hover";
|
||||
|
||||
/* the part of the settings which ends up in the RTC RAM, where available
|
||||
(those we either need early, save frequently, or without spinup) */
|
||||
|
@ -319,8 +320,8 @@ static const struct bit_entry hd_bits[] =
|
|||
{1, S_O(line_in), false, "line in", off_on },
|
||||
#endif
|
||||
/* voice */
|
||||
{3, S_O(talk_dir), 0, "talk dir", "off,number,spell,enter,hover" },
|
||||
{2, S_O(talk_file), 0, "talk file", "off,number,spell" },
|
||||
{2, S_O(talk_dir), 0, "talk dir", off_number_spell_hover },
|
||||
{2, S_O(talk_file), 0, "talk file", off_number_spell_hover },
|
||||
{1, S_O(talk_menu), true, "talk menu", off_on },
|
||||
|
||||
/* If values are just added to the end, no need to bump the version. */
|
||||
|
|
|
@ -898,28 +898,24 @@ static bool voice_menus(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool voice_dirs(void)
|
||||
{
|
||||
static const struct opt_items names[] = {
|
||||
/* this is used 2 times below, so it saves memory to put it in global scope */
|
||||
static const struct opt_items voice_names[] = {
|
||||
{ STR(LANG_OFF) },
|
||||
{ STR(LANG_VOICE_NUMBER) },
|
||||
{ STR(LANG_VOICE_SPELL) },
|
||||
{ STR(LANG_VOICE_DIR_ENTER) },
|
||||
{ STR(LANG_VOICE_DIR_HOVER) }
|
||||
};
|
||||
};
|
||||
|
||||
static bool voice_dirs(void)
|
||||
{
|
||||
return set_option( str(LANG_VOICE_DIR),
|
||||
&global_settings.talk_dir, INT, names, 5, NULL);
|
||||
&global_settings.talk_dir, INT, voice_names, 4, NULL);
|
||||
}
|
||||
|
||||
static bool voice_files(void)
|
||||
{
|
||||
static const struct opt_items names[] = {
|
||||
{ STR(LANG_OFF) },
|
||||
{ STR(LANG_VOICE_NUMBER) },
|
||||
{ STR(LANG_VOICE_SPELL) }
|
||||
};
|
||||
return set_option( str(LANG_VOICE_FILE),
|
||||
&global_settings.talk_file, INT, names, 3, NULL);
|
||||
&global_settings.talk_file, INT, voice_names, 4, NULL);
|
||||
}
|
||||
|
||||
static bool voice_menu(void)
|
||||
|
|
|
@ -55,8 +55,8 @@ enum {
|
|||
#define STR(id) ID2P(id), id
|
||||
|
||||
/* publish this string, so it's stored only once (better than #define) */
|
||||
extern const char* const dir_thumbnail_name;
|
||||
|
||||
extern const char* const dir_thumbnail_name; /* "_dirname.talk" */
|
||||
#define TALK_EXT ".talk" /* extra extension for file voicing */
|
||||
|
||||
void talk_init(void);
|
||||
int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
|
||||
|
|
106
apps/tree.c
106
apps/tree.c
|
@ -221,6 +221,25 @@ static int build_playlist(int start_index)
|
|||
return start_index;
|
||||
}
|
||||
|
||||
static int play_filenumber(int pos, int attr)
|
||||
{
|
||||
/* try to find a voice ID for the extension, if known */
|
||||
unsigned int j;
|
||||
int ext_id = -1; /* default to none */
|
||||
for (j=0; j<sizeof(filetypes)/sizeof(*filetypes); j++)
|
||||
{
|
||||
if (attr == filetypes[j].tree_attr)
|
||||
{
|
||||
ext_id = filetypes[j].voiceclip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
talk_id(VOICE_FILE, false);
|
||||
talk_number(pos, true);
|
||||
talk_id(ext_id, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int play_dirname(int start_index)
|
||||
{
|
||||
|
@ -250,6 +269,41 @@ static int play_dirname(int start_index)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int play_filename(char *dir, char *file)
|
||||
{
|
||||
int fd;
|
||||
char name_mp3_filename[MAX_PATH+1];
|
||||
|
||||
if (mpeg_status() & MPEG_STATUS_PLAY)
|
||||
return 0;
|
||||
|
||||
if (strcasecmp(&file[strlen(file) - strlen(TALK_EXT)], TALK_EXT))
|
||||
{ /* file has no .talk extension */
|
||||
snprintf(name_mp3_filename, sizeof(name_mp3_filename),
|
||||
"%s/%s" TALK_EXT, dir, file);
|
||||
|
||||
/* check if a corresponding .talk file exists */
|
||||
DEBUGF("Checking for Filename Thumb %s\n", name_mp3_filename);
|
||||
fd = open(name_mp3_filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
DEBUGF("Failed to find: %s\n", name_mp3_filename);
|
||||
return -1;
|
||||
}
|
||||
DEBUGF("Found: %s\n", name_mp3_filename);
|
||||
close(fd);
|
||||
talk_file(name_mp3_filename, 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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int compare(const void* p1, const void* p2)
|
||||
{
|
||||
|
@ -771,7 +825,6 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
int lastdircursor=-1;
|
||||
bool need_update = true;
|
||||
bool exit_func = false;
|
||||
bool enqueue_next = false;
|
||||
long thumbnail_time = -1; /* for delaying a thumbnail */
|
||||
bool update_all = false; /* set this to true when the whole file list
|
||||
has been refreshed on screen */
|
||||
|
@ -926,14 +979,6 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
snprintf(buf,sizeof(buf),"/%s",file->name);
|
||||
|
||||
if (file->attr & ATTR_DIRECTORY) {
|
||||
if (global_settings.talk_dir == 3) /* enter */
|
||||
{
|
||||
/* play_dirname */
|
||||
DEBUGF("Playing directory thumbnail: %s", currdir);
|
||||
play_dirname(dircursor+dirstart);
|
||||
/* avoid reading getting cut by next filename */
|
||||
enqueue_next = true;
|
||||
}
|
||||
memcpy(currdir,buf,sizeof(currdir));
|
||||
if ( dirlevel < MAX_DIR_LEVELS ) {
|
||||
dirpos[dirlevel] = dirstart;
|
||||
|
@ -1306,6 +1351,8 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
TIME_AFTER(current_tick, thumbnail_time))
|
||||
{ /* a delayed hovering thumbnail is due now */
|
||||
int res;
|
||||
if (dircache[lasti].attr & ATTR_DIRECTORY)
|
||||
{
|
||||
DEBUGF("Playing directory thumbnail: %s", currdir);
|
||||
res = play_dirname(lasti);
|
||||
if (res < 0) /* failed, not existing */
|
||||
|
@ -1313,6 +1360,18 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
talk_id(VOICE_DIR, false);
|
||||
talk_number(lasti+1, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("Playing file thumbnail: %s/%s%s\n",
|
||||
currdir, dircache[lasti].name, TALK_EXT);
|
||||
res = play_filename(currdir, dircache[lasti].name);
|
||||
if (res < 0) /* failed, not existing */
|
||||
{ /* say the number instead, as a fallback */
|
||||
play_filenumber(lasti-dirsindir+1,
|
||||
dircache[lasti].attr);
|
||||
}
|
||||
}
|
||||
thumbnail_time = -1; /* job done */
|
||||
}
|
||||
status_draw(false);
|
||||
|
@ -1417,7 +1476,7 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
if (dircache[i].attr & ATTR_DIRECTORY) /* directory? */
|
||||
{
|
||||
/* play directory thumbnail */
|
||||
if (global_settings.talk_dir == 4) /* hover */
|
||||
if (global_settings.talk_dir == 3) /* hover */
|
||||
{ /* "schedule" a thumbnail, to have a little dalay */
|
||||
thumbnail_time = current_tick + HOVER_DELAY;
|
||||
}
|
||||
|
@ -1433,29 +1492,16 @@ static bool dirbrowse(const char *root, const int *dirfilter)
|
|||
}
|
||||
else if (global_settings.talk_file == 1) /* files as numbers */
|
||||
{
|
||||
/* try to find a voice ID for the extension, if known */
|
||||
unsigned int j;
|
||||
int ext_id = -1; /* default to none */
|
||||
for (j=0; j<sizeof(filetypes)/sizeof(*filetypes); j++)
|
||||
{
|
||||
if ((dircache[i].attr & TREE_ATTR_MASK) == filetypes[j].tree_attr)
|
||||
{
|
||||
ext_id = filetypes[j].voiceclip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* enqueue_next is true if still talking the dir name */
|
||||
talk_id(VOICE_FILE, enqueue_next);
|
||||
talk_number(i-dirsindir+1, true);
|
||||
talk_id(ext_id, true);
|
||||
enqueue_next = false;
|
||||
play_filenumber(i-dirsindir+1,
|
||||
dircache[i].attr & TREE_ATTR_MASK);
|
||||
}
|
||||
else if (global_settings.talk_file == 2) /* files spelled */
|
||||
{
|
||||
/* enqueue_next is true if still talking the dir name */
|
||||
talk_spell(dircache[i].name, enqueue_next);
|
||||
enqueue_next = false;
|
||||
talk_spell(dircache[i].name, false);
|
||||
}
|
||||
else if (global_settings.talk_file == 3) /* hover */
|
||||
{ /* "schedule" a thumbnail, to have a little dalay */
|
||||
thumbnail_time = current_tick + HOVER_DELAY;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue