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). */ /* 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 }; 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 }; 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 }; static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate };
/* Queue commands. */ /* Queue commands. */
@ -145,6 +149,32 @@ bool tagcache_is_numeric_tag(int type)
return false; 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 #ifdef HAVE_TC_RAMCACHE
static struct index_entry *find_entry_ram(const char *filename, static struct index_entry *find_entry_ram(const char *filename,
const struct dircache_entry *dc) const struct dircache_entry *dc)
@ -324,21 +354,20 @@ static struct index_entry *find_entry_disk(const char *filename, bool retrieve)
return &idx; 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; struct index_entry idx;
if (!tagcache_is_numeric_tag(tag))
return -1;
#ifdef HAVE_TC_RAMCACHE #ifdef HAVE_TC_RAMCACHE
if (tcs->ramsearch) if (tcs->ramsearch)
{ {
return hdr->indices[tcs->idx_id].tag_seek[tag]; return hdr->indices[idxid].tag_seek[tag];
} }
#endif #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)) != if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) !=
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]; 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, static bool check_against_clause(long numeric, const char *str,
const struct tagcache_search_clause *clause) 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; return tcs->seek_list_count > 0;
} }
bool tagcache_search(struct tagcache_search *tcs, int tag) bool tagcache_search(struct tagcache_search *tcs, int tag)
{ {
struct tagcache_header h; struct tagcache_header h;
@ -601,6 +640,9 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
if (tcs->filter_count == TAGCACHE_MAX_FILTERS) if (tcs->filter_count == TAGCACHE_MAX_FILTERS)
return false; return false;
if (!tagcache_is_unique_tag(tag) || tagcache_is_numeric_tag(tag))
return false;
tcs->filter_tag[tcs->filter_count] = tag; tcs->filter_tag[tcs->filter_count] = tag;
tcs->filter_seek[tcs->filter_count] = seek; tcs->filter_seek[tcs->filter_count] = seek;
tcs->filter_count++; tcs->filter_count++;
@ -700,6 +742,9 @@ bool tagcache_get_next(struct tagcache_search *tcs)
tcs->result_len = ep->tag_length; tcs->result_len = ep->tag_length;
tcs->idx_id = ep->idx_id; tcs->idx_id = ep->idx_id;
if (!tagcache_is_unique_tag(tcs->type))
tcs->result_seek = tcs->idx_id;
return true; return true;
} }
else else
@ -732,6 +777,61 @@ bool tagcache_get_next(struct tagcache_search *tcs)
tcs->result = buf; tcs->result = buf;
tcs->result_len = entry.tag_length; tcs->result_len = entry.tag_length;
tcs->idx_id = entry.idx_id; 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; return true;
} }
@ -1154,32 +1254,6 @@ static int tempbuf_find_location(int id)
return entry->seek; 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) static bool build_numeric_index(int index_type, struct tagcache_header *h, int tmpfd)
{ {
struct tagcache_header tch; 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 * it entirely into memory so we can resort it later for use with
* chunked browsing. * chunked browsing.
*/ */
if (is_sorted_tag(index_type)) if (tagcache_is_sorted_tag(index_type))
{ {
for (i = 0; i < tch.entry_count; i++) 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 * Load new unique tags in memory to be sorted later and added
* to the master lookup file. * 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); lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
/* h is the header of the temporary file containing new tags. */ /* 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; goto error_exit;
} }
if (is_unique_tag(index_type)) if (tagcache_is_unique_tag(index_type))
error = !tempbuf_unique_insert(buf, i); error = !tempbuf_unique_insert(buf, i);
else else
error = !tempbuf_insert(buf, i, tch.entry_count + i); 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. */ /* Read entry headers. */
if (!is_sorted_tag(index_type)) if (!tagcache_is_sorted_tag(index_type))
{ {
struct temp_file_entry entry; struct temp_file_entry entry;
struct tagfile_entry fe; 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. */ /* 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.magic = TAGCACHE_MAGIC;
tch.entry_count = tempbufidx; 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, enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
clause_lteq, clause_contains, clause_begins_with, clause_ends_with }; 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 struct tagcache_search_clause
{ {
@ -81,12 +81,16 @@ struct tagcache_search {
}; };
bool tagcache_is_numeric_tag(int type); 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(struct tagcache_search *tcs, int tag);
bool tagcache_search_add_filter(struct tagcache_search *tcs, bool tagcache_search_add_filter(struct tagcache_search *tcs,
int tag, int seek); int tag, int seek);
bool tagcache_search_add_clause(struct tagcache_search *tcs, bool tagcache_search_add_clause(struct tagcache_search *tcs,
struct tagcache_search_clause *clause); struct tagcache_search_clause *clause);
bool tagcache_get_next(struct tagcache_search *tcs); 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); void tagcache_search_finish(struct tagcache_search *tcs);
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag); 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 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]; static char searchstring[32];
struct tagentry { struct tagentry {
char *name; char *name;
@ -702,32 +699,43 @@ static int tagtree_play_folder(struct tree_context* c)
{ {
struct tagentry *entry = (struct tagentry *)c->dircache; struct tagentry *entry = (struct tagentry *)c->dircache;
int i; 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"); logf("Failed creating playlist\n");
return -1; return -1;
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
cpu_boost(true); cpu_boost(true);
#endif
for (i=0; i < c->filesindir; i++) {
tagcache_search(&tcs, tag_filename); tagcache_search(&tcs, tag_filename);
tagcache_search_add_filter(&tcs, tag_title, entry[i].newtable); for (i=0; i < c->filesindir; i++)
{
if (!tagcache_get_next(&tcs)) if (current_tick - last_tick > HZ/2)
{
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))
{ {
tagcache_search_finish(&tcs);
continue; continue;
} }
playlist_insert_track(NULL, tcs.result, PLAYLIST_INSERT, false);
tagcache_search_finish(&tcs);
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ playlist_insert_track(NULL, buf, PLAYLIST_INSERT, false);
}
tagcache_search_finish(&tcs);
cpu_boost(false); cpu_boost(false);
#endif
if (global_settings.playlist_shuffle) if (global_settings.playlist_shuffle)
c->selected_item = playlist_shuffle(current_tick, c->selected_item); 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; 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 #ifdef HAVE_LCD_BITMAP
const char* tagtree_get_icon(struct tree_context* c) const char* tagtree_get_icon(struct tree_context* c)
#else #else

View file

@ -30,6 +30,7 @@ void tagtree_init(void);
int tagtree_enter(struct tree_context* c); int tagtree_enter(struct tree_context* c);
void tagtree_exit(struct tree_context* c); void tagtree_exit(struct tree_context* c);
int tagtree_load(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 #ifdef HAVE_LCD_BITMAP
const char* tagtree_get_icon(struct tree_context* c); const char* tagtree_get_icon(struct tree_context* c);
#else #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; bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
if (id3db) { if (id3db) {
char **buf = local_tc->dircache; return tagtree_get_entryname(&tc, selected_item);
name = buf[selected_item * (local_tc->dentry_size/sizeof(int))]; //char **buf = local_tc->dircache;
//name = buf[selected_item * (local_tc->dentry_size/sizeof(int))];
} }
else { else {
struct entry* dc = local_tc->dircache; struct entry* dc = local_tc->dircache;