diff --git a/apps/tagcache.c b/apps/tagcache.c index ca2421171b..38537b5ceb 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -538,6 +538,96 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx) return true; } +static bool open_files(struct tagcache_search *tcs, int tag) +{ + if (tcs->idxfd[tag] < 0) + { + char fn[MAX_PATH]; + + snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag); + tcs->idxfd[tag] = open(fn, O_RDONLY); + } + + if (tcs->idxfd[tag] < 0) + { + logf("File not open!"); + return false; + } + + return true; +} + +static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, + int tag, char *buf, long size) +{ + struct tagfile_entry tfe; + long seek; + + *buf = '\0'; + + if (tagcache_is_numeric_tag(tag)) + return false; + + seek = idx->tag_seek[tag]; + if (seek < 0) + { + logf("Retrieve failed"); + return false; + } + +#ifdef HAVE_TC_RAMCACHE + if (tcs->ramsearch) + { + struct tagfile_entry *ep; + +# ifdef HAVE_DIRCACHE + if (tag == tag_filename && idx->flag & FLAG_DIRCACHE) + { + dircache_copy_path((struct dircache_entry *)seek, + buf, size); + return true; + } + else +# endif + if (tag != tag_filename) + { + ep = (struct tagfile_entry *)&hdr->tags[tag][seek]; + strncpy(buf, ep->tag_data, size-1); + + return true; + } + } +#endif + + if (!open_files(tcs, tag)) + return false; + + lseek(tcs->idxfd[tag], seek, SEEK_SET); + if (read(tcs->idxfd[tag], &tfe, sizeof(struct tagfile_entry)) != + sizeof(struct tagfile_entry)) + { + logf("read error #5"); + return false; + } + + if (tfe.tag_length >= size) + { + logf("too small buffer"); + return false; + } + + if (read(tcs->idxfd[tag], buf, tfe.tag_length) != + tfe.tag_length) + { + logf("read error #6"); + return false; + } + + buf[tfe.tag_length] = '\0'; + + return true; +} + static long check_virtual_tags(int tag, const struct index_entry *idx) { long data = 0; @@ -671,6 +761,96 @@ static bool check_against_clause(long numeric, const char *str, return false; } +bool check_clauses(struct tagcache_search *tcs, + struct index_entry *idx, + struct tagcache_search_clause **clause, int count) +{ + int i; + +#ifdef HAVE_TC_RAMCACHE + if (tcs->ramsearch) + { + /* Go through all conditional clauses. */ + for (i = 0; i < count; i++) + { + struct tagfile_entry *tfe; + int seek; + char buf[256]; + char *str = NULL; + + seek = check_virtual_tags(clause[i]->tag, idx); + + if (!tagcache_is_numeric_tag(clause[i]->tag)) + { + if (clause[i]->tag == tag_filename) + { + retrieve(tcs, idx, tag_filename, buf, sizeof buf); + str = buf; + } + else + { + tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek]; + str = tfe->tag_data; + } + } + + if (!check_against_clause(seek, str, clause[i])) + return false; + } + } + else +#endif + { + /* Check for conditions. */ + for (i = 0; i < count; i++) + { + struct tagfile_entry tfe; + int seek; + char str[256]; + + seek = check_virtual_tags(clause[i]->tag, idx); + + memset(str, 0, sizeof str); + if (!tagcache_is_numeric_tag(clause[i]->tag)) + { + int fd = tcs->idxfd[clause[i]->tag]; + lseek(fd, seek, SEEK_SET); + read(fd, &tfe, sizeof(struct tagfile_entry)); + if (tfe.tag_length >= (int)sizeof(str)) + { + logf("Too long tag read!"); + break ; + } + + read(fd, str, tfe.tag_length); + + /* Check if entry has been deleted. */ + if (str[0] == '\0') + break; + } + + if (!check_against_clause(seek, str, clause[i])) + return false; + } + } + + return true; +} + +bool tagcache_check_clauses(struct tagcache_search *tcs, + struct tagcache_search_clause **clause, int count) +{ + struct index_entry idx; + + if (count == 0) + return true; + + if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true)) + return false; + + return check_clauses(tcs, &idx, clause, count); +} + static bool add_uniqbuf(struct tagcache_search *tcs, long id) { int i; @@ -713,18 +893,18 @@ static bool build_lookup_list(struct tagcache_search *tcs) for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) { + struct index_entry *idx = &hdr->indices[i]; if (tcs->seek_list_count == SEEK_LIST_SIZE) break ; /* Skip deleted files. */ - if (hdr->indices[i].flag & FLAG_DELETED) + if (idx->flag & FLAG_DELETED) continue; /* Go through all filters.. */ for (j = 0; j < tcs->filter_count; j++) { - if (hdr->indices[i].tag_seek[tcs->filter_tag[j]] != - tcs->filter_seek[j]) + if (idx->tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j]) { break ; } @@ -733,51 +913,17 @@ static bool build_lookup_list(struct tagcache_search *tcs) if (j < tcs->filter_count) continue ; - /* Go through all conditional clauses. */ - for (j = 0; j < tcs->clause_count; j++) - { - struct index_entry *idx = &hdr->indices[i]; - int seek; - char buf[256]; - char *str = NULL; - struct tagfile_entry *entry; - - seek = check_virtual_tags(tcs->clause[j]->tag, idx); - - if (!tagcache_is_numeric_tag(tcs->clause[j]->tag)) - { - if (tcs->clause[j]->tag == tag_filename) - { - int oldtype = tcs->type; - tcs->type = tag_filename; - tagcache_retrieve(tcs, i, buf, sizeof buf); - tcs->type = oldtype; - str = buf; - } - else - { - entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek]; - str = entry->tag_data; - } - } - - - if (!check_against_clause(seek, str, tcs->clause[j])) - break ; - } - - if (j < tcs->clause_count) - continue ; + /* Check for conditions. */ + if (!check_clauses(tcs, idx, tcs->clause, tcs->clause_count)) + continue; /* Add to the seek list if not already in uniq buffer. */ - if (!add_uniqbuf(tcs, hdr->indices[i].tag_seek[tcs->type])) + if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type])) continue; /* Lets add it. */ - 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[tcs->seek_list_count] = idx->tag_seek[tcs->type]; + tcs->seek_flags[tcs->seek_list_count] = idx->flag; tcs->seek_list_count++; } @@ -813,39 +959,8 @@ static bool build_lookup_list(struct tagcache_search *tcs) continue ; /* Check for conditions. */ - for (i = 0; i < tcs->clause_count; i++) - { - struct tagfile_entry tfe; - int seek; - char str[256]; - - seek = check_virtual_tags(tcs->clause[i]->tag, &entry); - - memset(str, 0, sizeof str); - if (!tagcache_is_numeric_tag(tcs->clause[i]->tag)) - { - int fd = tcs->idxfd[tcs->clause[i]->tag]; - lseek(fd, seek, SEEK_SET); - read(fd, &tfe, sizeof(struct tagfile_entry)); - if (tfe.tag_length >= (int)sizeof(str)) - { - logf("Too long tag read!"); - break ; - } - - read(fd, str, tfe.tag_length); - - /* Check if entry has been deleted. */ - if (str[0] == '\0') - break; - } - - if (!check_against_clause(seek, str, tcs->clause[i])) - break ; - } - - if (i < tcs->clause_count) - continue ; + if (!check_clauses(tcs, &entry, tcs->clause, tcs->clause_count)) + continue; /* Add to the seek list if not already in uniq buffer. */ if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type])) @@ -1025,25 +1140,6 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, return true; } -static bool open_files(struct tagcache_search *tcs) -{ - 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; - } - - return true; -} - #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ ? (flag & FLAG_DIRCACHE) : 1) @@ -1085,7 +1181,7 @@ static bool get_next(struct tagcache_search *tcs) if ((!tcs->ramsearch || !TAG_FILENAME_RAM(tcs)) && !tagcache_is_numeric_tag(tcs->type)) { - if (!open_files(tcs)) + if (!open_files(tcs, tcs->type)) return false; lseek(tcs->idxfd[tcs->type], tcs->seek_list[tcs->seek_list_count], SEEK_SET); @@ -1144,7 +1240,7 @@ static bool get_next(struct tagcache_search *tcs) else #endif { - if (!open_files(tcs)) + if (!open_files(tcs, tcs->type)) return false; tcs->result_seek = lseek(tcs->idxfd[tcs->type], 0, SEEK_CUR); @@ -1193,72 +1289,13 @@ bool tagcache_get_next(struct tagcache_search *tcs) bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, char *buf, long size) { - struct tagfile_entry tfe; struct index_entry idx; - long seek; *buf = '\0'; if (!get_index(tcs->masterfd, idxid, &idx, true)) return false; - seek = idx.tag_seek[tcs->type]; - if (seek < 0) - { - logf("Retrieve failed"); - return false; - } - -#ifdef HAVE_TC_RAMCACHE - if (tcs->ramsearch) - { - struct tagfile_entry *ep; - -# ifdef HAVE_DIRCACHE - if (tcs->type == tag_filename && hdr->indices[idxid].flag & FLAG_DIRCACHE) - { - dircache_copy_path((struct dircache_entry *)seek, - buf, size); - return true; - } - else -# endif - if (tcs->type != tag_filename) - { - ep = (struct tagfile_entry *)&hdr->tags[tcs->type][seek]; - strncpy(buf, ep->tag_data, size-1); - - return true; - } - } -#endif - - if (!open_files(tcs)) - 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 #5"); - 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 #6"); - return false; - } - - buf[tfe.tag_length] = '\0'; - - return true; + return retrieve(tcs, &idx, tcs->type, buf, size); } #if 0 @@ -2961,11 +2998,13 @@ static bool delete_entry(long idx_id) /* Skip the header block */ lseek(fd, myidx.tag_seek[tag] + sizeof(struct tagfile_entry), SEEK_SET); - + + /* Debug, print 10 first characters of the tag read(fd, buf, 10); buf[10]='\0'; logf("TAG:%s", buf); lseek(fd, -10, SEEK_CUR); + */ /* Write first data byte in tag as \0 */ write(fd, "", 1); diff --git a/apps/tagcache.h b/apps/tagcache.h index f2694cea1b..37423e63c8 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -98,7 +98,7 @@ struct tagcache_search_clause bool numeric; bool input; long numeric_data; - char str[128]; + char *str; }; struct tagcache_search { @@ -139,6 +139,8 @@ bool tagcache_is_numeric_tag(int type); 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_check_clauses(struct tagcache_search *tcs, + struct tagcache_search_clause **clause, int count); bool tagcache_search(struct tagcache_search *tcs, int tag); void tagcache_search_set_uniqbuf(struct tagcache_search *tcs, void *buffer, long length); diff --git a/apps/tagnavi.config b/apps/tagnavi.config index fdf66828af..191b4bdda5 100644 --- a/apps/tagnavi.config +++ b/apps/tagnavi.config @@ -5,6 +5,15 @@ # Instead, you can modify "/.rockbox/tagnavi_custom.config" which will never # get overwritten automatically. +# Basic format declarations +%format "fmt_title" "%02d. %s" tracknum title ? tracknum > "0" +%format "fmt_title" "%s" title +%format "fmt_mostplayed" "(%3d) %s" playcount title %sort = "inverse" %limit = "100" +%format "fmt_lastplayed" "%06d%s" lastplayed title %sort = "inverse" %limit = "99" %strip = "6" +%format "fmt_best_tracks" "%02d. %s (%3d)" tracknum title autoscore +%format "fmt_played" "(%3d/%d) %s" autoscore playcount title +%format "fmt_score" "(%3d) %s" autoscore title + # Include our custom menu %include "/.rockbox/tagnavi_custom.config" @@ -14,11 +23,11 @@ # Define the search sub menu %menu_start "search" "Search by..." -"Artist" -> artist ? artist ~ "" -> album -> title = "%02d. %s" tracknum title -"Album" -> album ? album ~ "" -> title = "%02d. %s" tracknum title +"Artist" -> artist ? artist ~ "" -> album -> title = "fmt_title" +"Album" -> album ? album ~ "" -> title = "fmt_title" "Title" -> title ? title ~ "" "Filename" -> filename ? filename ~ "" -"Score" -> title = "(%3d) %s" autoscore title ? autoscore > "" +"Score" -> title = "fmt_score" ? autoscore > "" # ^ An empy line ends the menu @@ -28,19 +37,20 @@ # Define the title of the main menu %menu_start "main" "Browse by..." -"Artist" -> artist -> album -> title = "%02d. %s" tracknum title -"Album" -> album -> title = "%02d. %s" tracknum title -"Genre" -> genre -> artist -> album -> title = "%02d. %s" tracknum title -"Composer" -> composer -> album -> title = "%02d. %s" tracknum title +"Artist" -> artist -> album -> title = "fmt_title" +"Album" -> album -> title = "fmt_title" +"Genre" -> genre -> artist -> album -> title = "fmt_title" +"Composer" -> composer -> album -> title = "fmt_title" "Track" -> title -"Year" -> year ? year > "1000" & year < "2008" -> artist -> album -> title = "%02d. %s" tracknum title +"Year" -> year ? year > "1000" & year < "2008" -> artist -> album -> title = "fmt_title" "Search..." ==> "search" -"Most played tracks" -> title = "(%3d) %s" playcount title %sort = "inverse" %limit = "100" ? playcount > "0" -"Last played tracks" -> title = "%06d%s" lastplayed title %sort = "inverse" %limit = "99" %strip = "6" ? playcount > "0" -"Never played tracks" -> artist ? playcount == "0" -> album -> title = "%02d. %s" tracknum title -"Best tracks" -> artist ? playcount > "1" & autoscore > "85" -> album -> title = "%02d. %s (%3d)" tracknum title autoscore -"List played tracks" -> title = "(%3d/%d) %s" autoscore playcount title ? playcount > "0" +"Most played tracks" -> title = "fmt_mostplayed" ? playcount > "0" +"Last played tracks" -> title = "fmt_lastplayed" ? playcount > "0" +"Never played tracks" -> artist ? playcount == "0" -> album -> title = "fmt_title" +"Best tracks" -> artist ? playcount > "1" & autoscore > "85" -> album -> title = "fmt_best_tracks" +"List played tracks" -> title = "fmt_played" ? playcount > "0" "Custom view..." ==> "custom" # And finally set main menu as our root menu %root_menu "main" + diff --git a/apps/tagtree.c b/apps/tagtree.c index d8d8597d68..a360098aee 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -56,6 +56,7 @@ enum variables { var_menu_start, var_include, var_rootmenu, + var_format, menu_next, menu_load, }; @@ -82,8 +83,11 @@ static bool sort_inverse; * sort_inverse = true */ struct display_format { - bool valid; - char formatstr[64]; + char name[32]; + struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES]; + int clause_count; + char *formatstr; + int group_id; int tags[MAX_TAGS]; int tag_count; @@ -92,12 +96,15 @@ struct display_format { bool sort_inverse; }; +static struct display_format *formats[TAGMENU_MAX_FMTS]; +static int format_count; + struct search_instruction { char name[64]; int tagorder[MAX_TAGS]; int tagorder_count; - struct tagcache_search_clause clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; - struct display_format format[MAX_TAGS]; + struct tagcache_search_clause *clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; + int format_id[MAX_TAGS]; int clause_count[MAX_TAGS]; int result_seek[MAX_TAGS]; }; @@ -130,6 +137,7 @@ static int root_menu; static int current_offset; static int current_entry_count; +static int format_count; static struct tree_context *tc; static int get_token_str(char *buf, int size) @@ -200,6 +208,7 @@ static int get_tag(int *tag) MATCH(tag, buf, "%menu_start", var_menu_start); MATCH(tag, buf, "%include", var_include); MATCH(tag, buf, "%root_menu", var_rootmenu); + MATCH(tag, buf, "%format", var_format); MATCH(tag, buf, "->", menu_next); MATCH(tag, buf, "==>", menu_load); @@ -249,45 +258,36 @@ static int get_clause(int *condition) return 0; } -static bool add_clause(struct search_instruction *inst, - int tag, int type, const char *str) +static bool read_clause(struct tagcache_search_clause *clause) { - int len = strlen(str); - struct tagcache_search_clause *clause; + char buf[256]; - if (inst->clause_count[inst->tagorder_count] >= TAGCACHE_MAX_CLAUSES) - { - logf("Too many clauses"); + if (get_tag(&clause->tag) <= 0) return false; - } - clause = &inst->clause[inst->tagorder_count] - [inst->clause_count[inst->tagorder_count]]; - if (len >= (int)sizeof(clause->str) - 1) - { - logf("Too long str in condition"); + if (get_clause(&clause->type) <= 0) return false; - } - clause->tag = tag; - clause->type = type; - if (len == 0) + if (get_token_str(buf, sizeof buf) < 0) + return false; + + clause->str = buffer_alloc(strlen(buf)+1); + strcpy(clause->str, buf); + + logf("got clause: %d/%d [%s]", clause->tag, clause->type, clause->str); + + if (*(clause->str) == '\0') clause->input = true; else clause->input = false; - if (tagcache_is_numeric_tag(tag)) + if (tagcache_is_numeric_tag(clause->tag)) { clause->numeric = true; - clause->numeric_data = atoi(str); + clause->numeric_data = atoi(clause->str); } else - { clause->numeric = false; - strcpy(clause->str, str); - } - - inst->clause_count[inst->tagorder_count]++; return true; } @@ -313,12 +313,38 @@ static int get_format_str(struct display_format *fmt) { int ret; char buf[128]; + int i; memset(fmt, 0, sizeof(struct display_format)); - if (get_token_str(fmt->formatstr, sizeof fmt->formatstr) < 0) + if (get_token_str(fmt->name, sizeof fmt->name) < 0) return -10; + /* Determine the group id */ + fmt->group_id = 0; + for (i = 0; i < format_count; i++) + { + if (!strcasecmp(formats[i]->name, fmt->name)) + { + fmt->group_id = formats[i]->group_id; + break; + } + + if (formats[i]->group_id > fmt->group_id) + fmt->group_id = formats[i]->group_id; + } + + if (i == format_count) + fmt->group_id++; + + logf("format: (%d) %s", fmt->group_id, fmt->name); + + if (get_token_str(buf, sizeof buf) < 0) + return -10; + + fmt->formatstr = buffer_alloc(strlen(buf) + 1); + strcpy(fmt->formatstr, buf); + while (fmt->tag_count < MAX_TAGS) { ret = get_tag(&fmt->tags[fmt->tag_count]); @@ -353,27 +379,79 @@ static int get_format_str(struct display_format *fmt) } } - fmt->valid = true; + return 1; +} + +static int add_format(const char *buf) +{ + strp = buf; + + if (formats[format_count] == NULL) + formats[format_count] = buffer_alloc(sizeof(struct display_format)); + + memset(formats[format_count], 0, sizeof(struct display_format)); + if (get_format_str(formats[format_count]) < 0) + { + logf("get_format_str() parser failed!"); + return -4; + } + + while (*strp != '\0' && *strp != '?') + strp++; + + if (*strp == '?') + { + int clause_count = 0; + strp++; + + while (1) + { + formats[format_count]->clause[clause_count] = + buffer_alloc(sizeof(struct tagcache_search_clause)); + + if (!read_clause(formats[format_count]->clause[clause_count])) + break; + + clause_count++; + } + + formats[format_count]->clause_count = clause_count; + } + + format_count++; return 1; } static int get_condition(struct search_instruction *inst) { - int tag; - int condition; + int clause_count; char buf[128]; switch (*strp) { case '=': - if (get_format_str(&inst->format[inst->tagorder_count]) < 0) + { + int i; + + if (get_token_str(buf, sizeof buf) < 0) + return -1; + + for (i = 0; i < format_count; i++) { - logf("get_format_str() parser failed!"); - return -4; + if (!strcasecmp(formats[i]->name, buf)) + break; } + + if (i == format_count) + { + logf("format not found: %s", buf); + return -2; + } + + inst->format_id[inst->tagorder_count] = formats[i]->group_id; return 1; - + } case '?': case ' ': case '&': @@ -384,17 +462,20 @@ static int get_condition(struct search_instruction *inst) return 0; } - if (get_tag(&tag) <= 0) + clause_count = inst->clause_count[inst->tagorder_count]; + if (clause_count >= TAGCACHE_MAX_CLAUSES) + { + logf("Too many clauses"); + return false; + } + + inst->clause[inst->tagorder_count][clause_count] = + buffer_alloc(sizeof(struct tagcache_search_clause)); + + if (!read_clause(inst->clause[inst->tagorder_count][clause_count])) return -1; - if (get_clause(&condition) <= 0) - return -2; - - if (get_token_str(buf, sizeof buf) < 0) - return -3; - - logf("got clause: %d/%d [%s]", tag, condition, buf); - add_clause(inst, tag, condition, buf); + inst->clause_count[inst->tagorder_count]++; return 1; } @@ -465,7 +546,9 @@ static bool parse_search(struct menu_entry *entry, const char *str) logf("tag: %d", inst->tagorder[inst->tagorder_count]); - while (get_condition(inst) > 0) ; + while ( (ret = get_condition(inst)) > 0 ) ; + if (ret < 0) + return false; inst->tagorder_count++; @@ -658,6 +741,13 @@ static bool parse_menu(const char *filename) switch (variable) { + case var_format: + if (add_format(strp) < 0) + { + logf("Format add fail: %s", data); + } + break; + case var_include: if (get_token_str(data, sizeof(data)) < 0) { @@ -731,9 +821,9 @@ static bool parse_menu(const char *filename) menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); - memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); } + memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); if (!parse_search(menu->items[menu->itemcount], buf)) continue; @@ -746,6 +836,7 @@ static bool parse_menu(const char *filename) void tagtree_init(void) { + format_count = 0; menu_count = 0; menu = NULL; root_menu = 0; @@ -852,14 +943,21 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, int j; for (j = 0; j < csi->clause_count[i]; j++) - tagcache_search_add_clause(tcs, &csi->clause[i][j]); + tagcache_search_add_clause(tcs, csi->clause[i][j]); } current_offset = offset; current_entry_count = 0; c->dirfull = false; - fmt = &csi->format[level]; - if (fmt->valid) + + fmt = NULL; + for (i = 0; i < format_count; i++) + { + if (formats[i]->group_id == csi->format_id[level]) + fmt = formats[i]; + } + + if (fmt) { sort_inverse = fmt->sort_inverse; sort_limit = fmt->limit; @@ -900,12 +998,27 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, else dptr->extraseek = tcs->result_seek; - if (!tcs->ramresult || fmt->valid) + fmt = NULL; + /* Check the format */ + for (i = 0; i < format_count; i++) + { + if (formats[i]->group_id != csi->format_id[level]) + continue; + + if (tagcache_check_clauses(tcs, formats[i]->clause, + formats[i]->clause_count)) + { + fmt = formats[i]; + break; + } + } + + if (!tcs->ramresult || fmt) { char buf[MAX_PATH]; int buf_pos = 0; - if (fmt->valid) + if (fmt) { char fmtbuf[8]; bool read_format = false; @@ -968,7 +1081,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, } dptr->name = &c->name_buffer[namebufused]; - if (fmt->valid) + if (fmt) namebufused += buf_pos; else namebufused += tcs->result_len; @@ -980,7 +1093,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, sort = false; break ; } - if (fmt->valid) + if (fmt) strcpy(dptr->name, buf); else strcpy(dptr->name, tcs->result); @@ -1192,7 +1305,7 @@ int tagtree_enter(struct tree_context* c) { for (j = 0; j < csi->clause_count[i]; j++) { - if (!csi->clause[i][j].input) + if (!csi->clause[i][j]->input) continue; rc = kbd_input(searchstring, sizeof(searchstring)); @@ -1202,11 +1315,11 @@ int tagtree_enter(struct tree_context* c) return 0; } - if (csi->clause[i][j].numeric) - csi->clause[i][j].numeric_data = atoi(searchstring); + if (csi->clause[i][j]->numeric) + csi->clause[i][j]->numeric_data = atoi(searchstring); else - strncpy(csi->clause[i][j].str, searchstring, - sizeof(csi->clause[i][j].str)-1); + strncpy(csi->clause[i][j]->str, searchstring, + sizeof(csi->clause[i][j]->str)-1); } } } @@ -1297,6 +1410,7 @@ bool insert_all_playlist(struct tree_context *c, int position, bool queue) int i; char buf[MAX_PATH]; int from, to, direction; + int files_left = c->filesindir; cpu_boost_id(true, CPUBOOSTID_TAGTREE); if (!tagcache_search(&tcs, tag_filename)) @@ -1321,7 +1435,8 @@ bool insert_all_playlist(struct tree_context *c, int position, bool queue) for (i = from; i != to; i += direction) { - if (!show_search_progress(false, i)) + /* Count back to zero */ + if (!show_search_progress(false, files_left--)) break; if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, diff --git a/apps/tagtree.h b/apps/tagtree.h index 9f570917f7..2c85bf90e1 100644 --- a/apps/tagtree.h +++ b/apps/tagtree.h @@ -25,6 +25,7 @@ #define TAGNAVI_VERSION "#! rockbox/tagbrowser/2.0" #define TAGMENU_MAX_ITEMS 64 #define TAGMENU_MAX_MENUS 16 +#define TAGMENU_MAX_FMTS 32 enum table { root = 1, navibrowse, allsubentries, playtrack };