summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-04-15 13:57:15 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-04-15 13:57:15 +0000
commit75b6abb11411f5c27f9aa21329164e6ef16f9972 (patch)
tree2c01722074c61cbbee34624a7d7d2658c3be58b5
parent16a57e2e4fcb29f84d6ce44a011d341378270c1f (diff)
downloadrockbox-75b6abb11411f5c27f9aa21329164e6ef16f9972.zip
rockbox-75b6abb11411f5c27f9aa21329164e6ef16f9972.tar.gz
rockbox-75b6abb11411f5c27f9aa21329164e6ef16f9972.tar.bz2
rockbox-75b6abb11411f5c27f9aa21329164e6ef16f9972.tar.xz
Proper chunked browsing support when dirbuffer limit is reached.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9681 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/tagtree.c357
-rw-r--r--apps/tagtree.h12
-rw-r--r--apps/tree.c10
3 files changed, 176 insertions, 203 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 1952878..ccf9261 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -45,12 +45,6 @@
static int tagtree_play_folder(struct tree_context* c);
static char searchstring[32];
-struct tagentry {
- char *name;
- int newtable;
- int extraseek;
-};
-
#define MAX_TAGS 5
struct search_instruction {
@@ -66,6 +60,9 @@ static struct search_instruction *si, *csi;
static int si_count = 0;
static const char *strp;
+static int current_offset;
+static int current_entry_count;
+
static int get_token_str(char *buf, int size)
{
/* Find the start. */
@@ -354,158 +351,200 @@ void tagtree_init(void)
audiobuf += sizeof(struct search_instruction) * si_count + 4;
}
-int tagtree_load(struct tree_context* c)
+bool show_search_progress(bool init, int count)
{
- int i;
- int namebufused = 0;
- struct tagentry *dptr = (struct tagentry *)c->dircache;
- bool sort = false;
- int last_tick;
-
- int table = c->currtable;
- int extra = c->currextra;
+ static int last_tick = 0;
- c->dentry_size = sizeof(struct tagentry);
-
- if (!table)
+ if (init)
{
- c->dirfull = false;
- table = root;
- c->currtable = table;
+ last_tick = current_tick;
+ return true;
}
+
+ if (current_tick - last_tick > HZ/2)
+ {
+ gui_syncsplash(0, true, str(LANG_PLAYLIST_SEARCH_MSG), count,
+#if CONFIG_KEYPAD == PLAYER_PAD
+ str(LANG_STOP_ABORT)
+#else
+ str(LANG_OFF_ABORT)
+#endif
+ );
+ if (SETTINGS_CANCEL == button_get(false))
+ return false;
+ last_tick = current_tick;
+ }
+
+ return true;
+}
- if (c->dirfull)
- table = chunked_next;
-
- switch (table) {
- case root: {
- for (i = 0; i < si_count; i++)
- {
- dptr->name = (si+i)->name;
- dptr->newtable = navibrowse;
- dptr->extraseek = i;
- dptr++;
- }
- c->dirlength = c->filesindir = i;
-
- return c->dirlength;
- }
-
- case navibrowse:
- logf("navibrowse...");
+int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
+ int offset, bool init)
+{
+ struct tagentry *dptr = (struct tagentry *)c->dircache;
+ int i;
+ int namebufused = 0;
+ int total_count = 0;
+ int extra = c->currextra;
+ bool sort = false;
+
+ if (init
#ifdef HAVE_TC_RAMCACHE
- if (!tagcache_is_ramcache())
+ && !tagcache_is_ramcache()
#endif
- gui_syncsplash(0, true, str(LANG_PLAYLIST_SEARCH_MSG),
- 0, csi->name);
+ )
+ {
+ show_search_progress(true, 0);
+ gui_syncsplash(0, true, str(LANG_PLAYLIST_SEARCH_MSG),
+ 0, csi->name);
+ }
- tagcache_search(&tcs, csi->tagorder[extra]);
- for (i = 0; i < extra; i++)
- {
- tagcache_search_add_filter(&tcs, csi->tagorder[i], csi->result_seek[i]);
- sort = true;
- }
-
- for (i = 0; i < csi->clause_count[extra]; i++)
- {
- tagcache_search_add_clause(&tcs, &csi->clause[extra][i]);
- sort = true;
- }
- break;
-
- case chunked_next:
- logf("chunked next...");
- break;
-
- default:
- logf("Unsupported table %d\n", table);
- return -1;
+ tagcache_search(tcs, csi->tagorder[extra]);
+ for (i = 0; i < extra; i++)
+ {
+ tagcache_search_add_filter(tcs, csi->tagorder[i], csi->result_seek[i]);
+ sort = true;
}
- i = 0;
- namebufused = 0;
+ for (i = 0; i < csi->clause_count[extra]; i++)
+ {
+ tagcache_search_add_clause(tcs, &csi->clause[extra][i]);
+ sort = true;
+ }
+
+ current_offset = offset;
+ current_entry_count = 0;
c->dirfull = false;
- last_tick = current_tick;
- while (tagcache_get_next(&tcs))
+ while (tagcache_get_next(tcs))
{
- dptr->newtable = tcs.result_seek;
- if (!tcs.ramsearch || csi->tagorder[extra] == tag_title)
+ if (total_count++ < offset)
+ continue;
+
+ dptr->newtable = tcs->result_seek;
+ if (!tcs->ramsearch || csi->tagorder[extra] == tag_title)
{
int tracknum = -1;
dptr->name = &c->name_buffer[namebufused];
if (csi->tagorder[extra] == tag_title)
- tracknum = tagcache_get_numeric(&tcs, tag_tracknumber);
+ tracknum = tagcache_get_numeric(tcs, tag_tracknumber);
if (tracknum > 0)
{
snprintf(dptr->name, c->name_buffer_size - namebufused, "%02d. %s",
- tracknum, tcs.result);
+ tracknum, tcs->result);
namebufused += strlen(dptr->name) + 1;
if (namebufused >= c->name_buffer_size)
{
- logf("buffer full, 1 entry missed.");
+ logf("chunk mode #1: %d", current_entry_count);
c->dirfull = true;
+ sort = false;
break ;
}
}
else
{
- namebufused += tcs.result_len;
+ namebufused += tcs->result_len;
if (namebufused >= c->name_buffer_size)
{
- logf("buffer full, 1 entry missed.");
+ logf("chunk mode #2: %d", current_entry_count);
c->dirfull = true;
+ sort = false;
break ;
}
- strcpy(dptr->name, tcs.result);
+ strcpy(dptr->name, tcs->result);
}
}
else
- dptr->name = tcs.result;
+ dptr->name = tcs->result;
dptr++;
- i++;
-
- /**
- * Estimate when we are running out of space so we can stop
- * and enabled chunked browsing without missing entries.
- */
- if (i >= global_settings.max_files_in_dir - 1
- || namebufused + 200 > c->name_buffer_size)
+ current_entry_count++;
+
+ if (current_entry_count >= global_settings.max_files_in_dir)
{
+ logf("chunk mode #3: %d", current_entry_count);
c->dirfull = true;
+ sort = false;
break ;
}
- if (!tcs.ramsearch && current_tick - last_tick > HZ/2)
+ if (init && !tcs->ramsearch)
{
- 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 (!show_search_progress(false, i))
+ {
+ tagcache_search_finish(tcs);
+ return current_entry_count;
+ }
}
}
-
+
if (sort)
- qsort(c->dircache, i, c->dentry_size, compare);
+ qsort(c->dircache, current_entry_count, c->dentry_size, compare);
- if (c->dirfull)
+ if (!init)
{
- dptr->name = "===>";
- dptr->newtable = chunked_next;
- dptr++;
- i++;
+ tagcache_search_finish(tcs);
+ return current_entry_count;
+ }
+
+ while (tagcache_get_next(tcs))
+ {
+ if (!tcs->ramsearch)
+ {
+ if (!show_search_progress(false, total_count))
+ break;
+ }
+ total_count++;
}
- else
- tagcache_search_finish(&tcs);
+ tagcache_search_finish(tcs);
+ return total_count;
+}
+
+int tagtree_load(struct tree_context* c)
+{
+ int i;
+ struct tagentry *dptr = (struct tagentry *)c->dircache;
+ int table = c->currtable;
+
+ c->dentry_size = sizeof(struct tagentry);
+
+ if (!table)
+ {
+ c->dirfull = false;
+ table = root;
+ c->currtable = table;
+ }
+
+ switch (table) {
+ case root: {
+ for (i = 0; i < si_count; i++)
+ {
+ dptr->name = (si+i)->name;
+ dptr->newtable = navibrowse;
+ dptr->extraseek = i;
+ dptr++;
+ }
+ c->dirlength = c->filesindir = i;
+ current_offset = 0;
+ current_entry_count = i;
+
+ return c->dirlength;
+ }
+
+ case navibrowse:
+ logf("navibrowse...");
+ i = retrieve_entries(c, &tcs, 0, true);
+ break;
+
+ default:
+ logf("Unsupported table %d\n", table);
+ return -1;
+ }
+
+
+ /* The _total_ numer of entries available. */
c->dirlength = c->filesindir = i;
return i;
@@ -514,17 +553,10 @@ int tagtree_load(struct tree_context* c)
int tagtree_enter(struct tree_context* c)
{
int rc = 0;
- struct tagentry *dptr = (struct tagentry *)c->dircache;
+ struct tagentry *dptr;
int newextra;
- dptr += c->selected_item;
-
- if (dptr->newtable == chunked_next)
- {
- c->selected_item=0;
- gui_synclist_select_item(&tree_lists, c->selected_item);
- return 0;
- }
+ dptr = tagtree_get_entry(c, c->selected_item);
c->dirfull = false;
newextra = dptr->newtable;
@@ -618,9 +650,9 @@ void tagtree_exit(struct tree_context* c)
int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
{
- struct tagentry *entry = (struct tagentry *)c->dircache;
+ struct tagentry *entry;
- entry += c->selected_item;
+ entry = tagtree_get_entry(c, c->selected_item);
tagcache_search(&tcs, tag_filename);
tagcache_search_add_filter(&tcs, tag_title, entry->newtable);
@@ -636,71 +668,11 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
return 0;
}
-
-#if 0
-bool tagtree_rename_tag(struct tree_context *c, const char *newtext)
-{
- struct tagentry *dptr = (struct tagentry *)c->dircache;
- int extra, extra2;
- int type;
-
- dptr += c->selected_item;
- extra = dptr->newtable;
- extra2 = dptr->extraseek;
-
- switch (c->currtable) {
- case allgenres:
- tagcache_search(&tcs, tag_title);
- tagcache_search_add_filter(&tcs, tag_genre, extra);
- type = tag_genre;
- break;
-
- case allalbums:
- tagcache_search(&tcs, tag_title);
- tagcache_search_add_filter(&tcs, tag_album, extra);
- type = tag_album;
- break;
-
- case allartists:
- tagcache_search(&tcs, tag_title);
- tagcache_search_add_filter(&tcs, tag_artist, extra);
- type = tag_artist;
- break;
-
- case artist4genres:
- tagcache_search(&tcs, tag_title);
- tagcache_search_add_filter(&tcs, tag_genre, extra);
- type = tag_artist;
- break;
-
- case albums4artist:
- tagcache_search(&tcs, tag_title);
- tagcache_search_add_filter(&tcs, tag_album, extra);
- tagcache_search_add_filter(&tcs, tag_artist, extra2);
- type = tag_album;
- break;
-
- default:
- logf("wrong table");
- return false;
- }
-
- while (tagcache_get_next(&tcs))
- {
- // tagcache_modify(&tcs, type, newtext);
- }
-
- tagcache_search_finish(&tcs);
- return true;
-}
-#endif
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)
{
@@ -712,21 +684,10 @@ static int tagtree_play_folder(struct tree_context* c)
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
- );
- if (SETTINGS_CANCEL == button_get(false))
- break ;
- last_tick = current_tick;
- }
+ if (!show_search_progress(false, i))
+ break;
- if (!tagcache_retrieve(&tcs, entry[i].newtable,
+ if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->newtable,
buf, sizeof buf))
{
continue;
@@ -748,11 +709,19 @@ static int tagtree_play_folder(struct tree_context* c)
return 0;
}
-char* tagtree_get_entryname(struct tree_context *c, int id)
+struct tagentry* tagtree_get_entry(struct tree_context *c, int id)
{
- char **buf = c->dircache;
-
- return buf[id * (c->dentry_size/sizeof(int))];
+ struct tagentry *entry = (struct tagentry *)c->dircache;
+ int realid = id - current_offset;
+
+ /* Load the next chunk if necessary. */
+ if (realid >= current_entry_count || realid < 0)
+ {
+ retrieve_entries(c, &tcs, MAX(0, id - (current_entry_count / 2)), false);
+ realid = id - current_offset;
+ }
+
+ return &entry[realid];
}
#ifdef HAVE_LCD_BITMAP
diff --git a/apps/tagtree.h b/apps/tagtree.h
index 204a028..f048b0e 100644
--- a/apps/tagtree.h
+++ b/apps/tagtree.h
@@ -22,15 +22,19 @@
#include "tagcache.h"
#include "tree.h"
-enum table {
- invalid, root, navibrowse,
- chunked_next };
+enum table { invalid, root, navibrowse };
+
+struct tagentry {
+ char *name;
+ int newtable;
+ int extraseek;
+};
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);
+struct tagentry* tagtree_get_entry(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 7f63b08..a1068c2 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -168,12 +168,12 @@ char * tree_get_filename(int selected_item, void * data, char *buffer)
int attr=0;
bool id3db = *(local_tc->dirfilter) == SHOW_ID3DB;
- if (id3db) {
- return tagtree_get_entryname(&tc, selected_item);
- //char **buf = local_tc->dircache;
- //name = buf[selected_item * (local_tc->dentry_size/sizeof(int))];
+ if (id3db)
+ {
+ return tagtree_get_entry(&tc, selected_item)->name;
}
- else {
+ else
+ {
struct entry* dc = local_tc->dircache;
struct entry* e = &dc[selected_item];
name = e->name;