summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-04-10 10:26:24 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-04-10 10:26:24 +0000
commit58fe4dea05f104111e8dfb5063df0d7aba504ea0 (patch)
tree72c3613274475f380bc76ccb097b559061a1e617
parent2caad6fbc112c7b0d8f54383e9406063661aa127 (diff)
downloadrockbox-58fe4dea05f104111e8dfb5063df0d7aba504ea0.zip
rockbox-58fe4dea05f104111e8dfb5063df0d7aba504ea0.tar.gz
rockbox-58fe4dea05f104111e8dfb5063df0d7aba504ea0.tar.bz2
rockbox-58fe4dea05f104111e8dfb5063df0d7aba504ea0.tar.xz
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
-rw-r--r--apps/tagcache.c148
-rw-r--r--apps/tagcache.h6
-rw-r--r--apps/tagtree.c51
-rw-r--r--apps/tagtree.h1
-rw-r--r--apps/tree.c5
5 files changed, 153 insertions, 58 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 3a6a78c..b6b12b7 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -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;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 794d2c0..2def028 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -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);
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 1756617..1952878 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -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);
+ tagcache_search(&tcs, tag_filename);
+ for (i=0; i < c->filesindir; i++)
+ {
+ 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
-
- 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))
+ );
+ 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);
-#endif
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
diff --git a/apps/tagtree.h b/apps/tagtree.h
index 2a275c8..204a028 100644
--- a/apps/tagtree.h
+++ b/apps/tagtree.h
@@ -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
diff --git a/apps/tree.c b/apps/tree.c
index 2777970..7f63b08 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -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;