diff options
| author | Miika Pekkarinen <miipekk@ihme.org> | 2006-04-15 13:57:15 +0000 |
|---|---|---|
| committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-04-15 13:57:15 +0000 |
| commit | 75b6abb11411f5c27f9aa21329164e6ef16f9972 (patch) | |
| tree | 2c01722074c61cbbee34624a7d7d2658c3be58b5 | |
| parent | 16a57e2e4fcb29f84d6ce44a011d341378270c1f (diff) | |
| download | rockbox-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.c | 357 | ||||
| -rw-r--r-- | apps/tagtree.h | 12 | ||||
| -rw-r--r-- | apps/tree.c | 10 |
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; |