Tagcache: Don't show duplicate entries and automatically inherit

clauses for correct search results.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10746 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-08-25 13:22:46 +00:00
parent a3ba6725cb
commit e308064353
3 changed files with 86 additions and 41 deletions

View file

@ -631,6 +631,30 @@ static bool check_against_clause(long numeric, const char *str,
return false;
}
static bool add_uniqbuf(struct tagcache_search *tcs, long id)
{
int i;
/* If uniq buffer is not defined we must return true for search to work. */
if (tcs->unique_list == NULL)
return true;
for (i = 0; i < tcs->unique_list_count; i++)
{
/* Return false if entry is found. */
if (tcs->unique_list[i] == id)
return false;
}
if (tcs->unique_list_count < tcs->unique_list_capacity)
{
tcs->unique_list[i] = id;
tcs->unique_list_count++;
}
return true;
}
static bool build_lookup_list(struct tagcache_search *tcs)
{
struct index_entry entry;
@ -699,22 +723,16 @@ static bool build_lookup_list(struct tagcache_search *tcs)
if (j < tcs->clause_count)
continue ;
/* Add to the seek list if not already there. */
for (j = 0; j < tcs->seek_list_count; j++)
{
if (tcs->seek_list[j] == hdr->indices[i].tag_seek[tcs->type])
break ;
}
/* Add to the seek list if not already in uniq buffer. */
if (!add_uniqbuf(tcs, hdr->indices[i].tag_seek[tcs->type]))
continue;
/* Lets add it. */
if (j == tcs->seek_list_count)
{
tcs->seek_list[tcs->seek_list_count] =
hdr->indices[i].tag_seek[tcs->type];
tcs->seek_flags[tcs->seek_list_count] =
hdr->indices[i].flag;
tcs->seek_list_count++;
}
tcs->seek_list[tcs->seek_list_count] =
hdr->indices[i].tag_seek[tcs->type];
tcs->seek_flags[tcs->seek_list_count] =
hdr->indices[i].flag;
tcs->seek_list_count++;
}
tcs->seek_pos = i;
@ -783,22 +801,14 @@ static bool build_lookup_list(struct tagcache_search *tcs)
if (i < tcs->clause_count)
continue ;
/* Add to the seek list if not already there. */
for (i = 0; i < tcs->seek_list_count; i++)
{
if (tcs->seek_list[i] == entry.tag_seek[tcs->type])
break ;
}
/* Add to the seek list if not already in uniq buffer. */
if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type]))
continue;
/* Lets add it. */
if (i == tcs->seek_list_count)
{
tcs->seek_list[tcs->seek_list_count] =
entry.tag_seek[tcs->type];
tcs->seek_flags[tcs->seek_list_count] = entry.flag;
tcs->seek_list_count++;
}
tcs->seek_list[tcs->seek_list_count] = entry.tag_seek[tcs->type];
tcs->seek_flags[tcs->seek_list_count] = entry.flag;
tcs->seek_list_count++;
}
return tcs->seek_list_count > 0;
@ -913,6 +923,14 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
return true;
}
void tagcache_search_set_uniqbuf(struct tagcache_search *tcs,
void *buffer, long length)
{
tcs->unique_list = (unsigned long *)buffer;
tcs->unique_list_capacity = length / sizeof(*tcs->unique_list);
tcs->unique_list_count = 0;
}
bool tagcache_search_add_filter(struct tagcache_search *tcs,
int tag, int seek)
{
@ -932,12 +950,23 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
bool tagcache_search_add_clause(struct tagcache_search *tcs,
struct tagcache_search_clause *clause)
{
int i;
if (tcs->clause_count >= TAGCACHE_MAX_CLAUSES)
{
logf("Too many clauses");
return false;
}
/* Check if there is already a similar filter in present (filters are
* much faster than clauses).
*/
for (i = 0; i < tcs->filter_count; i++)
{
if (tcs->filter_tag[i] == clause->tag)
return true;
}
if (!tagcache_is_numeric_tag(clause->tag) && tcs->idxfd[clause->tag] < 0)
{
char buf[MAX_PATH];

View file

@ -51,13 +51,13 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
#define TAGFILE_ENTRY_AVG_LENGTH 16
/* How many entries to fetch to the seek table at once while searching. */
#define SEEK_LIST_SIZE 50
#define SEEK_LIST_SIZE 32
/* Always strict align entries for best performance and binary compatability. */
#define TAGCACHE_STRICT_ALIGN 1
#define TAGCACHE_MAX_FILTERS 3
#define TAGCACHE_MAX_CLAUSES 10
#define TAGCACHE_MAX_FILTERS 4
#define TAGCACHE_MAX_CLAUSES 16
/* Tag database files. */
#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
@ -116,6 +116,9 @@ struct tagcache_search {
int entry_count;
bool valid;
bool initialized;
long *unique_list;
int unique_list_capacity;
int unique_list_count;
/* Exported variables. */
bool ramsearch;
@ -133,6 +136,8 @@ bool tagcache_is_unique_tag(int type);
bool tagcache_is_sorted_tag(int type);
bool tagcache_find_index(struct tagcache_search *tcs, const char *filename);
bool tagcache_search(struct tagcache_search *tcs, int tag);
void tagcache_search_set_uniqbuf(struct tagcache_search *tcs,
void *buffer, long length);
bool tagcache_search_add_filter(struct tagcache_search *tcs,
int tag, int seek);
bool tagcache_search_add_clause(struct tagcache_search *tcs,

View file

@ -48,6 +48,11 @@
static int tagtree_play_folder(struct tree_context* c);
static char searchstring[32];
/* Capacity 10 000 entries (for example 10k different artists) */
#define UNIQBUF_SIZE (64*1024)
static long *uniqbuf;
#define MAX_TAGS 5
/*
@ -500,6 +505,7 @@ void tagtree_init(void)
}
close(fd);
uniqbuf = buffer_alloc(UNIQBUF_SIZE);
audio_set_track_buffer_event(tagtree_buffer_event);
audio_set_track_unbuffer_event(tagtree_unbuffer_event);
}
@ -566,16 +572,21 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
if (!tagcache_search(tcs, tag))
return -1;
for (i = 0; i < extra; i++)
{
tagcache_search_add_filter(tcs, csi->tagorder[i], csi->result_seek[i]);
sort = true;
}
/* Prevent duplicate entries in the search list. */
tagcache_search_set_uniqbuf(tcs, uniqbuf, UNIQBUF_SIZE);
for (i = 0; i < csi->clause_count[extra]; i++)
{
tagcache_search_add_clause(tcs, &csi->clause[extra][i]);
if (extra || csi->clause_count[0])
sort = true;
for (i = 0; i < extra; i++)
tagcache_search_add_filter(tcs, csi->tagorder[i], csi->result_seek[i]);
for (i = 0; i <= extra; i++)
{
int j;
for (j = 0; j < csi->clause_count[i]; j++)
tagcache_search_add_clause(tcs, &csi->clause[i][j]);
}
current_offset = offset;