diff options
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r-- | apps/tagtree.c | 229 |
1 files changed, 181 insertions, 48 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c index 0d4330bac8..5766d2892e 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "storage.h" | 53 | #include "storage.h" |
54 | #include "dir.h" | 54 | #include "dir.h" |
55 | #include "playback.h" | 55 | #include "playback.h" |
56 | #include "panic.h" | ||
56 | 57 | ||
57 | #define str_or_empty(x) (x ? x : "(NULL)") | 58 | #define str_or_empty(x) (x ? x : "(NULL)") |
58 | 59 | ||
@@ -60,6 +61,17 @@ | |||
60 | 61 | ||
61 | static int tagtree_play_folder(struct tree_context* c); | 62 | static int tagtree_play_folder(struct tree_context* c); |
62 | 63 | ||
64 | /* this needs to be same size as struct entry (tree.h) and name needs to be | ||
65 | * the first; so that they're compatible enough to walk arrays of both | ||
66 | * derefencing the name member*/ | ||
67 | struct tagentry { | ||
68 | char* name; | ||
69 | int newtable; | ||
70 | int extraseek; | ||
71 | }; | ||
72 | |||
73 | static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); | ||
74 | |||
63 | #define SEARCHSTR_SIZE 256 | 75 | #define SEARCHSTR_SIZE 256 |
64 | 76 | ||
65 | enum table { | 77 | enum table { |
@@ -96,7 +108,7 @@ enum variables { | |||
96 | 108 | ||
97 | /* Capacity 10 000 entries (for example 10k different artists) */ | 109 | /* Capacity 10 000 entries (for example 10k different artists) */ |
98 | #define UNIQBUF_SIZE (64*1024) | 110 | #define UNIQBUF_SIZE (64*1024) |
99 | static long *uniqbuf; | 111 | static long uniqbuf[UNIQBUF_SIZE / sizeof(long)]; |
100 | 112 | ||
101 | #define MAX_TAGS 5 | 113 | #define MAX_TAGS 5 |
102 | #define MAX_MENU_ID_SIZE 32 | 114 | #define MAX_MENU_ID_SIZE 32 |
@@ -163,8 +175,8 @@ struct match | |||
163 | /* Statusbar text of the current view. */ | 175 | /* Statusbar text of the current view. */ |
164 | static char current_title[MAX_TAGS][128]; | 176 | static char current_title[MAX_TAGS][128]; |
165 | 177 | ||
166 | static struct menu_root *menus[TAGMENU_MAX_MENUS]; | 178 | static struct menu_root * menus[TAGMENU_MAX_MENUS]; |
167 | static struct menu_root *menu; | 179 | static struct menu_root * menu; |
168 | static struct search_instruction *csi; | 180 | static struct search_instruction *csi; |
169 | static const char *strp; | 181 | static const char *strp; |
170 | static int menu_count; | 182 | static int menu_count; |
@@ -176,8 +188,74 @@ static int current_entry_count; | |||
176 | static struct tree_context *tc; | 188 | static struct tree_context *tc; |
177 | 189 | ||
178 | /* a few memory alloc helper */ | 190 | /* a few memory alloc helper */ |
179 | static int tagtree_handle; | 191 | static int tagtree_handle, lock_count; |
180 | static size_t tagtree_bufsize, tagtree_buf_used; | 192 | static size_t tagtree_bufsize, tagtree_buf_used; |
193 | |||
194 | #define UPDATE(x, y) { x = (typeof(x))((char*)(x) + (y)); } | ||
195 | static int move_callback(int handle, void* current, void* new) | ||
196 | { | ||
197 | (void)handle; (void)current; (void)new; | ||
198 | ptrdiff_t diff = new - current; | ||
199 | |||
200 | if (lock_count > 0) | ||
201 | return BUFLIB_CB_CANNOT_MOVE; | ||
202 | |||
203 | UPDATE(menu, diff); | ||
204 | /* loop over menus */ | ||
205 | for(int i = 0; i < menu_count; i++) | ||
206 | { | ||
207 | struct menu_root* menu = menus[i]; | ||
208 | /* then over the menu_entries of a menu */ | ||
209 | for(int j = 0; j < menu->itemcount; j++) | ||
210 | { | ||
211 | struct menu_entry* mentry = menu->items[j]; | ||
212 | /* then over the search_instructions of each menu_entry */ | ||
213 | for(int k = 0; k < mentry->si.tagorder_count; k++) | ||
214 | { | ||
215 | for(int l = 0; l < mentry->si.clause_count[k]; l++) | ||
216 | { | ||
217 | UPDATE(mentry->si.clause[k][l]->str, diff); | ||
218 | UPDATE(mentry->si.clause[k][l], diff); | ||
219 | } | ||
220 | } | ||
221 | UPDATE(menu->items[j], diff); | ||
222 | } | ||
223 | UPDATE(menus[i], diff); | ||
224 | } | ||
225 | |||
226 | /* now the same game for formats */ | ||
227 | for(int i = 0; i < format_count; i++) | ||
228 | { | ||
229 | for(int j = 0; j < formats[i]->clause_count; j++) | ||
230 | { | ||
231 | UPDATE(formats[i]->clause[j]->str, diff); | ||
232 | UPDATE(formats[i]->clause[j], diff); | ||
233 | } | ||
234 | |||
235 | if (formats[i]->formatstr) | ||
236 | UPDATE(formats[i]->formatstr, diff); | ||
237 | |||
238 | UPDATE(formats[i], diff); | ||
239 | } | ||
240 | return BUFLIB_CB_OK; | ||
241 | } | ||
242 | #undef UPDATE | ||
243 | |||
244 | static inline void tagtree_lock(void) | ||
245 | { | ||
246 | lock_count++; | ||
247 | } | ||
248 | |||
249 | static inline void tagtree_unlock(void) | ||
250 | { | ||
251 | lock_count--; | ||
252 | } | ||
253 | |||
254 | static struct buflib_callbacks ops = { | ||
255 | .move_callback = move_callback, | ||
256 | .shrink_callback = NULL, | ||
257 | }; | ||
258 | |||
181 | static void* tagtree_alloc(size_t size) | 259 | static void* tagtree_alloc(size_t size) |
182 | { | 260 | { |
183 | char* buf = core_get_data(tagtree_handle) + tagtree_buf_used; | 261 | char* buf = core_get_data(tagtree_handle) + tagtree_buf_used; |
@@ -201,6 +279,7 @@ static char* tagtree_strdup(const char* buf) | |||
201 | return dest; | 279 | return dest; |
202 | } | 280 | } |
203 | 281 | ||
282 | /* save to call without locking */ | ||
204 | static int get_token_str(char *buf, int size) | 283 | static int get_token_str(char *buf, int size) |
205 | { | 284 | { |
206 | /* Find the start. */ | 285 | /* Find the start. */ |
@@ -510,7 +589,8 @@ static int add_format(const char *buf) | |||
510 | { | 589 | { |
511 | int clause_count = 0; | 590 | int clause_count = 0; |
512 | strp++; | 591 | strp++; |
513 | 592 | ||
593 | tagtree_lock(); | ||
514 | while (1) | 594 | while (1) |
515 | { | 595 | { |
516 | struct tagcache_search_clause *newclause; | 596 | struct tagcache_search_clause *newclause; |
@@ -529,6 +609,7 @@ static int add_format(const char *buf) | |||
529 | 609 | ||
530 | clause_count++; | 610 | clause_count++; |
531 | } | 611 | } |
612 | tagtree_unlock(); | ||
532 | 613 | ||
533 | formats[format_count]->clause_count = clause_count; | 614 | formats[format_count]->clause_count = clause_count; |
534 | } | 615 | } |
@@ -593,9 +674,14 @@ static int get_condition(struct search_instruction *inst) | |||
593 | strp++; | 674 | strp++; |
594 | new_clause->type = clause_logical_or; | 675 | new_clause->type = clause_logical_or; |
595 | } | 676 | } |
596 | else if (!read_clause(new_clause)) | 677 | else |
597 | return -1; | 678 | { |
598 | 679 | tagtree_lock(); | |
680 | bool ret = read_clause(new_clause); | ||
681 | tagtree_unlock(); | ||
682 | if (!ret) | ||
683 | return -1; | ||
684 | } | ||
599 | inst->clause_count[inst->tagorder_count]++; | 685 | inst->clause_count[inst->tagorder_count]++; |
600 | 686 | ||
601 | return 1; | 687 | return 1; |
@@ -616,7 +702,6 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
616 | struct search_instruction *inst = &entry->si; | 702 | struct search_instruction *inst = &entry->si; |
617 | char buf[MAX_PATH]; | 703 | char buf[MAX_PATH]; |
618 | int i; | 704 | int i; |
619 | struct menu_root *new_menu; | ||
620 | 705 | ||
621 | strp = str; | 706 | strp = str; |
622 | 707 | ||
@@ -654,8 +739,7 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
654 | 739 | ||
655 | /* Allocate a new menu unless link is found. */ | 740 | /* Allocate a new menu unless link is found. */ |
656 | menus[menu_count] = tagtree_alloc0(sizeof(struct menu_root)); | 741 | menus[menu_count] = tagtree_alloc0(sizeof(struct menu_root)); |
657 | new_menu = menus[menu_count]; | 742 | strlcpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE); |
658 | strlcpy(new_menu->id, buf, MAX_MENU_ID_SIZE); | ||
659 | entry->link = menu_count; | 743 | entry->link = menu_count; |
660 | ++menu_count; | 744 | ++menu_count; |
661 | 745 | ||
@@ -679,8 +763,11 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
679 | break ; | 763 | break ; |
680 | 764 | ||
681 | logf("tag: %d", inst->tagorder[inst->tagorder_count]); | 765 | logf("tag: %d", inst->tagorder[inst->tagorder_count]); |
682 | 766 | ||
767 | tagtree_lock(); | ||
683 | while ( (ret = get_condition(inst)) > 0 ) ; | 768 | while ( (ret = get_condition(inst)) > 0 ) ; |
769 | tagtree_unlock(); | ||
770 | |||
684 | if (ret < 0) | 771 | if (ret < 0) |
685 | return false; | 772 | return false; |
686 | 773 | ||
@@ -697,7 +784,7 @@ static int compare(const void *p1, const void *p2) | |||
697 | { | 784 | { |
698 | struct tagentry *e1 = (struct tagentry *)p1; | 785 | struct tagentry *e1 = (struct tagentry *)p1; |
699 | struct tagentry *e2 = (struct tagentry *)p2; | 786 | struct tagentry *e2 = (struct tagentry *)p2; |
700 | 787 | ||
701 | if (sort_inverse) | 788 | if (sort_inverse) |
702 | return strncasecmp(e2->name, e1->name, MAX_PATH); | 789 | return strncasecmp(e2->name, e1->name, MAX_PATH); |
703 | 790 | ||
@@ -1001,11 +1088,11 @@ static int parse_line(int n, char *buf, void *parameters) | |||
1001 | if (menu->items[menu->itemcount] == NULL) | 1088 | if (menu->items[menu->itemcount] == NULL) |
1002 | menu->items[menu->itemcount] = tagtree_alloc0(sizeof(struct menu_entry)); | 1089 | menu->items[menu->itemcount] = tagtree_alloc0(sizeof(struct menu_entry)); |
1003 | 1090 | ||
1004 | if (!parse_search(menu->items[menu->itemcount], buf)) | 1091 | tagtree_lock(); |
1005 | return 0; | 1092 | if (parse_search(menu->items[menu->itemcount], buf)) |
1006 | 1093 | menu->itemcount++; | |
1007 | menu->itemcount++; | 1094 | tagtree_unlock(); |
1008 | 1095 | ||
1009 | return 0; | 1096 | return 0; |
1010 | } | 1097 | } |
1011 | 1098 | ||
@@ -1040,15 +1127,20 @@ void tagtree_init(void) | |||
1040 | menu_count = 0; | 1127 | menu_count = 0; |
1041 | menu = NULL; | 1128 | menu = NULL; |
1042 | rootmenu = -1; | 1129 | rootmenu = -1; |
1043 | tagtree_handle = core_alloc_maximum("tagtree", &tagtree_bufsize, NULL); | 1130 | tagtree_handle = core_alloc_maximum("tagtree", &tagtree_bufsize, &ops); |
1044 | parse_menu(FILE_SEARCH_INSTRUCTIONS); | 1131 | parse_menu(FILE_SEARCH_INSTRUCTIONS); |
1132 | |||
1133 | /* safety check since tree.c needs to cast tagentry to entry */ | ||
1134 | if (sizeof(struct tagentry) != sizeof(struct entry)) | ||
1135 | panicf("tagentry(%zu) and entry mismatch(%zu)", | ||
1136 | sizeof(struct tagentry), sizeof(struct entry)); | ||
1137 | if (lock_count > 0) | ||
1138 | panicf("tagtree locked after parsing"); | ||
1045 | 1139 | ||
1046 | /* If no root menu is set, assume it's the first single menu | 1140 | /* If no root menu is set, assume it's the first single menu |
1047 | * we have. That shouldn't normally happen. */ | 1141 | * we have. That shouldn't normally happen. */ |
1048 | if (rootmenu < 0) | 1142 | if (rootmenu < 0) |
1049 | rootmenu = 0; | 1143 | rootmenu = 0; |
1050 | |||
1051 | uniqbuf = tagtree_alloc(UNIQBUF_SIZE); | ||
1052 | 1144 | ||
1053 | add_event(PLAYBACK_EVENT_TRACK_BUFFER, false, tagtree_buffer_event); | 1145 | add_event(PLAYBACK_EVENT_TRACK_BUFFER, false, tagtree_buffer_event); |
1054 | add_event(PLAYBACK_EVENT_TRACK_FINISH, false, tagtree_track_finish_event); | 1146 | add_event(PLAYBACK_EVENT_TRACK_FINISH, false, tagtree_track_finish_event); |
@@ -1181,10 +1273,14 @@ static int format_str(struct tagcache_search *tcs, struct display_format *fmt, | |||
1181 | return 0; | 1273 | return 0; |
1182 | } | 1274 | } |
1183 | 1275 | ||
1276 | static struct tagentry* get_entries(struct tree_context *tc) | ||
1277 | { | ||
1278 | return core_get_data(tc->cache.entries_handle); | ||
1279 | } | ||
1280 | |||
1184 | static int retrieve_entries(struct tree_context *c, int offset, bool init) | 1281 | static int retrieve_entries(struct tree_context *c, int offset, bool init) |
1185 | { | 1282 | { |
1186 | struct tagcache_search tcs; | 1283 | struct tagcache_search tcs; |
1187 | struct tagentry *dptr = c->cache.entries; | ||
1188 | struct display_format *fmt; | 1284 | struct display_format *fmt; |
1189 | int i; | 1285 | int i; |
1190 | int namebufused = 0; | 1286 | int namebufused = 0; |
@@ -1242,7 +1338,10 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1242 | csi->result_seek[i]); | 1338 | csi->result_seek[i]); |
1243 | } | 1339 | } |
1244 | } | 1340 | } |
1245 | 1341 | ||
1342 | /* because tagcache saves the clauses, we need to lock the buffer | ||
1343 | * for the entire duration of the search */ | ||
1344 | tagtree_lock(); | ||
1246 | for (i = 0; i <= level; i++) | 1345 | for (i = 0; i <= level; i++) |
1247 | { | 1346 | { |
1248 | int j; | 1347 | int j; |
@@ -1276,6 +1375,10 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1276 | strip = 0; | 1375 | strip = 0; |
1277 | } | 1376 | } |
1278 | 1377 | ||
1378 | /* lock buflib out due to possible yields */ | ||
1379 | tree_lock_cache(c); | ||
1380 | struct tagentry *dptr = core_get_data(c->cache.entries_handle); | ||
1381 | |||
1279 | if (tag != tag_title && tag != tag_filename) | 1382 | if (tag != tag_title && tag != tag_filename) |
1280 | { | 1383 | { |
1281 | if (offset == 0) | 1384 | if (offset == 0) |
@@ -1315,6 +1418,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1315 | 1418 | ||
1316 | fmt = NULL; | 1419 | fmt = NULL; |
1317 | /* Check the format */ | 1420 | /* Check the format */ |
1421 | tagtree_lock(); | ||
1318 | for (i = 0; i < format_count; i++) | 1422 | for (i = 0; i < format_count; i++) |
1319 | { | 1423 | { |
1320 | if (formats[i]->group_id != csi->format_id[level]) | 1424 | if (formats[i]->group_id != csi->format_id[level]) |
@@ -1327,6 +1431,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1327 | break; | 1431 | break; |
1328 | } | 1432 | } |
1329 | } | 1433 | } |
1434 | tagtree_unlock(); | ||
1330 | 1435 | ||
1331 | if (strcmp(tcs.result, UNTAGGED) == 0) | 1436 | if (strcmp(tcs.result, UNTAGGED) == 0) |
1332 | { | 1437 | { |
@@ -1337,7 +1442,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1337 | 1442 | ||
1338 | if (!tcs.ramresult || fmt) | 1443 | if (!tcs.ramresult || fmt) |
1339 | { | 1444 | { |
1340 | dptr->name = &c->cache.name_buffer[namebufused]; | 1445 | dptr->name = core_get_data(c->cache.name_buffer_handle)+namebufused; |
1341 | 1446 | ||
1342 | if (fmt) | 1447 | if (fmt) |
1343 | { | 1448 | { |
@@ -1354,6 +1459,8 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1354 | { | 1459 | { |
1355 | logf("format_str() failed"); | 1460 | logf("format_str() failed"); |
1356 | tagcache_search_finish(&tcs); | 1461 | tagcache_search_finish(&tcs); |
1462 | tree_unlock_cache(c); | ||
1463 | tagtree_unlock(); | ||
1357 | return 0; | 1464 | return 0; |
1358 | } | 1465 | } |
1359 | else | 1466 | else |
@@ -1392,6 +1499,8 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1392 | if (!show_search_progress(false, total_count)) | 1499 | if (!show_search_progress(false, total_count)) |
1393 | { /* user aborted */ | 1500 | { /* user aborted */ |
1394 | tagcache_search_finish(&tcs); | 1501 | tagcache_search_finish(&tcs); |
1502 | tree_unlock_cache(c); | ||
1503 | tagtree_unlock(); | ||
1395 | return current_entry_count; | 1504 | return current_entry_count; |
1396 | } | 1505 | } |
1397 | } | 1506 | } |
@@ -1399,15 +1508,17 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1399 | 1508 | ||
1400 | if (sort) | 1509 | if (sort) |
1401 | { | 1510 | { |
1402 | int entry_size = sizeof(struct tagentry); | 1511 | struct tagentry *entries = get_entries(c); |
1403 | qsort(c->cache.entries + special_entry_count * entry_size, | 1512 | qsort(&entries[special_entry_count], |
1404 | current_entry_count - special_entry_count, | 1513 | current_entry_count - special_entry_count, |
1405 | entry_size, compare); | 1514 | sizeof(struct tagentry), compare); |
1406 | } | 1515 | } |
1407 | 1516 | ||
1408 | if (!init) | 1517 | if (!init) |
1409 | { | 1518 | { |
1410 | tagcache_search_finish(&tcs); | 1519 | tagcache_search_finish(&tcs); |
1520 | tree_unlock_cache(c); | ||
1521 | tagtree_unlock(); | ||
1411 | return current_entry_count; | 1522 | return current_entry_count; |
1412 | } | 1523 | } |
1413 | 1524 | ||
@@ -1422,7 +1533,9 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1422 | } | 1533 | } |
1423 | 1534 | ||
1424 | tagcache_search_finish(&tcs); | 1535 | tagcache_search_finish(&tcs); |
1425 | 1536 | tree_unlock_cache(c); | |
1537 | tagtree_unlock(); | ||
1538 | |||
1426 | if (!sort && (sort_inverse || sort_limit)) | 1539 | if (!sort && (sort_inverse || sort_limit)) |
1427 | { | 1540 | { |
1428 | splashf(HZ*4, ID2P(LANG_SHOWDIR_BUFFER_FULL), total_count); | 1541 | splashf(HZ*4, ID2P(LANG_SHOWDIR_BUFFER_FULL), total_count); |
@@ -1435,7 +1548,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1435 | 1548 | ||
1436 | if (strip) | 1549 | if (strip) |
1437 | { | 1550 | { |
1438 | dptr = c->cache.entries; | 1551 | dptr = get_entries(c); |
1439 | for (i = special_entry_count; i < current_entry_count; i++, dptr++) | 1552 | for (i = special_entry_count; i < current_entry_count; i++, dptr++) |
1440 | { | 1553 | { |
1441 | int len = strlen(dptr->name); | 1554 | int len = strlen(dptr->name); |
@@ -1446,14 +1559,14 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1446 | dptr->name = &dptr->name[strip]; | 1559 | dptr->name = &dptr->name[strip]; |
1447 | } | 1560 | } |
1448 | } | 1561 | } |
1449 | 1562 | ||
1450 | return total_count; | 1563 | return total_count; |
1451 | 1564 | ||
1452 | } | 1565 | } |
1453 | 1566 | ||
1454 | static int load_root(struct tree_context *c) | 1567 | static int load_root(struct tree_context *c) |
1455 | { | 1568 | { |
1456 | struct tagentry *dptr = c->cache.entries; | 1569 | struct tagentry *dptr = core_get_data(c->cache.entries_handle); |
1457 | int i; | 1570 | int i; |
1458 | 1571 | ||
1459 | tc = c; | 1572 | tc = c; |
@@ -1569,6 +1682,10 @@ int tagtree_enter(struct tree_context* c) | |||
1569 | c->pos_history[c->dirlevel] = c->firstpos; | 1682 | c->pos_history[c->dirlevel] = c->firstpos; |
1570 | c->dirlevel++; | 1683 | c->dirlevel++; |
1571 | 1684 | ||
1685 | /* lock buflib for possible I/O to protect dptr */ | ||
1686 | tree_lock_cache(c); | ||
1687 | tagtree_lock(); | ||
1688 | |||
1572 | switch (c->currtable) { | 1689 | switch (c->currtable) { |
1573 | case ROOT: | 1690 | case ROOT: |
1574 | c->currextra = newextra; | 1691 | c->currextra = newextra; |
@@ -1634,6 +1751,8 @@ int tagtree_enter(struct tree_context* c) | |||
1634 | if (rc < 0 || !searchstring[0]) | 1751 | if (rc < 0 || !searchstring[0]) |
1635 | { | 1752 | { |
1636 | tagtree_exit(c); | 1753 | tagtree_exit(c); |
1754 | tree_unlock_cache(c); | ||
1755 | tagtree_unlock(); | ||
1637 | return 0; | 1756 | return 0; |
1638 | } | 1757 | } |
1639 | if (csi->clause[i][j]->numeric) | 1758 | if (csi->clause[i][j]->numeric) |
@@ -1682,9 +1801,12 @@ int tagtree_enter(struct tree_context* c) | |||
1682 | c->dirlevel--; | 1801 | c->dirlevel--; |
1683 | break; | 1802 | break; |
1684 | } | 1803 | } |
1804 | |||
1685 | 1805 | ||
1686 | c->selected_item=0; | 1806 | c->selected_item=0; |
1687 | gui_synclist_select_item(&tree_lists, c->selected_item); | 1807 | gui_synclist_select_item(&tree_lists, c->selected_item); |
1808 | tree_unlock_cache(c); | ||
1809 | tagtree_unlock(); | ||
1688 | 1810 | ||
1689 | return rc; | 1811 | return rc; |
1690 | } | 1812 | } |
@@ -1704,14 +1826,13 @@ void tagtree_exit(struct tree_context* c) | |||
1704 | int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) | 1826 | int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) |
1705 | { | 1827 | { |
1706 | struct tagcache_search tcs; | 1828 | struct tagcache_search tcs; |
1707 | struct tagentry *entry; | 1829 | int extraseek = tagtree_get_entry(c, c->selected_item)->extraseek; |
1708 | 1830 | ||
1709 | entry = tagtree_get_entry(c, c->selected_item); | ||
1710 | 1831 | ||
1711 | if (!tagcache_search(&tcs, tag_filename)) | 1832 | if (!tagcache_search(&tcs, tag_filename)) |
1712 | return -1; | 1833 | return -1; |
1713 | 1834 | ||
1714 | if (!tagcache_retrieve(&tcs, entry->extraseek, tcs.type, buf, buflen)) | 1835 | if (!tagcache_retrieve(&tcs, extraseek, tcs.type, buf, buflen)) |
1715 | { | 1836 | { |
1716 | tagcache_search_finish(&tcs); | 1837 | tagcache_search_finish(&tcs); |
1717 | return -2; | 1838 | return -2; |
@@ -1790,9 +1911,9 @@ static bool insert_all_playlist(struct tree_context *c, int position, bool queue | |||
1790 | 1911 | ||
1791 | bool tagtree_insert_selection_playlist(int position, bool queue) | 1912 | bool tagtree_insert_selection_playlist(int position, bool queue) |
1792 | { | 1913 | { |
1793 | struct tagentry *dptr; | ||
1794 | char buf[MAX_PATH]; | 1914 | char buf[MAX_PATH]; |
1795 | int dirlevel = tc->dirlevel; | 1915 | int dirlevel = tc->dirlevel; |
1916 | int newtable; | ||
1796 | 1917 | ||
1797 | show_search_progress( | 1918 | show_search_progress( |
1798 | #ifdef HAVE_DISK_STORAGE | 1919 | #ifdef HAVE_DISK_STORAGE |
@@ -1804,10 +1925,10 @@ bool tagtree_insert_selection_playlist(int position, bool queue) | |||
1804 | 1925 | ||
1805 | 1926 | ||
1806 | /* We need to set the table to allsubentries. */ | 1927 | /* We need to set the table to allsubentries. */ |
1807 | dptr = tagtree_get_entry(tc, tc->selected_item); | 1928 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; |
1808 | 1929 | ||
1809 | /* Insert a single track? */ | 1930 | /* Insert a single track? */ |
1810 | if (dptr->newtable == PLAYTRACK) | 1931 | if (newtable == PLAYTRACK) |
1811 | { | 1932 | { |
1812 | if (tagtree_get_filename(tc, buf, sizeof buf) < 0) | 1933 | if (tagtree_get_filename(tc, buf, sizeof buf) < 0) |
1813 | { | 1934 | { |
@@ -1819,29 +1940,29 @@ bool tagtree_insert_selection_playlist(int position, bool queue) | |||
1819 | return true; | 1940 | return true; |
1820 | } | 1941 | } |
1821 | 1942 | ||
1822 | if (dptr->newtable == NAVIBROWSE) | 1943 | if (newtable == NAVIBROWSE) |
1823 | { | 1944 | { |
1824 | tagtree_enter(tc); | 1945 | tagtree_enter(tc); |
1825 | tagtree_load(tc); | 1946 | tagtree_load(tc); |
1826 | dptr = tagtree_get_entry(tc, tc->selected_item); | 1947 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; |
1827 | } | 1948 | } |
1828 | else if (dptr->newtable != ALLSUBENTRIES) | 1949 | else if (newtable != ALLSUBENTRIES) |
1829 | { | 1950 | { |
1830 | logf("unsupported table: %d", dptr->newtable); | 1951 | logf("unsupported table: %d", newtable); |
1831 | return false; | 1952 | return false; |
1832 | } | 1953 | } |
1833 | 1954 | ||
1834 | /* Now the current table should be allsubentries. */ | 1955 | /* Now the current table should be allsubentries. */ |
1835 | if (dptr->newtable != PLAYTRACK) | 1956 | if (newtable != PLAYTRACK) |
1836 | { | 1957 | { |
1837 | tagtree_enter(tc); | 1958 | tagtree_enter(tc); |
1838 | tagtree_load(tc); | 1959 | tagtree_load(tc); |
1839 | dptr = tagtree_get_entry(tc, tc->selected_item); | 1960 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; |
1840 | 1961 | ||
1841 | /* And now the newtable should be playtrack. */ | 1962 | /* And now the newtable should be playtrack. */ |
1842 | if (dptr->newtable != PLAYTRACK) | 1963 | if (newtable != PLAYTRACK) |
1843 | { | 1964 | { |
1844 | logf("newtable: %d !!", dptr->newtable); | 1965 | logf("newtable: %d !!", newtable); |
1845 | tc->dirlevel = dirlevel; | 1966 | tc->dirlevel = dirlevel; |
1846 | return false; | 1967 | return false; |
1847 | } | 1968 | } |
@@ -1886,9 +2007,9 @@ static int tagtree_play_folder(struct tree_context* c) | |||
1886 | return 0; | 2007 | return 0; |
1887 | } | 2008 | } |
1888 | 2009 | ||
1889 | struct tagentry* tagtree_get_entry(struct tree_context *c, int id) | 2010 | static struct tagentry* tagtree_get_entry(struct tree_context *c, int id) |
1890 | { | 2011 | { |
1891 | struct tagentry *entry = (struct tagentry *)c->cache.entries; | 2012 | struct tagentry *entry; |
1892 | int realid = id - current_offset; | 2013 | int realid = id - current_offset; |
1893 | 2014 | ||
1894 | /* Load the next chunk if necessary. */ | 2015 | /* Load the next chunk if necessary. */ |
@@ -1905,10 +2026,22 @@ struct tagentry* tagtree_get_entry(struct tree_context *c, int id) | |||
1905 | realid = id - current_offset; | 2026 | realid = id - current_offset; |
1906 | cpu_boost(false); | 2027 | cpu_boost(false); |
1907 | } | 2028 | } |
1908 | 2029 | ||
2030 | entry = get_entries(c); | ||
1909 | return &entry[realid]; | 2031 | return &entry[realid]; |
1910 | } | 2032 | } |
1911 | 2033 | ||
2034 | char* tagtree_get_entry_name(struct tree_context *c, int id, | ||
2035 | char* buf, size_t bufsize) | ||
2036 | { | ||
2037 | struct tagentry *entry = tagtree_get_entry(c, id); | ||
2038 | if (!entry) | ||
2039 | return NULL; | ||
2040 | strlcpy(buf, entry->name, bufsize); | ||
2041 | return buf; | ||
2042 | } | ||
2043 | |||
2044 | |||
1912 | char *tagtree_get_title(struct tree_context* c) | 2045 | char *tagtree_get_title(struct tree_context* c) |
1913 | { | 2046 | { |
1914 | switch (c->currtable) | 2047 | switch (c->currtable) |