diff options
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r-- | apps/tagtree.c | 233 |
1 files changed, 174 insertions, 59 deletions
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 { | |||
56 | var_menu_start, | 56 | var_menu_start, |
57 | var_include, | 57 | var_include, |
58 | var_rootmenu, | 58 | var_rootmenu, |
59 | var_format, | ||
59 | menu_next, | 60 | menu_next, |
60 | menu_load, | 61 | menu_load, |
61 | }; | 62 | }; |
@@ -82,8 +83,11 @@ static bool sort_inverse; | |||
82 | * sort_inverse = true | 83 | * sort_inverse = true |
83 | */ | 84 | */ |
84 | struct display_format { | 85 | struct display_format { |
85 | bool valid; | 86 | char name[32]; |
86 | char formatstr[64]; | 87 | struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES]; |
88 | int clause_count; | ||
89 | char *formatstr; | ||
90 | int group_id; | ||
87 | int tags[MAX_TAGS]; | 91 | int tags[MAX_TAGS]; |
88 | int tag_count; | 92 | int tag_count; |
89 | 93 | ||
@@ -92,12 +96,15 @@ struct display_format { | |||
92 | bool sort_inverse; | 96 | bool sort_inverse; |
93 | }; | 97 | }; |
94 | 98 | ||
99 | static struct display_format *formats[TAGMENU_MAX_FMTS]; | ||
100 | static int format_count; | ||
101 | |||
95 | struct search_instruction { | 102 | struct search_instruction { |
96 | char name[64]; | 103 | char name[64]; |
97 | int tagorder[MAX_TAGS]; | 104 | int tagorder[MAX_TAGS]; |
98 | int tagorder_count; | 105 | int tagorder_count; |
99 | struct tagcache_search_clause clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; | 106 | struct tagcache_search_clause *clause[MAX_TAGS][TAGCACHE_MAX_CLAUSES]; |
100 | struct display_format format[MAX_TAGS]; | 107 | int format_id[MAX_TAGS]; |
101 | int clause_count[MAX_TAGS]; | 108 | int clause_count[MAX_TAGS]; |
102 | int result_seek[MAX_TAGS]; | 109 | int result_seek[MAX_TAGS]; |
103 | }; | 110 | }; |
@@ -130,6 +137,7 @@ static int root_menu; | |||
130 | static int current_offset; | 137 | static int current_offset; |
131 | static int current_entry_count; | 138 | static int current_entry_count; |
132 | 139 | ||
140 | static int format_count; | ||
133 | static struct tree_context *tc; | 141 | static struct tree_context *tc; |
134 | 142 | ||
135 | static int get_token_str(char *buf, int size) | 143 | static int get_token_str(char *buf, int size) |
@@ -200,6 +208,7 @@ static int get_tag(int *tag) | |||
200 | MATCH(tag, buf, "%menu_start", var_menu_start); | 208 | MATCH(tag, buf, "%menu_start", var_menu_start); |
201 | MATCH(tag, buf, "%include", var_include); | 209 | MATCH(tag, buf, "%include", var_include); |
202 | MATCH(tag, buf, "%root_menu", var_rootmenu); | 210 | MATCH(tag, buf, "%root_menu", var_rootmenu); |
211 | MATCH(tag, buf, "%format", var_format); | ||
203 | MATCH(tag, buf, "->", menu_next); | 212 | MATCH(tag, buf, "->", menu_next); |
204 | MATCH(tag, buf, "==>", menu_load); | 213 | MATCH(tag, buf, "==>", menu_load); |
205 | 214 | ||
@@ -249,45 +258,36 @@ static int get_clause(int *condition) | |||
249 | return 0; | 258 | return 0; |
250 | } | 259 | } |
251 | 260 | ||
252 | static bool add_clause(struct search_instruction *inst, | 261 | static bool read_clause(struct tagcache_search_clause *clause) |
253 | int tag, int type, const char *str) | ||
254 | { | 262 | { |
255 | int len = strlen(str); | 263 | char buf[256]; |
256 | struct tagcache_search_clause *clause; | ||
257 | 264 | ||
258 | if (inst->clause_count[inst->tagorder_count] >= TAGCACHE_MAX_CLAUSES) | 265 | if (get_tag(&clause->tag) <= 0) |
259 | { | ||
260 | logf("Too many clauses"); | ||
261 | return false; | 266 | return false; |
262 | } | ||
263 | 267 | ||
264 | clause = &inst->clause[inst->tagorder_count] | 268 | if (get_clause(&clause->type) <= 0) |
265 | [inst->clause_count[inst->tagorder_count]]; | ||
266 | if (len >= (int)sizeof(clause->str) - 1) | ||
267 | { | ||
268 | logf("Too long str in condition"); | ||
269 | return false; | 269 | return false; |
270 | } | ||
271 | 270 | ||
272 | clause->tag = tag; | 271 | if (get_token_str(buf, sizeof buf) < 0) |
273 | clause->type = type; | 272 | return false; |
274 | if (len == 0) | 273 | |
274 | clause->str = buffer_alloc(strlen(buf)+1); | ||
275 | strcpy(clause->str, buf); | ||
276 | |||
277 | logf("got clause: %d/%d [%s]", clause->tag, clause->type, clause->str); | ||
278 | |||
279 | if (*(clause->str) == '\0') | ||
275 | clause->input = true; | 280 | clause->input = true; |
276 | else | 281 | else |
277 | clause->input = false; | 282 | clause->input = false; |
278 | 283 | ||
279 | if (tagcache_is_numeric_tag(tag)) | 284 | if (tagcache_is_numeric_tag(clause->tag)) |
280 | { | 285 | { |
281 | clause->numeric = true; | 286 | clause->numeric = true; |
282 | clause->numeric_data = atoi(str); | 287 | clause->numeric_data = atoi(clause->str); |
283 | } | 288 | } |
284 | else | 289 | else |
285 | { | ||
286 | clause->numeric = false; | 290 | clause->numeric = false; |
287 | strcpy(clause->str, str); | ||
288 | } | ||
289 | |||
290 | inst->clause_count[inst->tagorder_count]++; | ||
291 | 291 | ||
292 | return true; | 292 | return true; |
293 | } | 293 | } |
@@ -313,12 +313,38 @@ static int get_format_str(struct display_format *fmt) | |||
313 | { | 313 | { |
314 | int ret; | 314 | int ret; |
315 | char buf[128]; | 315 | char buf[128]; |
316 | int i; | ||
316 | 317 | ||
317 | memset(fmt, 0, sizeof(struct display_format)); | 318 | memset(fmt, 0, sizeof(struct display_format)); |
318 | 319 | ||
319 | if (get_token_str(fmt->formatstr, sizeof fmt->formatstr) < 0) | 320 | if (get_token_str(fmt->name, sizeof fmt->name) < 0) |
321 | return -10; | ||
322 | |||
323 | /* Determine the group id */ | ||
324 | fmt->group_id = 0; | ||
325 | for (i = 0; i < format_count; i++) | ||
326 | { | ||
327 | if (!strcasecmp(formats[i]->name, fmt->name)) | ||
328 | { | ||
329 | fmt->group_id = formats[i]->group_id; | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | if (formats[i]->group_id > fmt->group_id) | ||
334 | fmt->group_id = formats[i]->group_id; | ||
335 | } | ||
336 | |||
337 | if (i == format_count) | ||
338 | fmt->group_id++; | ||
339 | |||
340 | logf("format: (%d) %s", fmt->group_id, fmt->name); | ||
341 | |||
342 | if (get_token_str(buf, sizeof buf) < 0) | ||
320 | return -10; | 343 | return -10; |
321 | 344 | ||
345 | fmt->formatstr = buffer_alloc(strlen(buf) + 1); | ||
346 | strcpy(fmt->formatstr, buf); | ||
347 | |||
322 | while (fmt->tag_count < MAX_TAGS) | 348 | while (fmt->tag_count < MAX_TAGS) |
323 | { | 349 | { |
324 | ret = get_tag(&fmt->tags[fmt->tag_count]); | 350 | ret = get_tag(&fmt->tags[fmt->tag_count]); |
@@ -353,27 +379,79 @@ static int get_format_str(struct display_format *fmt) | |||
353 | } | 379 | } |
354 | } | 380 | } |
355 | 381 | ||
356 | fmt->valid = true; | 382 | return 1; |
383 | } | ||
384 | |||
385 | static int add_format(const char *buf) | ||
386 | { | ||
387 | strp = buf; | ||
388 | |||
389 | if (formats[format_count] == NULL) | ||
390 | formats[format_count] = buffer_alloc(sizeof(struct display_format)); | ||
391 | |||
392 | memset(formats[format_count], 0, sizeof(struct display_format)); | ||
393 | if (get_format_str(formats[format_count]) < 0) | ||
394 | { | ||
395 | logf("get_format_str() parser failed!"); | ||
396 | return -4; | ||
397 | } | ||
398 | |||
399 | while (*strp != '\0' && *strp != '?') | ||
400 | strp++; | ||
401 | |||
402 | if (*strp == '?') | ||
403 | { | ||
404 | int clause_count = 0; | ||
405 | strp++; | ||
406 | |||
407 | while (1) | ||
408 | { | ||
409 | formats[format_count]->clause[clause_count] = | ||
410 | buffer_alloc(sizeof(struct tagcache_search_clause)); | ||
411 | |||
412 | if (!read_clause(formats[format_count]->clause[clause_count])) | ||
413 | break; | ||
414 | |||
415 | clause_count++; | ||
416 | } | ||
417 | |||
418 | formats[format_count]->clause_count = clause_count; | ||
419 | } | ||
420 | |||
421 | format_count++; | ||
357 | 422 | ||
358 | return 1; | 423 | return 1; |
359 | } | 424 | } |
360 | 425 | ||
361 | static int get_condition(struct search_instruction *inst) | 426 | static int get_condition(struct search_instruction *inst) |
362 | { | 427 | { |
363 | int tag; | 428 | int clause_count; |
364 | int condition; | ||
365 | char buf[128]; | 429 | char buf[128]; |
366 | 430 | ||
367 | switch (*strp) | 431 | switch (*strp) |
368 | { | 432 | { |
369 | case '=': | 433 | case '=': |
370 | if (get_format_str(&inst->format[inst->tagorder_count]) < 0) | 434 | { |
435 | int i; | ||
436 | |||
437 | if (get_token_str(buf, sizeof buf) < 0) | ||
438 | return -1; | ||
439 | |||
440 | for (i = 0; i < format_count; i++) | ||
371 | { | 441 | { |
372 | logf("get_format_str() parser failed!"); | 442 | if (!strcasecmp(formats[i]->name, buf)) |
373 | return -4; | 443 | break; |
374 | } | 444 | } |
445 | |||
446 | if (i == format_count) | ||
447 | { | ||
448 | logf("format not found: %s", buf); | ||
449 | return -2; | ||
450 | } | ||
451 | |||
452 | inst->format_id[inst->tagorder_count] = formats[i]->group_id; | ||
375 | return 1; | 453 | return 1; |
376 | 454 | } | |
377 | case '?': | 455 | case '?': |
378 | case ' ': | 456 | case ' ': |
379 | case '&': | 457 | case '&': |
@@ -384,17 +462,20 @@ static int get_condition(struct search_instruction *inst) | |||
384 | return 0; | 462 | return 0; |
385 | } | 463 | } |
386 | 464 | ||
387 | if (get_tag(&tag) <= 0) | 465 | clause_count = inst->clause_count[inst->tagorder_count]; |
388 | return -1; | 466 | if (clause_count >= TAGCACHE_MAX_CLAUSES) |
467 | { | ||
468 | logf("Too many clauses"); | ||
469 | return false; | ||
470 | } | ||
389 | 471 | ||
390 | if (get_clause(&condition) <= 0) | 472 | inst->clause[inst->tagorder_count][clause_count] = |
391 | return -2; | 473 | buffer_alloc(sizeof(struct tagcache_search_clause)); |
392 | 474 | ||
393 | if (get_token_str(buf, sizeof buf) < 0) | 475 | if (!read_clause(inst->clause[inst->tagorder_count][clause_count])) |
394 | return -3; | 476 | return -1; |
395 | 477 | ||
396 | logf("got clause: %d/%d [%s]", tag, condition, buf); | 478 | inst->clause_count[inst->tagorder_count]++; |
397 | add_clause(inst, tag, condition, buf); | ||
398 | 479 | ||
399 | return 1; | 480 | return 1; |
400 | } | 481 | } |
@@ -465,7 +546,9 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
465 | 546 | ||
466 | logf("tag: %d", inst->tagorder[inst->tagorder_count]); | 547 | logf("tag: %d", inst->tagorder[inst->tagorder_count]); |
467 | 548 | ||
468 | while (get_condition(inst) > 0) ; | 549 | while ( (ret = get_condition(inst)) > 0 ) ; |
550 | if (ret < 0) | ||
551 | return false; | ||
469 | 552 | ||
470 | inst->tagorder_count++; | 553 | inst->tagorder_count++; |
471 | 554 | ||
@@ -658,6 +741,13 @@ static bool parse_menu(const char *filename) | |||
658 | 741 | ||
659 | switch (variable) | 742 | switch (variable) |
660 | { | 743 | { |
744 | case var_format: | ||
745 | if (add_format(strp) < 0) | ||
746 | { | ||
747 | logf("Format add fail: %s", data); | ||
748 | } | ||
749 | break; | ||
750 | |||
661 | case var_include: | 751 | case var_include: |
662 | if (get_token_str(data, sizeof(data)) < 0) | 752 | if (get_token_str(data, sizeof(data)) < 0) |
663 | { | 753 | { |
@@ -731,9 +821,9 @@ static bool parse_menu(const char *filename) | |||
731 | menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); | 821 | menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); |
732 | memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); | 822 | memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); |
733 | menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); | 823 | menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); |
734 | memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); | ||
735 | } | 824 | } |
736 | 825 | ||
826 | memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); | ||
737 | if (!parse_search(menu->items[menu->itemcount], buf)) | 827 | if (!parse_search(menu->items[menu->itemcount], buf)) |
738 | continue; | 828 | continue; |
739 | 829 | ||
@@ -746,6 +836,7 @@ static bool parse_menu(const char *filename) | |||
746 | 836 | ||
747 | void tagtree_init(void) | 837 | void tagtree_init(void) |
748 | { | 838 | { |
839 | format_count = 0; | ||
749 | menu_count = 0; | 840 | menu_count = 0; |
750 | menu = NULL; | 841 | menu = NULL; |
751 | root_menu = 0; | 842 | root_menu = 0; |
@@ -852,14 +943,21 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
852 | int j; | 943 | int j; |
853 | 944 | ||
854 | for (j = 0; j < csi->clause_count[i]; j++) | 945 | for (j = 0; j < csi->clause_count[i]; j++) |
855 | tagcache_search_add_clause(tcs, &csi->clause[i][j]); | 946 | tagcache_search_add_clause(tcs, csi->clause[i][j]); |
856 | } | 947 | } |
857 | 948 | ||
858 | current_offset = offset; | 949 | current_offset = offset; |
859 | current_entry_count = 0; | 950 | current_entry_count = 0; |
860 | c->dirfull = false; | 951 | c->dirfull = false; |
861 | fmt = &csi->format[level]; | 952 | |
862 | if (fmt->valid) | 953 | fmt = NULL; |
954 | for (i = 0; i < format_count; i++) | ||
955 | { | ||
956 | if (formats[i]->group_id == csi->format_id[level]) | ||
957 | fmt = formats[i]; | ||
958 | } | ||
959 | |||
960 | if (fmt) | ||
863 | { | 961 | { |
864 | sort_inverse = fmt->sort_inverse; | 962 | sort_inverse = fmt->sort_inverse; |
865 | sort_limit = fmt->limit; | 963 | sort_limit = fmt->limit; |
@@ -900,12 +998,27 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
900 | else | 998 | else |
901 | dptr->extraseek = tcs->result_seek; | 999 | dptr->extraseek = tcs->result_seek; |
902 | 1000 | ||
903 | if (!tcs->ramresult || fmt->valid) | 1001 | fmt = NULL; |
1002 | /* Check the format */ | ||
1003 | for (i = 0; i < format_count; i++) | ||
1004 | { | ||
1005 | if (formats[i]->group_id != csi->format_id[level]) | ||
1006 | continue; | ||
1007 | |||
1008 | if (tagcache_check_clauses(tcs, formats[i]->clause, | ||
1009 | formats[i]->clause_count)) | ||
1010 | { | ||
1011 | fmt = formats[i]; | ||
1012 | break; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | if (!tcs->ramresult || fmt) | ||
904 | { | 1017 | { |
905 | char buf[MAX_PATH]; | 1018 | char buf[MAX_PATH]; |
906 | int buf_pos = 0; | 1019 | int buf_pos = 0; |
907 | 1020 | ||
908 | if (fmt->valid) | 1021 | if (fmt) |
909 | { | 1022 | { |
910 | char fmtbuf[8]; | 1023 | char fmtbuf[8]; |
911 | bool read_format = false; | 1024 | bool read_format = false; |
@@ -968,7 +1081,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
968 | } | 1081 | } |
969 | 1082 | ||
970 | dptr->name = &c->name_buffer[namebufused]; | 1083 | dptr->name = &c->name_buffer[namebufused]; |
971 | if (fmt->valid) | 1084 | if (fmt) |
972 | namebufused += buf_pos; | 1085 | namebufused += buf_pos; |
973 | else | 1086 | else |
974 | namebufused += tcs->result_len; | 1087 | namebufused += tcs->result_len; |
@@ -980,7 +1093,7 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | |||
980 | sort = false; | 1093 | sort = false; |
981 | break ; | 1094 | break ; |
982 | } | 1095 | } |
983 | if (fmt->valid) | 1096 | if (fmt) |
984 | strcpy(dptr->name, buf); | 1097 | strcpy(dptr->name, buf); |
985 | else | 1098 | else |
986 | strcpy(dptr->name, tcs->result); | 1099 | strcpy(dptr->name, tcs->result); |
@@ -1192,7 +1305,7 @@ int tagtree_enter(struct tree_context* c) | |||
1192 | { | 1305 | { |
1193 | for (j = 0; j < csi->clause_count[i]; j++) | 1306 | for (j = 0; j < csi->clause_count[i]; j++) |
1194 | { | 1307 | { |
1195 | if (!csi->clause[i][j].input) | 1308 | if (!csi->clause[i][j]->input) |
1196 | continue; | 1309 | continue; |
1197 | 1310 | ||
1198 | rc = kbd_input(searchstring, sizeof(searchstring)); | 1311 | rc = kbd_input(searchstring, sizeof(searchstring)); |
@@ -1202,11 +1315,11 @@ int tagtree_enter(struct tree_context* c) | |||
1202 | return 0; | 1315 | return 0; |
1203 | } | 1316 | } |
1204 | 1317 | ||
1205 | if (csi->clause[i][j].numeric) | 1318 | if (csi->clause[i][j]->numeric) |
1206 | csi->clause[i][j].numeric_data = atoi(searchstring); | 1319 | csi->clause[i][j]->numeric_data = atoi(searchstring); |
1207 | else | 1320 | else |
1208 | strncpy(csi->clause[i][j].str, searchstring, | 1321 | strncpy(csi->clause[i][j]->str, searchstring, |
1209 | sizeof(csi->clause[i][j].str)-1); | 1322 | sizeof(csi->clause[i][j]->str)-1); |
1210 | } | 1323 | } |
1211 | } | 1324 | } |
1212 | } | 1325 | } |
@@ -1297,6 +1410,7 @@ bool insert_all_playlist(struct tree_context *c, int position, bool queue) | |||
1297 | int i; | 1410 | int i; |
1298 | char buf[MAX_PATH]; | 1411 | char buf[MAX_PATH]; |
1299 | int from, to, direction; | 1412 | int from, to, direction; |
1413 | int files_left = c->filesindir; | ||
1300 | 1414 | ||
1301 | cpu_boost_id(true, CPUBOOSTID_TAGTREE); | 1415 | cpu_boost_id(true, CPUBOOSTID_TAGTREE); |
1302 | if (!tagcache_search(&tcs, tag_filename)) | 1416 | if (!tagcache_search(&tcs, tag_filename)) |
@@ -1321,7 +1435,8 @@ bool insert_all_playlist(struct tree_context *c, int position, bool queue) | |||
1321 | 1435 | ||
1322 | for (i = from; i != to; i += direction) | 1436 | for (i = from; i != to; i += direction) |
1323 | { | 1437 | { |
1324 | if (!show_search_progress(false, i)) | 1438 | /* Count back to zero */ |
1439 | if (!show_search_progress(false, files_left--)) | ||
1325 | break; | 1440 | break; |
1326 | 1441 | ||
1327 | if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, | 1442 | if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, |