1
0
Fork 0
forked from len0rd/rockbox

Improvement for talking filenames: While loading the directory, already cache for which files are clips available. This avoids unsuccessful spinups while browsing.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5317 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jörg Hohensohn 2004-10-21 18:34:48 +00:00
parent a24bf1caef
commit 40ae63b4fc
5 changed files with 145 additions and 42 deletions

View file

@ -924,8 +924,16 @@ static bool voice_dirs(void)
static bool voice_files(void)
{
return set_option( str(LANG_VOICE_FILE),
int oldval = global_settings.talk_file;
bool ret;
ret = set_option( str(LANG_VOICE_FILE),
&global_settings.talk_file, INT, voice_names, 4, NULL);
if (oldval != 3 && global_settings.talk_file == 3)
{ /* force reload if newly talking thumbnails,
because the clip presence is cached only if enabled */
reload_directory();
}
return ret;
}
static bool voice_menu(void)

View file

@ -39,6 +39,7 @@
#define QUEUE_SIZE 64 /* must be a power of two */
#define QUEUE_MASK (QUEUE_SIZE-1)
const char* const dir_thumbnail_name = "_dirname.talk";
const char* const file_thumbnail_ext = ".talk";
/***************** Functional Macros *****************/

View file

@ -54,9 +54,9 @@ enum {
/* convenience macro to have both virtual pointer and ID as arguments */
#define STR(id) ID2P(id), id
/* publish this string, so it's stored only once (better than #define) */
/* publish these strings, so they're stored only once (better than #define) */
extern const char* const dir_thumbnail_name; /* "_dirname.talk" */
#define TALK_EXT ".talk" /* extra extension for file voicing */
extern const char* const file_thumbnail_ext; /* ".talk" for file voicing */
void talk_init(void);
int talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */

View file

@ -269,29 +269,19 @@ static int play_dirname(int start_index)
return 1;
}
static int play_filename(char *dir, char *file)
static void play_filename(char *dir, char *file)
{
int fd;
char name_mp3_filename[MAX_PATH+1];
if (mpeg_status() & MPEG_STATUS_PLAY)
return 0;
return;
if (strcasecmp(&file[strlen(file) - strlen(TALK_EXT)], TALK_EXT))
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" TALK_EXT, dir, file);
"%s/%s%s", dir, file, file_thumbnail_ext);
/* 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
@ -301,8 +291,6 @@ static int play_filename(char *dir, char *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)
@ -388,6 +376,94 @@ static void showfileline(int line, int direntry, bool scroll, const int *dirfilt
*dotpos = '.';
}
/* walk a directory and check all dircache entries if a .talk file exists */
void check_file_thumbnails(const char *dirname, int num_files)
{
int i;
struct dirent *entry;
DIR *dir;
dir = opendir(dirname);
if(!dir)
return;
for (i=0; i<num_files; i++) /* mark all files as non talking, except the .talk ones */
{
if (dircache[i].attr & ATTR_DIRECTORY)
continue; /* we're not touching directories */
if (strcasecmp(file_thumbnail_ext,
&dircache[i].name[strlen(dircache[i].name)
- strlen(file_thumbnail_ext)]))
{ /* no .talk file */
dircache[i].attr &= ~TREE_ATTR_THUMBNAIL; /* clear */
}
else
{ /* .talk file, we later let them speak themselves */
dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set */
}
}
while((entry = readdir(dir)) != 0) /* walk directory */
{
int ext_pos;
ext_pos = strlen(entry->d_name) - strlen(file_thumbnail_ext);
if (ext_pos <= 0 /* too short to carry ".talk" */
|| (entry->attribute & ATTR_DIRECTORY) /* no file */
|| strcasecmp(&entry->d_name[ext_pos], file_thumbnail_ext))
{ /* or doesn't end with ".talk", no candidate */
continue;
}
/* terminate the (disposable) name in dir buffer,
this truncates off the ".talk" without needing an extra buffer */
entry->d_name[ext_pos] = '\0';
/* search corresponding file in dir cache */
for (i=0; i<num_files; i++)
{
if (!strcasecmp(dircache[i].name, entry->d_name))
{ /* match */
dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set the flag */
break; /* exit search loop, because we found it */
}
}
}
closedir(dir);
}
/* check all dircache directories if they contain a "_dirname.talk" file */
#if 0 /* not practical, this is too slow */
void check_dir_thumbnails(const char *dirname, int num_files)
{
int i;
int fd;
char clipfile[MAX_PATH];
for (i=0; i<num_files; i++)
{
if (!(dircache[i].attr & ATTR_DIRECTORY))
continue; /* only directories are interesting */
/* compose pathname of directory name clip file */
snprintf(clipfile, sizeof(clipfile), "%s%s/%s",
dirname, dircache[i].name, dir_thumbnail_name);
fd = open(clipfile, O_RDONLY); /* check if exists */
if (fd >= 0)
{ /* there is one */
dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set the flag */
close(fd);
}
else
{ /* none found, clear the flag */
dircache[i].attr &= ~TREE_ATTR_THUMBNAIL;
}
}
}
#endif /* #if 0 */
/* load sorted directory into dircache. returns NULL on failure. */
struct entry* load_and_sort_directory(const char *dirname, const int *dirfilter,
int *num_files, bool *buffer_full)
@ -490,6 +566,14 @@ struct entry* load_and_sort_directory(const char *dirname, const int *dirfilter,
lastdir[sizeof(lastdir)-1] = 0;
qsort(dircache,i,sizeof(struct entry),compare);
/* If thumbnail talking is enabled, make an extra run to mark files with
associated thumbnails, so we don't do unsuccessful spinups later. */
if (global_settings.talk_file == 3)
check_file_thumbnails(dirname, i); /* map .talk to ours */
#if 0 /* not practical, this is too slow */
if (global_settings.talk_dir == 3)
check_dir_thumbnails(dirname, i); /* try in the directories */
#endif /* #if 0 */
return dircache;
}
@ -1375,13 +1459,10 @@ static bool dirbrowse(const char *root, const int *dirfilter)
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);
}
currdir, dircache[lasti].name, file_thumbnail_ext);
/* no fallback necessary, we knew in advance
that the file exists */
play_filename(currdir, dircache[lasti].name);
}
thumbnail_time = -1; /* job done */
}
@ -1501,20 +1582,30 @@ static bool dirbrowse(const char *root, const int *dirfilter)
talk_spell(dircache[i].name, false);
}
}
else if (global_settings.talk_file == 1) /* files as numbers */
else /* file */
{
int voicemethod = global_settings.talk_file;
if (voicemethod == 3) /* thumbnail clip */
{ /* "schedule" a thumbnail, to have a little delay */
if (dircache[i].attr & TREE_ATTR_THUMBNAIL)
{
thumbnail_time = current_tick + HOVER_DELAY;
}
else
{ /* say the number as fallback */
voicemethod = 1;
}
}
if (voicemethod == 1) /* files as numbers */
{
play_filenumber(i-dirsindir+1,
dircache[i].attr & TREE_ATTR_MASK);
}
else if (global_settings.talk_file == 2) /* files spelled */
else if (voicemethod == 2) /* files spelled */
{
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;
}
}
}

View file

@ -88,7 +88,10 @@ struct filetype {
};
/* using attribute not used by FAT */
/* using attribute bits not used by FAT (FAT uses lower 6) */
#define TREE_ATTR_THUMBNAIL 0x0080 /* corresponding .talk file exists */
/* (this also reflects the sort order if by type) */
#define TREE_ATTR_BMARK 0x0100 /* book mark file */
#define TREE_ATTR_M3U 0x0200 /* playlist */
@ -99,7 +102,7 @@ struct filetype {
#define TREE_ATTR_LNG 0x0700 /* binary lang file */
#define TREE_ATTR_ROCK 0x0800 /* binary rockbox plugin */
#define TREE_ATTR_MOD 0x0900 /* firmware file */
#define TREE_ATTR_MASK 0xFFC0 /* which bits tree.c uses (above) */
#define TREE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */
void tree_get_filetypes(const struct filetype**, int*);
void tree_init(void);