diff --git a/apps/tagcache.c b/apps/tagcache.c index 3a6a78cc2f..b6b12b7035 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 794d2c04a4..2def028b7c 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 1756617629..195287862f 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); -#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)) + tagcache_search(&tcs, tag_filename); + for (i=0; i < c->filesindir; i++) + { + if (current_tick - last_tick > HZ/2) { - tagcache_search_finish(&tcs); - continue ; - } - playlist_insert_track(NULL, tcs.result, PLAYLIST_INSERT, false); - tagcache_search_finish(&tcs); - } - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - cpu_boost(false); + 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 (!tagcache_retrieve(&tcs, entry[i].newtable, + buf, sizeof buf)) + { + continue; + } + + playlist_insert_track(NULL, buf, PLAYLIST_INSERT, false); + } + tagcache_search_finish(&tcs); + cpu_boost(false); 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 2a275c89f8..204a028086 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 2777970d5f..7f63b08ddd 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;