1
0
Fork 0
forked from len0rd/rockbox

Major improvement in playlist creation speed with tagcache. Fixed also

the sorting bug.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9592 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-04-10 10:26:24 +00:00
parent 2caad6fbc1
commit 58fe4dea05
5 changed files with 156 additions and 61 deletions

View file

@ -52,7 +52,11 @@ static long tempbuf_pos;
/* Tags we want to get sorted (loaded to the tempbuf). */
static const int sorted_tags[] = { tag_artist, tag_album, tag_genre, tag_composer, tag_title };
/* Uniqued tags (we can use these tags with filters and conditional clauses). */
static const int unique_tags[] = { tag_artist, tag_album, tag_genre, tag_composer };
/* Numeric tags (we can use these tags with conditional clauses). */
static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate };
/* Queue commands. */
@ -145,6 +149,32 @@ bool tagcache_is_numeric_tag(int type)
return false;
}
bool tagcache_is_unique_tag(int type)
{
int i;
for (i = 0; i < (int)(sizeof(unique_tags)/sizeof(unique_tags[0])); i++)
{
if (type == unique_tags[i])
return true;
}
return false;
}
bool tagcache_is_sorted_tag(int type)
{
int i;
for (i = 0; i < (int)(sizeof(sorted_tags)/sizeof(sorted_tags[0])); i++)
{
if (type == sorted_tags[i])
return true;
}
return false;
}
#ifdef HAVE_TC_RAMCACHE
static struct index_entry *find_entry_ram(const char *filename,
const struct dircache_entry *dc)
@ -324,21 +354,20 @@ static struct index_entry *find_entry_disk(const char *filename, bool retrieve)
return &idx;
}
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
static long tagcache_get_seek(const struct tagcache_search *tcs,
int tag, int idxid)
{
struct index_entry idx;
if (!tagcache_is_numeric_tag(tag))
return -1;
#ifdef HAVE_TC_RAMCACHE
if (tcs->ramsearch)
{
return hdr->indices[tcs->idx_id].tag_seek[tag];
return hdr->indices[idxid].tag_seek[tag];
}
#endif
lseek(tcs->masterfd, tcs->idx_id * sizeof(struct index_entry), SEEK_CUR);
lseek(tcs->masterfd, idxid * sizeof(struct index_entry)
+ sizeof(struct tagcache_header), SEEK_SET);
if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) !=
sizeof(struct index_entry))
{
@ -349,6 +378,15 @@ long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
return idx.tag_seek[tag];
}
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
{
if (!tagcache_is_numeric_tag(tag))
return -1;
return tagcache_get_seek(tcs, tag, tcs->idx_id);
}
static bool check_against_clause(long numeric, const char *str,
const struct tagcache_search_clause *clause)
{
@ -520,6 +558,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
return tcs->seek_list_count > 0;
}
bool tagcache_search(struct tagcache_search *tcs, int tag)
{
struct tagcache_header h;
@ -601,6 +640,9 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
if (tcs->filter_count == TAGCACHE_MAX_FILTERS)
return false;
if (!tagcache_is_unique_tag(tag) || tagcache_is_numeric_tag(tag))
return false;
tcs->filter_tag[tcs->filter_count] = tag;
tcs->filter_seek[tcs->filter_count] = seek;
tcs->filter_count++;
@ -699,6 +741,9 @@ bool tagcache_get_next(struct tagcache_search *tcs)
tcs->result = ep->tag_data;
tcs->result_len = ep->tag_length;
tcs->idx_id = ep->idx_id;
if (!tagcache_is_unique_tag(tcs->type))
tcs->result_seek = tcs->idx_id;
return true;
}
@ -732,6 +777,61 @@ bool tagcache_get_next(struct tagcache_search *tcs)
tcs->result = buf;
tcs->result_len = entry.tag_length;
tcs->idx_id = entry.idx_id;
if (!tagcache_is_unique_tag(tcs->type))
tcs->result_seek = tcs->idx_id;
return true;
}
bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
char *buf, long size)
{
struct tagfile_entry tfe;
long seek;
seek = tagcache_get_seek(tcs, tcs->type, idxid);
if (seek < 0)
{
logf("Retrieve failed");
return false;
}
if (tcs->idxfd[tcs->type] < 0)
{
char fn[MAX_PATH];
snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tcs->type);
tcs->idxfd[tcs->type] = open(fn, O_RDONLY);
}
if (tcs->idxfd[tcs->type] < 0)
{
logf("File not open!");
return false;
}
lseek(tcs->idxfd[tcs->type], seek, SEEK_SET);
if (read(tcs->idxfd[tcs->type], &tfe, sizeof(struct tagfile_entry)) !=
sizeof(struct tagfile_entry))
{
logf("read error");
return false;
}
if (tfe.tag_length >= size)
{
logf("too small buffer");
return false;
}
if (read(tcs->idxfd[tcs->type], buf, tfe.tag_length) !=
tfe.tag_length)
{
logf("read error #2");
return false;
}
buf[tfe.tag_length] = '\0';
return true;
}
@ -1154,32 +1254,6 @@ static int tempbuf_find_location(int id)
return entry->seek;
}
static bool is_unique_tag(int type)
{
int i;
for (i = 0; i < (int)(sizeof(unique_tags)/sizeof(unique_tags[0])); i++)
{
if (type == unique_tags[i])
return true;
}
return false;
}
static bool is_sorted_tag(int type)
{
int i;
for (i = 0; i < (int)(sizeof(sorted_tags)/sizeof(sorted_tags[0])); i++)
{
if (type == sorted_tags[i])
return true;
}
return false;
}
static bool build_numeric_index(int index_type, struct tagcache_header *h, int tmpfd)
{
struct tagcache_header tch;
@ -1318,7 +1392,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
* it entirely into memory so we can resort it later for use with
* chunked browsing.
*/
if (is_sorted_tag(index_type))
if (tagcache_is_sorted_tag(index_type))
{
for (i = 0; i < tch.entry_count; i++)
{
@ -1445,7 +1519,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
* Load new unique tags in memory to be sorted later and added
* to the master lookup file.
*/
if (is_sorted_tag(index_type))
if (tagcache_is_sorted_tag(index_type))
{
lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
/* h is the header of the temporary file containing new tags. */
@ -1478,7 +1552,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
goto error_exit;
}
if (is_unique_tag(index_type))
if (tagcache_is_unique_tag(index_type))
error = !tempbuf_unique_insert(buf, i);
else
error = !tempbuf_insert(buf, i, tch.entry_count + i);
@ -1563,7 +1637,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
}
/* Read entry headers. */
if (!is_sorted_tag(index_type))
if (!tagcache_is_sorted_tag(index_type))
{
struct temp_file_entry entry;
struct tagfile_entry fe;
@ -1634,7 +1708,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
}
/* Finally write the uniqued tag index file. */
if (is_sorted_tag(index_type))
if (tagcache_is_sorted_tag(index_type))
{
tch.magic = TAGCACHE_MAGIC;
tch.entry_count = tempbufidx;

View file

@ -43,7 +43,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
enum modifies { clause_mod_none, clause_mod_not };
enum modifiers { clause_mod_none, clause_mod_not };
struct tagcache_search_clause
{
@ -81,12 +81,16 @@ struct tagcache_search {
};
bool tagcache_is_numeric_tag(int type);
bool tagcache_is_unique_tag(int type);
bool tagcache_is_sorted_tag(int type);
bool tagcache_search(struct tagcache_search *tcs, int tag);
bool tagcache_search_add_filter(struct tagcache_search *tcs,
int tag, int seek);
bool tagcache_search_add_clause(struct tagcache_search *tcs,
struct tagcache_search_clause *clause);
bool tagcache_get_next(struct tagcache_search *tcs);
bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
char *buf, long size);
void tagcache_search_finish(struct tagcache_search *tcs);
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);

View file

@ -44,9 +44,6 @@
static int tagtree_play_folder(struct tree_context* c);
static const int numeric_tags[] = { tag_year, tag_length, tag_bitrate, tag_tracknumber };
static const int string_tags[] = { tag_artist, tag_title, tag_album, tag_composer, tag_genre };
static char searchstring[32];
struct tagentry {
char *name;
@ -702,32 +699,43 @@ static int tagtree_play_folder(struct tree_context* c)
{
struct tagentry *entry = (struct tagentry *)c->dircache;
int i;
char buf[MAX_PATH];
int last_tick = 0;
if (playlist_create(NULL, NULL) < 0) {
if (playlist_create(NULL, NULL) < 0)
{
logf("Failed creating playlist\n");
return -1;
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
cpu_boost(true);
#endif
for (i=0; i < c->filesindir; i++) {
tagcache_search(&tcs, tag_filename);
tagcache_search_add_filter(&tcs, tag_title, entry[i].newtable);
if (!tagcache_get_next(&tcs))
tagcache_search(&tcs, tag_filename);
for (i=0; i < c->filesindir; i++)
{
if (current_tick - last_tick > HZ/2)
{
tagcache_search_finish(&tcs);
continue ;
}
playlist_insert_track(NULL, tcs.result, PLAYLIST_INSERT, false);
tagcache_search_finish(&tcs);
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
cpu_boost(false);
gui_syncsplash(0, true, str(LANG_PLAYLIST_SEARCH_MSG), i,
#if CONFIG_KEYPAD == PLAYER_PAD
str(LANG_STOP_ABORT)
#else
str(LANG_OFF_ABORT)
#endif
);
if (SETTINGS_CANCEL == button_get(false))
break ;
last_tick = current_tick;
}
if (!tagcache_retrieve(&tcs, entry[i].newtable,
buf, sizeof buf))
{
continue;
}
playlist_insert_track(NULL, buf, PLAYLIST_INSERT, false);
}
tagcache_search_finish(&tcs);
cpu_boost(false);
if (global_settings.playlist_shuffle)
c->selected_item = playlist_shuffle(current_tick, c->selected_item);
@ -740,6 +748,13 @@ static int tagtree_play_folder(struct tree_context* c)
return 0;
}
char* tagtree_get_entryname(struct tree_context *c, int id)
{
char **buf = c->dircache;
return buf[id * (c->dentry_size/sizeof(int))];
}
#ifdef HAVE_LCD_BITMAP
const char* tagtree_get_icon(struct tree_context* c)
#else

View file

@ -30,6 +30,7 @@ void tagtree_init(void);
int tagtree_enter(struct tree_context* c);
void tagtree_exit(struct tree_context* c);
int tagtree_load(struct tree_context* c);
char* tagtree_get_entryname(struct tree_context *c, int id);
#ifdef HAVE_LCD_BITMAP
const char* tagtree_get_icon(struct tree_context* c);
#else

View file

@ -169,8 +169,9 @@ char * tree_get_filename(int selected_item, void * data, char *buffer)
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
if (id3db) {
char **buf = local_tc->dircache;
name = buf[selected_item * (local_tc->dentry_size/sizeof(int))];
return tagtree_get_entryname(&tc, selected_item);
//char **buf = local_tc->dircache;
//name = buf[selected_item * (local_tc->dentry_size/sizeof(int))];
}
else {
struct entry* dc = local_tc->dircache;