summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/tagnavi.config15
-rw-r--r--apps/tagtree.c105
2 files changed, 90 insertions, 30 deletions
diff --git a/apps/tagnavi.config b/apps/tagnavi.config
index ea12409396..55418718bf 100644
--- a/apps/tagnavi.config
+++ b/apps/tagnavi.config
@@ -1,16 +1,15 @@
1"Artists" artist : album : title = "%02d. %s" tracknum title 1"Artist" artist : album : title = "%02d. %s" tracknum title
2"Albums" album : title = "%02d. %s" tracknum title 2"Album" album : title = "%02d. %s" tracknum title
3"Genres" genre : artist : album : title = "%02d. %s" tracknum title 3"Genre" genre : artist : album : title = "%02d. %s" tracknum title
4"Composers" composer : album : title = "%02d. %s" tracknum title 4"Composer" composer : album : title = "%02d. %s" tracknum title
5"Tracks" title 5"Track" title
6"Year" year ? year > "1000" & year < "2008" : artist : album : title = "%02d. %s" tracknum title 6"Year" year ? year > "1000" & year < "2008" : artist : album : title = "%02d. %s" tracknum title
7"Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title 7"Search by artist" artist ? artist ~ "" : album : title = "%02d. %s" tracknum title
8"Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title 8"Search by album" album ? album ~ "" : title = "%02d. %s" tracknum title
9"Search by title" title ? title ~ "" 9"Search by title" title ? title ~ ""
10"Search by filename" filename ? filename ~ "" 10"Search by filename" filename ? filename ~ ""
11"Search by year" artist ? year = "" : album : title = "%02d. %s" tracknum title
12"Search by score" title = "(%3d) %s" autoscore title ? autoscore > "" 11"Search by score" title = "(%3d) %s" autoscore title ? autoscore > ""
13"Most played tracks" title = "(%2d) %s" playcount title ? playcount > "1" 12"Most played tracks" title = "(%3d) %s" playcount title %sort = "inverse" %limit = "100" ? playcount > "0"
14"Never played tracks" artist ? playcount == "0" : album : title = "%02d. %s" tracknum title 13"Never played tracks" artist ? playcount == "0" : album : title = "%02d. %s" tracknum title
15"Best tracks" artist ? playcount > "1" & autoscore > "85" : album : title = "%02d. %s (%3d)" tracknum title autoscore 14"Best tracks" artist ? playcount > "1" & autoscore > "85" : album : title = "%02d. %s (%3d)" tracknum title autoscore
16"List played tracks" title = "(%3d/%d) %s" autoscore playcount title ? playcount > "0" 15"List played tracks" title = "(%3d/%d) %s" autoscore playcount title ? playcount > "0"
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 6602e9ac24..08e6eb59b0 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -49,26 +49,40 @@ static int tagtree_play_folder(struct tree_context* c);
49 49
50static char searchstring[32]; 50static char searchstring[32];
51 51
52enum variables {
53 var_sorttype = 100,
54 var_limit
55};
56
52/* Capacity 10 000 entries (for example 10k different artists) */ 57/* Capacity 10 000 entries (for example 10k different artists) */
53#define UNIQBUF_SIZE (64*1024) 58#define UNIQBUF_SIZE (64*1024)
54static long *uniqbuf; 59static long *uniqbuf;
55 60
56#define MAX_TAGS 5 61#define MAX_TAGS 5
57 62
63static struct tagcache_search tcs, tcs2;
64static bool sort_inverse;
65
58/* 66/*
59 * "%3d. %s" autoscore title 67 * "%3d. %s" autoscore title %sort = "inverse" %limit = "100"
60 * 68 *
61 * valid = true 69 * valid = true
62 * formatstr = "%-3d. %s" 70 * formatstr = "%-3d. %s"
63 * tags[0] = tag_autoscore 71 * tags[0] = tag_autoscore
64 * tags[1] = tag_title 72 * tags[1] = tag_title
65 * tag_count = 2 73 * tag_count = 2
74 *
75 * limit = 100
76 * sort_inverse = true
66 */ 77 */
67struct display_format { 78struct display_format {
68 bool valid; 79 bool valid;
69 char formatstr[64]; 80 char formatstr[64];
70 int tags[MAX_TAGS]; 81 int tags[MAX_TAGS];
71 int tag_count; 82 int tag_count;
83
84 int limit;
85 bool sort_inverse;
72}; 86};
73 87
74struct search_instruction { 88struct search_instruction {
@@ -127,7 +141,7 @@ static int get_tag(int *tag)
127 while (*strp == ' ' && *strp != '\0') 141 while (*strp == ' ' && *strp != '\0')
128 strp++; 142 strp++;
129 143
130 if (*strp == '\0') 144 if (*strp == '\0' || *strp == '?' || *strp == ':')
131 return 0; 145 return 0;
132 146
133 for (i = 0; i < (int)sizeof(buf)-1; i++) 147 for (i = 0; i < (int)sizeof(buf)-1; i++)
@@ -151,6 +165,8 @@ static int get_tag(int *tag)
151 MATCH(tag, buf, "year", tag_year); 165 MATCH(tag, buf, "year", tag_year);
152 MATCH(tag, buf, "playcount", tag_playcount); 166 MATCH(tag, buf, "playcount", tag_playcount);
153 MATCH(tag, buf, "autoscore", tag_virt_autoscore); 167 MATCH(tag, buf, "autoscore", tag_virt_autoscore);
168 MATCH(tag, buf, "%sort", var_sorttype);
169 MATCH(tag, buf, "%limit", var_limit);
154 170
155 logf("NO MATCH: %s\n", buf); 171 logf("NO MATCH: %s\n", buf);
156 if (buf[0] == '?') 172 if (buf[0] == '?')
@@ -240,9 +256,27 @@ static bool add_clause(struct search_instruction *inst,
240 return true; 256 return true;
241} 257}
242 258
259static bool read_variable(char *buf, int size)
260{
261 int condition;
262
263 if (!get_clause(&condition))
264 return false;
265
266 if (condition != clause_is)
267 return false;
268
269 if (get_token_str(buf, size) < 0)
270 return false;
271
272 return true;
273}
274
275/* "%3d. %s" autoscore title %sort = "inverse" %limit = "100" */
243static int get_format_str(struct display_format *fmt) 276static int get_format_str(struct display_format *fmt)
244{ 277{
245 int ret; 278 int ret;
279 char buf[32];
246 280
247 memset(fmt, 0, sizeof(struct display_format)); 281 memset(fmt, 0, sizeof(struct display_format));
248 282
@@ -258,7 +292,23 @@ static int get_format_str(struct display_format *fmt)
258 if (ret == 0) 292 if (ret == 0)
259 break; 293 break;
260 294
261 fmt->tag_count++; 295 switch (fmt->tags[fmt->tag_count]) {
296 case var_sorttype:
297 if (!read_variable(buf, sizeof buf))
298 return -12;
299 if (!strcasecmp("inverse", buf))
300 fmt->sort_inverse = true;
301 break;
302
303 case var_limit:
304 if (!read_variable(buf, sizeof buf))
305 return -13;
306 fmt->limit = atoi(buf);
307 break;
308
309 default:
310 fmt->tag_count++;
311 }
262 } 312 }
263 313
264 fmt->valid = true; 314 fmt->valid = true;
@@ -268,8 +318,6 @@ static int get_format_str(struct display_format *fmt)
268 318
269static int get_condition(struct search_instruction *inst) 319static int get_condition(struct search_instruction *inst)
270{ 320{
271 struct display_format format;
272 struct display_format *fmt = NULL;
273 int tag; 321 int tag;
274 int condition; 322 int condition;
275 char buf[32]; 323 char buf[32];
@@ -277,13 +325,12 @@ static int get_condition(struct search_instruction *inst)
277 switch (*strp) 325 switch (*strp)
278 { 326 {
279 case '=': 327 case '=':
280 if (get_format_str(&format) < 0) 328 if (get_format_str(&inst->format[inst->tagorder_count]) < 0)
281 { 329 {
282 logf("get_format_str() parser failed!"); 330 logf("get_format_str() parser failed!");
283 return -4; 331 return -4;
284 } 332 }
285 fmt = &format; 333 return 1;
286 break;
287 334
288 case '?': 335 case '?':
289 case ' ': 336 case ' ':
@@ -296,14 +343,6 @@ static int get_condition(struct search_instruction *inst)
296 return 0; 343 return 0;
297 } 344 }
298 345
299 if (fmt)
300 {
301 memcpy(&inst->format[inst->tagorder_count], fmt,
302 sizeof(struct display_format));
303 }
304 else
305 inst->format[inst->tagorder_count].valid = false;
306
307 if (get_tag(&tag) <= 0) 346 if (get_tag(&tag) <= 0)
308 return -1; 347 return -1;
309 348
@@ -362,14 +401,14 @@ static bool parse_search(struct search_instruction *inst, const char *str)
362 return true; 401 return true;
363} 402}
364 403
365
366static struct tagcache_search tcs, tcs2;
367
368static int compare(const void *p1, const void *p2) 404static int compare(const void *p1, const void *p2)
369{ 405{
370 struct tagentry *e1 = (struct tagentry *)p1; 406 struct tagentry *e1 = (struct tagentry *)p1;
371 struct tagentry *e2 = (struct tagentry *)p2; 407 struct tagentry *e2 = (struct tagentry *)p2;
372 408
409 if (sort_inverse)
410 return strncasecmp(e2->name, e1->name, MAX_PATH);
411
373 return strncasecmp(e1->name, e2->name, MAX_PATH); 412 return strncasecmp(e1->name, e2->name, MAX_PATH);
374} 413}
375 414
@@ -558,6 +597,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
558 int offset, bool init) 597 int offset, bool init)
559{ 598{
560 struct tagentry *dptr = (struct tagentry *)c->dircache; 599 struct tagentry *dptr = (struct tagentry *)c->dircache;
600 struct display_format *fmt;
561 int i; 601 int i;
562 int namebufused = 0; 602 int namebufused = 0;
563 int total_count = 0; 603 int total_count = 0;
@@ -565,6 +605,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
565 int level = c->currextra; 605 int level = c->currextra;
566 int tag; 606 int tag;
567 bool sort = false; 607 bool sort = false;
608 int sort_limit = 0;
568 609
569 if (init 610 if (init
570#ifdef HAVE_TC_RAMCACHE 611#ifdef HAVE_TC_RAMCACHE
@@ -625,6 +666,17 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
625 current_offset = offset; 666 current_offset = offset;
626 current_entry_count = 0; 667 current_entry_count = 0;
627 c->dirfull = false; 668 c->dirfull = false;
669 fmt = &csi->format[level];
670 if (fmt->valid)
671 {
672 sort_inverse = fmt->sort_inverse;
673 sort_limit = fmt->limit;
674 }
675 else
676 {
677 sort_inverse = false;
678 sort_limit = 0;
679 }
628 680
629 if (tag != tag_title && tag != tag_filename) 681 if (tag != tag_title && tag != tag_filename)
630 { 682 {
@@ -642,8 +694,6 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
642 694
643 while (tagcache_get_next(tcs)) 695 while (tagcache_get_next(tcs))
644 { 696 {
645 struct display_format *fmt = &csi->format[level];
646
647 if (total_count++ < offset) 697 if (total_count++ < offset)
648 continue; 698 continue;
649 699
@@ -664,7 +714,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
664 bool read_format = false; 714 bool read_format = false;
665 int fmtbuf_pos = 0; 715 int fmtbuf_pos = 0;
666 int parpos = 0; 716 int parpos = 0;
667 717
668 memset(buf, 0, sizeof buf); 718 memset(buf, 0, sizeof buf);
669 for (i = 0; fmt->formatstr[i] != '\0'; i++) 719 for (i = 0; fmt->formatstr[i] != '\0'; i++)
670 { 720 {
@@ -784,6 +834,17 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
784 } 834 }
785 835
786 tagcache_search_finish(tcs); 836 tagcache_search_finish(tcs);
837
838 if (!sort && (sort_inverse || sort_limit))
839 {
840 gui_syncsplash(HZ*4, true, str(LANG_INCREASE_DIR_BUFFER), total_count);
841 logf("Too small dir buffer");
842 return 0;
843 }
844
845 if (sort_limit)
846 total_count = MIN(total_count, sort_limit);
847
787 return total_count; 848 return total_count;
788} 849}
789 850