summaryrefslogtreecommitdiff
path: root/apps/tagtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r--apps/tagtree.c278
1 files changed, 229 insertions, 49 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c
index ea2a756a46..1a49936f45 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -56,6 +56,8 @@
56#include "playback.h" 56#include "playback.h"
57#include "strnatcmp.h" 57#include "strnatcmp.h"
58#include "panic.h" 58#include "panic.h"
59#include "onplay.h"
60#include "plugin.h"
59 61
60#define str_or_empty(x) (x ? x : "(NULL)") 62#define str_or_empty(x) (x ? x : "(NULL)")
61 63
@@ -64,6 +66,10 @@
64 66
65static int tagtree_play_folder(struct tree_context* c); 67static int tagtree_play_folder(struct tree_context* c);
66 68
69/* reuse of tagtree data after tagtree_play_folder() */
70static uint32_t loaded_entries_crc = 0;
71
72
67/* this needs to be same size as struct entry (tree.h) and name needs to be 73/* this needs to be same size as struct entry (tree.h) and name needs to be
68 * the first; so that they're compatible enough to walk arrays of both 74 * the first; so that they're compatible enough to walk arrays of both
69 * derefencing the name member*/ 75 * derefencing the name member*/
@@ -71,6 +77,7 @@ struct tagentry {
71 char* name; 77 char* name;
72 int newtable; 78 int newtable;
73 int extraseek; 79 int extraseek;
80 int customaction;
74}; 81};
75 82
76static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); 83static struct tagentry* tagtree_get_entry(struct tree_context *c, int id);
@@ -78,10 +85,10 @@ static struct tagentry* tagtree_get_entry(struct tree_context *c, int id);
78#define SEARCHSTR_SIZE 256 85#define SEARCHSTR_SIZE 256
79 86
80enum table { 87enum table {
81 ROOT = 1, 88 TABLE_ROOT = 1,
82 NAVIBROWSE, 89 TABLE_NAVIBROWSE,
83 ALLSUBENTRIES, 90 TABLE_ALLSUBENTRIES,
84 PLAYTRACK, 91 TABLE_PLAYTRACK,
85}; 92};
86 93
87static const struct id3_to_search_mapping { 94static const struct id3_to_search_mapping {
@@ -108,6 +115,7 @@ enum variables {
108 menu_next, 115 menu_next,
109 menu_load, 116 menu_load,
110 menu_reload, 117 menu_reload,
118 menu_shuffle_songs,
111}; 119};
112 120
113/* Capacity 10 000 entries (for example 10k different artists) */ 121/* Capacity 10 000 entries (for example 10k different artists) */
@@ -276,6 +284,20 @@ static struct buflib_callbacks ops = {
276 .shrink_callback = NULL, 284 .shrink_callback = NULL,
277}; 285};
278 286
287static uint32_t tagtree_data_crc(struct tree_context* c)
288{
289 char* buf;
290 uint32_t crc;
291 buf = core_get_data(tagtree_handle); /* data for the search clauses etc */
292 crc = crc_32(buf, tagtree_buf_used, c->dirlength);
293 buf = core_get_data(c->cache.name_buffer_handle); /* names */
294 crc = crc_32(buf, c->cache.name_buffer_size, crc);
295 buf = core_get_data(c->cache.entries_handle); /* tagentries */
296 crc = crc_32(buf, c->cache.max_entries * sizeof(struct tagentry), crc);
297 logf("%s 0x%x", __func__, crc);
298 return crc;
299}
300
279static void* tagtree_alloc(size_t size) 301static void* tagtree_alloc(size_t size)
280{ 302{
281 size = ALIGN_UP(size, sizeof(void*)); 303 size = ALIGN_UP(size, sizeof(void*));
@@ -338,6 +360,7 @@ static int get_tag(int *tag)
338 TAG_MATCH("Pm", tag_virt_playtime_min), 360 TAG_MATCH("Pm", tag_virt_playtime_min),
339 TAG_MATCH("Ps", tag_virt_playtime_sec), 361 TAG_MATCH("Ps", tag_virt_playtime_sec),
340 TAG_MATCH("->", menu_next), 362 TAG_MATCH("->", menu_next),
363 TAG_MATCH("~>", menu_shuffle_songs),
341 364
342 TAG_MATCH("==>", menu_load), 365 TAG_MATCH("==>", menu_load),
343 366
@@ -820,7 +843,7 @@ static bool parse_search(struct menu_entry *entry, const char *str)
820 return true; 843 return true;
821 } 844 }
822 845
823 if (entry->type != menu_next) 846 if (entry->type != menu_next && entry->type != menu_shuffle_songs)
824 return false; 847 return false;
825 848
826 while (inst->tagorder_count < MAX_TAGS) 849 while (inst->tagorder_count < MAX_TAGS)
@@ -847,7 +870,7 @@ static bool parse_search(struct menu_entry *entry, const char *str)
847 870
848 inst->tagorder_count++; 871 inst->tagorder_count++;
849 872
850 if (get_tag(&type) <= 0 || type != menu_next) 873 if (get_tag(&type) <= 0 || (type != menu_next && type != menu_shuffle_songs))
851 break; 874 break;
852 } 875 }
853 876
@@ -1245,6 +1268,7 @@ static void tagtree_unload(struct tree_context *c)
1245 dptr->name = NULL; 1268 dptr->name = NULL;
1246 dptr->newtable = 0; 1269 dptr->newtable = 0;
1247 dptr->extraseek = 0; 1270 dptr->extraseek = 0;
1271 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1248 dptr++; 1272 dptr++;
1249 } 1273 }
1250 } 1274 }
@@ -1452,9 +1476,9 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1452#else 1476#else
1453 true 1477 true
1454#endif 1478#endif
1455 , 0); 1479 , 0, 0, 0);
1456 1480
1457 if (c->currtable == ALLSUBENTRIES) 1481 if (c->currtable == TABLE_ALLSUBENTRIES)
1458 { 1482 {
1459 tag = tag_title; 1483 tag = tag_title;
1460 level--; 1484 level--;
@@ -1544,17 +1568,19 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1544 { 1568 {
1545 if (offset == 0) 1569 if (offset == 0)
1546 { 1570 {
1547 dptr->newtable = ALLSUBENTRIES; 1571 dptr->newtable = TABLE_ALLSUBENTRIES;
1548 dptr->name = str(LANG_TAGNAVI_ALL_TRACKS); 1572 dptr->name = str(LANG_TAGNAVI_ALL_TRACKS);
1573 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1549 dptr++; 1574 dptr++;
1550 current_entry_count++; 1575 current_entry_count++;
1551 special_entry_count++; 1576 special_entry_count++;
1552 } 1577 }
1553 if (offset <= 1) 1578 if (offset <= 1)
1554 { 1579 {
1555 dptr->newtable = NAVIBROWSE; 1580 dptr->newtable = TABLE_NAVIBROWSE;
1556 dptr->name = str(LANG_TAGNAVI_RANDOM); 1581 dptr->name = str(LANG_TAGNAVI_RANDOM);
1557 dptr->extraseek = -1; 1582 dptr->extraseek = -1;
1583 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1558 dptr++; 1584 dptr++;
1559 current_entry_count++; 1585 current_entry_count++;
1560 special_entry_count++; 1586 special_entry_count++;
@@ -1568,14 +1594,15 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1568 if (total_count++ < offset) 1594 if (total_count++ < offset)
1569 continue; 1595 continue;
1570 1596
1571 dptr->newtable = NAVIBROWSE; 1597 dptr->newtable = TABLE_NAVIBROWSE;
1572 if (tag == tag_title || tag == tag_filename) 1598 if (tag == tag_title || tag == tag_filename)
1573 { 1599 {
1574 dptr->newtable = PLAYTRACK; 1600 dptr->newtable = TABLE_PLAYTRACK;
1575 dptr->extraseek = tcs.idx_id; 1601 dptr->extraseek = tcs.idx_id;
1576 } 1602 }
1577 else 1603 else
1578 dptr->extraseek = tcs.result_seek; 1604 dptr->extraseek = tcs.result_seek;
1605 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1579 1606
1580 fmt = NULL; 1607 fmt = NULL;
1581 /* Check the format */ 1608 /* Check the format */
@@ -1676,7 +1703,7 @@ entry_skip_formatter:
1676 1703
1677 if (init) 1704 if (init)
1678 { 1705 {
1679 if (!show_search_progress(false, total_count)) 1706 if (!show_search_progress(false, total_count, 0, 0))
1680 { /* user aborted */ 1707 { /* user aborted */
1681 tagcache_search_finish(&tcs); 1708 tagcache_search_finish(&tcs);
1682 tree_unlock_cache(c); 1709 tree_unlock_cache(c);
@@ -1710,7 +1737,7 @@ entry_skip_formatter:
1710 1737
1711 while (tagcache_get_next(&tcs, tcs_buf, tcs_bufsz)) 1738 while (tagcache_get_next(&tcs, tcs_buf, tcs_bufsz))
1712 { 1739 {
1713 if (!show_search_progress(false, total_count)) 1740 if (!show_search_progress(false, total_count, 0, 0))
1714 break; 1741 break;
1715 total_count++; 1742 total_count++;
1716 } 1743 }
@@ -1758,7 +1785,7 @@ static int load_root(struct tree_context *c)
1758 int i; 1785 int i;
1759 1786
1760 tc = c; 1787 tc = c;
1761 c->currtable = ROOT; 1788 c->currtable = TABLE_ROOT;
1762 if (c->dirlevel == 0) 1789 if (c->dirlevel == 0)
1763 c->currextra = rootmenu; 1790 c->currextra = rootmenu;
1764 1791
@@ -1775,13 +1802,21 @@ static int load_root(struct tree_context *c)
1775 switch (menu->items[i]->type) 1802 switch (menu->items[i]->type)
1776 { 1803 {
1777 case menu_next: 1804 case menu_next:
1778 dptr->newtable = NAVIBROWSE; 1805 dptr->newtable = TABLE_NAVIBROWSE;
1779 dptr->extraseek = i; 1806 dptr->extraseek = i;
1807 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1780 break; 1808 break;
1781 1809
1782 case menu_load: 1810 case menu_load:
1783 dptr->newtable = ROOT; 1811 dptr->newtable = TABLE_ROOT;
1784 dptr->extraseek = menu->items[i]->link; 1812 dptr->extraseek = menu->items[i]->link;
1813 dptr->customaction = ONPLAY_NO_CUSTOMACTION;
1814 break;
1815
1816 case menu_shuffle_songs:
1817 dptr->newtable = TABLE_NAVIBROWSE;
1818 dptr->extraseek = i;
1819 dptr->customaction = ONPLAY_CUSTOMACTION_SHUFFLE_SONGS;
1785 break; 1820 break;
1786 } 1821 }
1787 1822
@@ -1796,6 +1831,8 @@ static int load_root(struct tree_context *c)
1796 1831
1797int tagtree_load(struct tree_context* c) 1832int tagtree_load(struct tree_context* c)
1798{ 1833{
1834 logf( "%s", __func__);
1835
1799 int count; 1836 int count;
1800 int table = c->currtable; 1837 int table = c->currtable;
1801 1838
@@ -1804,20 +1841,32 @@ int tagtree_load(struct tree_context* c)
1804 if (!table) 1841 if (!table)
1805 { 1842 {
1806 c->dirfull = false; 1843 c->dirfull = false;
1807 table = ROOT; 1844 table = TABLE_ROOT;
1808 c->currtable = table; 1845 c->currtable = table;
1809 c->currextra = rootmenu; 1846 c->currextra = rootmenu;
1810 } 1847 }
1811 1848
1812 switch (table) 1849 switch (table)
1813 { 1850 {
1814 case ROOT: 1851 case TABLE_ROOT:
1852 logf( "root...");
1815 count = load_root(c); 1853 count = load_root(c);
1816 break; 1854 break;
1817 1855
1818 case ALLSUBENTRIES: 1856 case TABLE_ALLSUBENTRIES:
1819 case NAVIBROWSE: 1857 case TABLE_NAVIBROWSE:
1820 logf("navibrowse..."); 1858 logf("navibrowse...");
1859
1860 if (loaded_entries_crc != 0)
1861 {
1862 if (loaded_entries_crc == tagtree_data_crc(c))
1863 {
1864 count = c->dirlength;
1865 logf("Reusing %d entries", count);
1866 break;
1867 }
1868 }
1869
1821 cpu_boost(true); 1870 cpu_boost(true);
1822 count = retrieve_entries(c, 0, true); 1871 count = retrieve_entries(c, 0, true);
1823 cpu_boost(false); 1872 cpu_boost(false);
@@ -1828,6 +1877,8 @@ int tagtree_load(struct tree_context* c)
1828 return -1; 1877 return -1;
1829 } 1878 }
1830 1879
1880 loaded_entries_crc = 0;
1881
1831 if (count < 0) 1882 if (count < 0)
1832 { 1883 {
1833 if (count != RELOAD_TAGTREE) 1884 if (count != RELOAD_TAGTREE)
@@ -1860,6 +1911,8 @@ int tagtree_load(struct tree_context* c)
1860 */ 1911 */
1861int tagtree_enter(struct tree_context* c, bool is_visible) 1912int tagtree_enter(struct tree_context* c, bool is_visible)
1862{ 1913{
1914 logf( "%s", __func__);
1915
1863 int rc = 0; 1916 int rc = 0;
1864 struct tagentry *dptr; 1917 struct tagentry *dptr;
1865 struct mp3entry *id3; 1918 struct mp3entry *id3;
@@ -1921,16 +1974,16 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
1921 core_pin(tagtree_handle); 1974 core_pin(tagtree_handle);
1922 1975
1923 switch (c->currtable) { 1976 switch (c->currtable) {
1924 case ROOT: 1977 case TABLE_ROOT:
1925 c->currextra = newextra; 1978 c->currextra = newextra;
1926 1979
1927 if (newextra == ROOT) 1980 if (newextra == TABLE_ROOT)
1928 { 1981 {
1929 menu = menus[seek]; 1982 menu = menus[seek];
1930 c->currextra = seek; 1983 c->currextra = seek;
1931 } 1984 }
1932 1985
1933 else if (newextra == NAVIBROWSE) 1986 else if (newextra == TABLE_NAVIBROWSE)
1934 { 1987 {
1935 int i, j; 1988 int i, j;
1936 1989
@@ -2005,9 +2058,9 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
2005 2058
2006 break; 2059 break;
2007 2060
2008 case NAVIBROWSE: 2061 case TABLE_NAVIBROWSE:
2009 case ALLSUBENTRIES: 2062 case TABLE_ALLSUBENTRIES:
2010 if (newextra == PLAYTRACK) 2063 if (newextra == TABLE_PLAYTRACK)
2011 { 2064 {
2012 adjust_selection = false; 2065 adjust_selection = false;
2013 2066
@@ -2059,6 +2112,7 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
2059/* Exits current database menu or table */ 2112/* Exits current database menu or table */
2060void tagtree_exit(struct tree_context* c, bool is_visible) 2113void tagtree_exit(struct tree_context* c, bool is_visible)
2061{ 2114{
2115 logf( "%s", __func__);
2062 if (is_visible) /* update selection history only for user-selected items */ 2116 if (is_visible) /* update selection history only for user-selected items */
2063 { 2117 {
2064 if (c->selected_item != selected_item_history[c->dirlevel]) 2118 if (c->selected_item != selected_item_history[c->dirlevel])
@@ -2102,15 +2156,54 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
2102 return 0; 2156 return 0;
2103} 2157}
2104 2158
2159int tagtree_get_custom_action(struct tree_context* c)
2160{
2161 return tagtree_get_entry(c, c->selected_item)->customaction;
2162}
2163
2164static void swap_array_bool(bool *a, bool *b)
2165{
2166 bool temp = *a;
2167 *a = *b;
2168 *b = temp;
2169}
2170
2171/**
2172 * Randomly shuffle an array using the Fisher-Yates algorithm :
2173 * https://en.wikipedia.org/wiki/Random_permutation
2174 * This algorithm has a linear complexity.
2175 * Don't forget to srand before call to use it with a relevant seed.
2176 */
2177static bool* fill_random_playlist_indexes(bool *bool_array, size_t arr_sz,
2178 size_t track_count, size_t max_slots)
2179{
2180 size_t i;
2181 if (track_count * sizeof(bool) > arr_sz || max_slots > track_count)
2182 return NULL;
2183
2184 for (i = 0; i < arr_sz; i++) /* fill max_slots with TRUE */
2185 bool_array[i] = i < max_slots;
2186
2187 /* shuffle bool array */
2188 for (i = track_count - 1; i > 0; i--)
2189 {
2190 int j = rand() % (i + 1);
2191 swap_array_bool(&bool_array[i], &bool_array[j]);
2192 }
2193 return bool_array;
2194}
2105 2195
2106static bool insert_all_playlist(struct tree_context *c, 2196static bool insert_all_playlist(struct tree_context *c,
2107 const char* playlist, bool new_playlist, 2197 const char* playlist, bool new_playlist,
2108 int position, bool queue) 2198 int position, bool queue)
2109{ 2199{
2110 struct tagcache_search tcs; 2200 struct tagcache_search tcs;
2111 int i, n; 2201 int n;
2112 int fd = -1; 2202 int fd = -1;
2113 unsigned long last_tick; 2203 unsigned long last_tick;
2204 int slots_remaining = 0;
2205 bool fill_randomly = false;
2206 bool *rand_bool_array = NULL;
2114 char buf[MAX_PATH]; 2207 char buf[MAX_PATH];
2115 2208
2116 cpu_boost(true); 2209 cpu_boost(true);
@@ -2148,40 +2241,114 @@ static bool insert_all_playlist(struct tree_context *c,
2148 last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */ 2241 last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */
2149 splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */ 2242 splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
2150 n = c->filesindir; 2243 n = c->filesindir;
2151 for (i = 0; i < n; i++) 2244
2245 if (playlist == NULL)
2152 { 2246 {
2247 int max_playlist_size = playlist_get_current()->max_playlist_size;
2248 slots_remaining = max_playlist_size - playlist_get_current()->amount;
2249 if (slots_remaining <= 0)
2250 {
2251 logf("Playlist has no space remaining");
2252 cpu_boost(false);
2253 return false;
2254 }
2153 2255
2154 splash_progress(i, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT)); 2256 fill_randomly = n > slots_remaining;
2257
2258 if (fill_randomly)
2259 {
2260 srand(current_tick);
2261 size_t bufsize = 0;
2262 bool *buffer = (bool *) plugin_get_buffer(&bufsize);
2263 rand_bool_array = fill_random_playlist_indexes(buffer, bufsize,
2264 n, slots_remaining);
2265
2266 talk_id(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY, true);
2267 splashf(HZ * 2, str(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY),
2268 slots_remaining);
2269 }
2270 }
2271
2272 bool exit_loop_now = false;
2273 for (int i = 0; i < n; i++)
2274 {
2155 if (TIME_AFTER(current_tick, last_tick + HZ/4)) 2275 if (TIME_AFTER(current_tick, last_tick + HZ/4))
2156 { 2276 {
2277 splash_progress(i, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
2157 if (action_userabort(TIMEOUT_NOBLOCK)) 2278 if (action_userabort(TIMEOUT_NOBLOCK))
2279 {
2280 exit_loop_now = true;
2158 break; 2281 break;
2282 }
2159 last_tick = current_tick; 2283 last_tick = current_tick;
2160 } 2284 }
2161 2285
2162 if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, 2286 if (playlist == NULL)
2163 tcs.type, buf, sizeof buf))
2164 { 2287 {
2165 continue; 2288 if (fill_randomly)
2289 {
2290 int remaining_tracks = n - i;
2291 if (remaining_tracks > slots_remaining)
2292 {
2293 if (rand_bool_array)
2294 {
2295 /* Skip the track if rand_bool_array[i] is FALSE */
2296 if (!rand_bool_array[i])
2297 continue;
2298 }
2299 else
2300 {
2301 /* Generate random value between 0 and remaining_tracks - 1 */
2302 int selrange = RAND_MAX / remaining_tracks; /* Improve distribution */
2303 int random;
2304
2305 for (int r = 0; r < 0x0FFF; r++) /* limit loops */
2306 {
2307 random = rand() / selrange;
2308 if (random < remaining_tracks)
2309 break;
2310 else
2311 random = 0;
2312 }
2313 /* Skip the track if random >= slots_remaining */
2314 if (random >= slots_remaining)
2315 continue;
2316 }
2317 }
2318 }
2166 } 2319 }
2167 2320
2321 if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, tcs.type, buf, sizeof buf))
2322 continue;
2323
2168 if (playlist == NULL) 2324 if (playlist == NULL)
2169 { 2325 {
2170 if (playlist_insert_track(NULL, buf, position, queue, false) < 0) 2326 if (fill_randomly)
2171 { 2327 {
2328 if (--slots_remaining <= 0)
2329 {
2330 exit_loop_now = true;
2331 break;
2332 }
2333 }
2334
2335 if (playlist_insert_track(NULL, buf, position, queue, false) < 0) {
2172 logf("playlist_insert_track failed"); 2336 logf("playlist_insert_track failed");
2337 exit_loop_now = true;
2173 break; 2338 break;
2174 } 2339 }
2175 } 2340 }
2176 else if (fdprintf(fd, "%s\n", buf) <= 0) 2341 else if (fdprintf(fd, "%s\n", buf) <= 0)
2177 break; 2342 {
2178 2343 exit_loop_now = true;
2344 break;
2345 }
2179 yield(); 2346 yield();
2180
2181 if (playlist == NULL && position == PLAYLIST_INSERT_FIRST) 2347 if (playlist == NULL && position == PLAYLIST_INSERT_FIRST)
2182 {
2183 position = PLAYLIST_INSERT; 2348 position = PLAYLIST_INSERT;
2184 } 2349
2350 if (exit_loop_now)
2351 break;
2185 } 2352 }
2186 if (playlist == NULL) 2353 if (playlist == NULL)
2187 playlist_sync(NULL); 2354 playlist_sync(NULL);
@@ -2196,14 +2363,14 @@ static bool insert_all_playlist(struct tree_context *c,
2196static bool goto_allsubentries(int newtable) 2363static bool goto_allsubentries(int newtable)
2197{ 2364{
2198 int i = 0; 2365 int i = 0;
2199 while (i < 2 && (newtable == NAVIBROWSE || newtable == ALLSUBENTRIES)) 2366 while (i < 2 && (newtable == TABLE_NAVIBROWSE || newtable == TABLE_ALLSUBENTRIES))
2200 { 2367 {
2201 tagtree_enter(tc, false); 2368 tagtree_enter(tc, false);
2202 tagtree_load(tc); 2369 tagtree_load(tc);
2203 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; 2370 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2204 i++; 2371 i++;
2205 } 2372 }
2206 return (newtable == PLAYTRACK); 2373 return (newtable == TABLE_PLAYTRACK);
2207} 2374}
2208 2375
2209static void reset_tc_to_prev(int dirlevel, int selected_item) 2376static void reset_tc_to_prev(int dirlevel, int selected_item)
@@ -2229,11 +2396,11 @@ static bool tagtree_insert_selection(int position, bool queue,
2229#else 2396#else
2230 true 2397 true
2231#endif 2398#endif
2232 , 0); 2399 , 0, 0, 0);
2233 2400
2234 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; 2401 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2235 2402
2236 if (newtable == PLAYTRACK) /* Insert a single track? */ 2403 if (newtable == TABLE_PLAYTRACK) /* Insert a single track? */
2237 { 2404 {
2238 if (tagtree_get_filename(tc, buf, sizeof buf) < 0) 2405 if (tagtree_get_filename(tc, buf, sizeof buf) < 0)
2239 return false; 2406 return false;
@@ -2342,6 +2509,7 @@ int tagtree_add_to_playlist(const char* playlist, bool new_playlist)
2342 2509
2343static int tagtree_play_folder(struct tree_context* c) 2510static int tagtree_play_folder(struct tree_context* c)
2344{ 2511{
2512 logf( "%s", __func__);
2345 int start_index = c->selected_item; 2513 int start_index = c->selected_item;
2346 2514
2347 if (playlist_create(NULL, NULL) < 0) 2515 if (playlist_create(NULL, NULL) < 0)
@@ -2353,14 +2521,26 @@ static int tagtree_play_folder(struct tree_context* c)
2353 if (!insert_all_playlist(c, NULL, false, PLAYLIST_INSERT_LAST, false)) 2521 if (!insert_all_playlist(c, NULL, false, PLAYLIST_INSERT_LAST, false))
2354 return -2; 2522 return -2;
2355 2523
2524 int n = c->filesindir;
2525 bool has_playlist_been_randomized = n > playlist_get_current()->max_playlist_size;
2526 if (has_playlist_been_randomized)
2527 {
2528 /* We need to recalculate the start index based on a percentage to put the user
2529 around its desired start position and avoid out of bounds */
2530
2531 int percentage_start_index = 100 * start_index / n;
2532 start_index = percentage_start_index * playlist_get_current()->amount / 100;
2533 }
2534
2356 if (global_settings.playlist_shuffle) 2535 if (global_settings.playlist_shuffle)
2357 { 2536 {
2358 start_index = playlist_shuffle(current_tick, c->selected_item); 2537 start_index = playlist_shuffle(current_tick, start_index);
2359 if (!global_settings.play_selected) 2538 if (!global_settings.play_selected)
2360 start_index = 0; 2539 start_index = 0;
2361 } 2540 }
2362 2541
2363 playlist_start(start_index, 0, 0); 2542 playlist_start(start_index, 0, 0);
2543 loaded_entries_crc = tagtree_data_crc(c); /* save crc in case we return */
2364 return 0; 2544 return 0;
2365} 2545}
2366 2546
@@ -2403,11 +2583,11 @@ char *tagtree_get_title(struct tree_context* c)
2403{ 2583{
2404 switch (c->currtable) 2584 switch (c->currtable)
2405 { 2585 {
2406 case ROOT: 2586 case TABLE_ROOT:
2407 return menu->title; 2587 return menu->title;
2408 2588
2409 case NAVIBROWSE: 2589 case TABLE_NAVIBROWSE:
2410 case ALLSUBENTRIES: 2590 case TABLE_ALLSUBENTRIES:
2411 return current_title[c->currextra]; 2591 return current_title[c->currextra];
2412 } 2592 }
2413 2593
@@ -2419,7 +2599,7 @@ int tagtree_get_attr(struct tree_context* c)
2419 int attr = -1; 2599 int attr = -1;
2420 switch (c->currtable) 2600 switch (c->currtable)
2421 { 2601 {
2422 case NAVIBROWSE: 2602 case TABLE_NAVIBROWSE:
2423 if (csi->tagorder[c->currextra] == tag_title 2603 if (csi->tagorder[c->currextra] == tag_title
2424 || csi->tagorder[c->currextra] == tag_virt_basename) 2604 || csi->tagorder[c->currextra] == tag_virt_basename)
2425 attr = FILE_ATTR_AUDIO; 2605 attr = FILE_ATTR_AUDIO;
@@ -2427,7 +2607,7 @@ int tagtree_get_attr(struct tree_context* c)
2427 attr = ATTR_DIRECTORY; 2607 attr = ATTR_DIRECTORY;
2428 break; 2608 break;
2429 2609
2430 case ALLSUBENTRIES: 2610 case TABLE_ALLSUBENTRIES:
2431 attr = FILE_ATTR_AUDIO; 2611 attr = FILE_ATTR_AUDIO;
2432 break; 2612 break;
2433 2613