From e72bcfec7e98f318381dfb31f51055f474dcc970 Mon Sep 17 00:00:00 2001 From: Justin Gan Date: Sat, 17 Aug 2013 16:45:14 +0200 Subject: [PATCH] AllTracks patch to allow custom sorting of the AllTracks database option --- apps/tagcache.c | 1175 +++++++++++++++++++++++++++---------------------------- apps/tagcache.h | 29 +- apps/tagtree.c | 115 +++++- apps/tagtree.h | 2 +- apps/tree.h | 1 + 5 files changed, 697 insertions(+), 625 deletions(-) mode change 100644 => 100755 apps/tagcache.c mode change 100644 => 100755 apps/tagcache.h mode change 100644 => 100755 apps/tagtree.c mode change 100644 => 100755 apps/tagtree.h mode change 100644 => 100755 apps/tree.h diff --git a/apps/tagcache.c b/apps/tagcache.c old mode 100644 new mode 100755 index 07d8d1d..55c7a34 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -1398,10 +1399,9 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs, } bool tagcache_search_add_clause(struct tagcache_search *tcs, - struct tagcache_search_clause *clause) + struct tagcache_search_clause *clause, + bool addfullclause) { - int i; - if (tcs->clause_count >= TAGCACHE_MAX_CLAUSES) { logf("Too many clauses"); @@ -1410,27 +1410,22 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, if (clause->type != clause_logical_or) { - /* Check if there is already a similar filter in present (filters are - * much faster than clauses). - */ - for (i = 0; i < tcs->filter_count; i++) - { - if (tcs->filter_tag[i] == clause->tag) - return true; - } - if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0) { char buf[MAX_PATH]; - - snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); + + snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); tcs->idxfd[clause->tag] = open(buf, O_RDONLY); } } - - tcs->clause[tcs->clause_count] = clause; - tcs->clause_count++; - + + // Only add the full clause if required + if (addfullclause) + { + tcs->clause[tcs->clause_count] = clause; + tcs->clause_count++; + } + return true; } diff --git a/apps/tagcache.h b/apps/tagcache.h old mode 100644 new mode 100755 index dbe1c92..ec3ec25 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -51,7 +51,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, #define IDX_BUF_DEPTH 64 /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ -#define TAGCACHE_MAGIC 0x5443480e +#define TAGCACHE_MAGIC 0x5443481e /* Dump store/restore header version 'TCSxx'. */ #define TAGCACHE_STATEFILE_MAGIC 0x54435301 @@ -79,7 +79,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, /* Idle time before committing events in the command queue. */ #define TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY HZ*2 -#define TAGCACHE_MAX_FILTERS 4 +#define TAGCACHE_MAX_FILTERS 5 #define TAGCACHE_MAX_CLAUSES 32 /* Tag database files. */ @@ -219,9 +219,10 @@ void tagcache_search_set_uniqbuf(struct tagcache_search *tcs, 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); + struct tagcache_search_clause *clause, + bool addfullclause); bool tagcache_get_next(struct tagcache_search *tcs); -bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, +bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, int tag, 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 old mode 100644 new mode 100755 index 417b6f2..971b121 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -68,6 +68,7 @@ struct tagentry { char* name; int newtable; int extraseek; + int strip; }; static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); @@ -106,11 +107,21 @@ enum variables { menu_load, }; +/* String presentation of the tags defined in tagcache.h. Must be in correct order! */ +static const char *tags_str[] = { "artist", "album", "genre", "title", + "filename", "composer", "comment", "albumartist", "grouping", "year", + "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", + "playtime", "lastplayed", "commitid", "mtime" }; + +/* String presentation of the clauses defined in tagcache.h. Must be in correct order! */ +/* static const char *clause_str[] = { "NONE", "=", "!=", ">", ">=", + "<", "<=", "~", "!~", "^", "!^", "$", "!$", "@" }; */ + /* Capacity 10 000 entries (for example 10k different artists) */ #define UNIQBUF_SIZE (64*1024) static long uniqbuf[UNIQBUF_SIZE / sizeof(long)]; -#define MAX_TAGS 5 +#define MAX_TAGS 8 #define MAX_MENU_ID_SIZE 32 static bool sort_inverse; @@ -1301,7 +1312,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) { struct tagcache_search tcs; struct display_format *fmt; - int i; + int i, j; int namebufused = 0; int total_count = 0; int special_entry_count = 0; @@ -1309,7 +1320,9 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) int tag; bool sort = false; int sort_limit; - int strip; + bool strip = false; + bool alltracks = false; + char all_tracks_fmt[MAX_PATH]; /* Show search progress straight away if the disk needs to spin up, otherwise show it after the normal 1/2 second delay */ @@ -1323,6 +1336,8 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) if (c->currtable == ALLSUBENTRIES) { + alltracks = true; /* cache flag defining whether this is the AllTracks menu */ + sort = true; /* default the all subentries to always sort */ tag = tag_title; level--; } @@ -1338,6 +1353,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) if (level || csi->clause_count[0] || TAGCACHE_IS_NUMERIC(tag)) sort = true; + /* Add filters for each parent level */ for (i = 0; i < level; i++) { if (TAGCACHE_IS_NUMERIC(csi->tagorder[i])) @@ -1349,7 +1365,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) cc.type = clause_is; cc.numeric = true; cc.numeric_data = csi->result_seek[i]; - tagcache_search_add_clause(&tcs, &cc); + tagcache_search_add_clause(&tcs, &cc, true); } else { @@ -1361,12 +1377,14 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) /* because tagcache saves the clauses, we need to lock the buffer * for the entire duration of the search */ tagtree_lock(); + + /* Add clauses for each level in the menu */ for (i = 0; i <= level; i++) { - 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], true); + } } current_offset = offset; @@ -1374,24 +1392,65 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) c->dirfull = false; fmt = NULL; - for (i = 0; i < format_count; i++) + if (alltracks) { - if (formats[i]->group_id == csi->format_id[level]) - fmt = formats[i]; + /* All Tracks format functionality */ + sort = true; + all_tracks_fmt[0] = '\0'; + + /* Construct the All format name by concatenating the menu level tags */ + for (i = 0; i <= level; i++) + { + strcat(all_tracks_fmt, tags_str[csi->tagorder[i]]); + strcat(all_tracks_fmt, "."); + } + strcat(all_tracks_fmt, "All"); + + /* look for any AllTracks format matching the derived format name */ + for (i = 0; i < format_count; i++) + { + if (!strcasecmp(formats[i]->name, all_tracks_fmt)) + { + /* add all possible clauses for all formats */ + fmt = formats[i]; + for (j = 0; j < fmt->clause_count; j++) + { + tagcache_search_add_clause(&tcs, fmt->clause[j], false); + } + } + } + } + else + { + /* Normal track format functionality */ + for (i = 0; i < format_count; i++) + { + if (formats[i]->group_id == csi->format_id[level]) + { + /* Ensure that tags from all clauses for the fmt are loaded */ + fmt = formats[i]; + for (j = 0; j < fmt->clause_count; j++) + { + tagcache_search_add_clause(&tcs, fmt->clause[j], false); + } + } + } } + /* The assigning of the sort_inverse and sort_limit fields here is a bit arbitrary since any + * track title can match any one of the associated formats, each of which can have a different + * set of values for the sort inverse and sort limit attributes. [JG] */ if (fmt) { sort_inverse = fmt->sort_inverse; sort_limit = fmt->limit; - strip = fmt->strip; sort = true; } else { + /* No global format */ sort_inverse = false; sort_limit = 0; - strip = 0; } /* lock buflib out due to possible yields */ @@ -1402,6 +1461,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) { if (offset == 0) { + /* Adds the option */ dptr->newtable = ALLSUBENTRIES; dptr->name = str(LANG_TAGNAVI_ALL_TRACKS); dptr++; @@ -1410,6 +1470,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) } if (offset <= 1) { + /* Adds the option */ dptr->newtable = NAVIBROWSE; dptr->name = str(LANG_TAGNAVI_RANDOM); dptr->extraseek = -1; @@ -1418,29 +1479,35 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) special_entry_count++; } - total_count += 2; + total_count += special_entry_count; } + /* Now cycle through each entry and apply any formatting */ while (tagcache_get_next(&tcs)) { if (total_count++ < offset) continue; - dptr->newtable = NAVIBROWSE; + dptr->strip = 0; /* set the default strip amount for this entry */ if (tag == tag_title || tag == tag_filename) { dptr->newtable = PLAYTRACK; dptr->extraseek = tcs.idx_id; } else + { + dptr->newtable = NAVIBROWSE; dptr->extraseek = tcs.result_seek; + } fmt = NULL; /* Check the format */ tagtree_lock(); for (i = 0; i < format_count; i++) { - if (formats[i]->group_id != csi->format_id[level]) + /* Handle the allsubentries case as well - look for format defined in all_tracks_fmt */ + if (((formats[i]->group_id != csi->format_id[level]) && !alltracks) || + (alltracks && strcasecmp(formats[i]->name, all_tracks_fmt))) continue; if (tagcache_check_clauses(&tcs, formats[i]->clause, @@ -1484,6 +1551,11 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) } else namebufused += strlen(dptr->name)+1; + + /* Set the strip amount for this track if the title was successfully formatted */ + dptr->strip = fmt->strip; + if (!strip && (fmt->strip > 0)) + strip = true; /* cached strip flag */ } else { @@ -1567,20 +1639,23 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) if (strip) { + /* Now perform strip based on the format applied to each track name */ dptr = get_entries(c); for (i = special_entry_count; i < current_entry_count; i++, dptr++) { - int len = strlen(dptr->name); + if (dptr->strip > 0) + { + int len = strlen(dptr->name); - if (len < strip) - continue; + if (len < dptr->strip) + continue; - dptr->name = &dptr->name[strip]; + dptr->name = &dptr->name[dptr->strip]; + } } } return total_count; - } static int load_root(struct tree_context *c) diff --git a/apps/tagtree.h b/apps/tagtree.h old mode 100644 new mode 100755 index 8369020..76eaeed --- a/apps/tagtree.h +++ b/apps/tagtree.h @@ -29,7 +29,7 @@ #define TAGNAVI_VERSION "#! rockbox/tagbrowser/2.0" #define TAGMENU_MAX_ITEMS 64 #define TAGMENU_MAX_MENUS 32 -#define TAGMENU_MAX_FMTS 32 +#define TAGMENU_MAX_FMTS 98 bool tagtree_export(void); bool tagtree_import(void); diff --git a/apps/tree.h b/apps/tree.h old mode 100644 new mode 100755 index 70494f8..7dd95a9 --- a/apps/tree.h +++ b/apps/tree.h @@ -33,6 +33,7 @@ struct entry { char *name; int attr; /* FAT attributes + file type flags */ unsigned time_write; /* Last write time */ + int strip; }; #define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */ -- 1.7.5.4