diff options
Diffstat (limited to 'apps/tagtree.c')
-rw-r--r-- | apps/tagtree.c | 228 |
1 files changed, 164 insertions, 64 deletions
diff --git a/apps/tagtree.c b/apps/tagtree.c index d2e27a3e58..4a0bff32bd 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -56,6 +56,7 @@ | |||
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" | ||
59 | 60 | ||
60 | #define str_or_empty(x) (x ? x : "(NULL)") | 61 | #define str_or_empty(x) (x ? x : "(NULL)") |
61 | 62 | ||
@@ -71,6 +72,7 @@ struct tagentry { | |||
71 | char* name; | 72 | char* name; |
72 | int newtable; | 73 | int newtable; |
73 | int extraseek; | 74 | int extraseek; |
75 | int customaction; | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); | 78 | static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); |
@@ -78,10 +80,10 @@ static struct tagentry* tagtree_get_entry(struct tree_context *c, int id); | |||
78 | #define SEARCHSTR_SIZE 256 | 80 | #define SEARCHSTR_SIZE 256 |
79 | 81 | ||
80 | enum table { | 82 | enum table { |
81 | ROOT = 1, | 83 | TABLE_ROOT = 1, |
82 | NAVIBROWSE, | 84 | TABLE_NAVIBROWSE, |
83 | ALLSUBENTRIES, | 85 | TABLE_ALLSUBENTRIES, |
84 | PLAYTRACK, | 86 | TABLE_PLAYTRACK, |
85 | }; | 87 | }; |
86 | 88 | ||
87 | static const struct id3_to_search_mapping { | 89 | static const struct id3_to_search_mapping { |
@@ -108,12 +110,21 @@ enum variables { | |||
108 | menu_next, | 110 | menu_next, |
109 | menu_load, | 111 | menu_load, |
110 | menu_reload, | 112 | menu_reload, |
113 | menu_shuffle_songs, | ||
111 | }; | 114 | }; |
112 | 115 | ||
113 | /* Capacity 10 000 entries (for example 10k different artists) */ | 116 | /* Capacity 10 000 entries (for example 10k different artists) */ |
114 | #define UNIQBUF_SIZE (64*1024) | 117 | #define UNIQBUF_SIZE (64*1024) |
115 | static uint32_t uniqbuf[UNIQBUF_SIZE / sizeof(uint32_t)]; | 118 | static uint32_t uniqbuf[UNIQBUF_SIZE / sizeof(uint32_t)]; |
116 | 119 | ||
120 | #if MEMORYSIZE > 2 | ||
121 | #define INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE (1024) | ||
122 | #else | ||
123 | /* Lower quality randomness for low-ram devices using smaller segments */ | ||
124 | #define INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE (128) | ||
125 | #endif | ||
126 | static bool selective_random_playlist_indexes[INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE]; | ||
127 | |||
117 | #define MAX_TAGS 5 | 128 | #define MAX_TAGS 5 |
118 | #define MAX_MENU_ID_SIZE 32 | 129 | #define MAX_MENU_ID_SIZE 32 |
119 | 130 | ||
@@ -338,6 +349,7 @@ static int get_tag(int *tag) | |||
338 | TAG_MATCH("Pm", tag_virt_playtime_min), | 349 | TAG_MATCH("Pm", tag_virt_playtime_min), |
339 | TAG_MATCH("Ps", tag_virt_playtime_sec), | 350 | TAG_MATCH("Ps", tag_virt_playtime_sec), |
340 | TAG_MATCH("->", menu_next), | 351 | TAG_MATCH("->", menu_next), |
352 | TAG_MATCH("~>", menu_shuffle_songs), | ||
341 | 353 | ||
342 | TAG_MATCH("==>", menu_load), | 354 | TAG_MATCH("==>", menu_load), |
343 | 355 | ||
@@ -820,7 +832,7 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
820 | return true; | 832 | return true; |
821 | } | 833 | } |
822 | 834 | ||
823 | if (entry->type != menu_next) | 835 | if (entry->type != menu_next && entry->type != menu_shuffle_songs) |
824 | return false; | 836 | return false; |
825 | 837 | ||
826 | while (inst->tagorder_count < MAX_TAGS) | 838 | while (inst->tagorder_count < MAX_TAGS) |
@@ -847,7 +859,7 @@ static bool parse_search(struct menu_entry *entry, const char *str) | |||
847 | 859 | ||
848 | inst->tagorder_count++; | 860 | inst->tagorder_count++; |
849 | 861 | ||
850 | if (get_tag(&type) <= 0 || type != menu_next) | 862 | if (get_tag(&type) <= 0 || (type != menu_next && type != menu_shuffle_songs)) |
851 | break; | 863 | break; |
852 | } | 864 | } |
853 | 865 | ||
@@ -1245,6 +1257,7 @@ static void tagtree_unload(struct tree_context *c) | |||
1245 | dptr->name = NULL; | 1257 | dptr->name = NULL; |
1246 | dptr->newtable = 0; | 1258 | dptr->newtable = 0; |
1247 | dptr->extraseek = 0; | 1259 | dptr->extraseek = 0; |
1260 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1248 | dptr++; | 1261 | dptr++; |
1249 | } | 1262 | } |
1250 | } | 1263 | } |
@@ -1454,7 +1467,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1454 | #endif | 1467 | #endif |
1455 | , 0, 0, 0); | 1468 | , 0, 0, 0); |
1456 | 1469 | ||
1457 | if (c->currtable == ALLSUBENTRIES) | 1470 | if (c->currtable == TABLE_ALLSUBENTRIES) |
1458 | { | 1471 | { |
1459 | tag = tag_title; | 1472 | tag = tag_title; |
1460 | level--; | 1473 | level--; |
@@ -1544,17 +1557,19 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1544 | { | 1557 | { |
1545 | if (offset == 0) | 1558 | if (offset == 0) |
1546 | { | 1559 | { |
1547 | dptr->newtable = ALLSUBENTRIES; | 1560 | dptr->newtable = TABLE_ALLSUBENTRIES; |
1548 | dptr->name = str(LANG_TAGNAVI_ALL_TRACKS); | 1561 | dptr->name = str(LANG_TAGNAVI_ALL_TRACKS); |
1562 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1549 | dptr++; | 1563 | dptr++; |
1550 | current_entry_count++; | 1564 | current_entry_count++; |
1551 | special_entry_count++; | 1565 | special_entry_count++; |
1552 | } | 1566 | } |
1553 | if (offset <= 1) | 1567 | if (offset <= 1) |
1554 | { | 1568 | { |
1555 | dptr->newtable = NAVIBROWSE; | 1569 | dptr->newtable = TABLE_NAVIBROWSE; |
1556 | dptr->name = str(LANG_TAGNAVI_RANDOM); | 1570 | dptr->name = str(LANG_TAGNAVI_RANDOM); |
1557 | dptr->extraseek = -1; | 1571 | dptr->extraseek = -1; |
1572 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1558 | dptr++; | 1573 | dptr++; |
1559 | current_entry_count++; | 1574 | current_entry_count++; |
1560 | special_entry_count++; | 1575 | special_entry_count++; |
@@ -1568,14 +1583,15 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init) | |||
1568 | if (total_count++ < offset) | 1583 | if (total_count++ < offset) |
1569 | continue; | 1584 | continue; |
1570 | 1585 | ||
1571 | dptr->newtable = NAVIBROWSE; | 1586 | dptr->newtable = TABLE_NAVIBROWSE; |
1572 | if (tag == tag_title || tag == tag_filename) | 1587 | if (tag == tag_title || tag == tag_filename) |
1573 | { | 1588 | { |
1574 | dptr->newtable = PLAYTRACK; | 1589 | dptr->newtable = TABLE_PLAYTRACK; |
1575 | dptr->extraseek = tcs.idx_id; | 1590 | dptr->extraseek = tcs.idx_id; |
1576 | } | 1591 | } |
1577 | else | 1592 | else |
1578 | dptr->extraseek = tcs.result_seek; | 1593 | dptr->extraseek = tcs.result_seek; |
1594 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1579 | 1595 | ||
1580 | fmt = NULL; | 1596 | fmt = NULL; |
1581 | /* Check the format */ | 1597 | /* Check the format */ |
@@ -1758,7 +1774,7 @@ static int load_root(struct tree_context *c) | |||
1758 | int i; | 1774 | int i; |
1759 | 1775 | ||
1760 | tc = c; | 1776 | tc = c; |
1761 | c->currtable = ROOT; | 1777 | c->currtable = TABLE_ROOT; |
1762 | if (c->dirlevel == 0) | 1778 | if (c->dirlevel == 0) |
1763 | c->currextra = rootmenu; | 1779 | c->currextra = rootmenu; |
1764 | 1780 | ||
@@ -1775,13 +1791,21 @@ static int load_root(struct tree_context *c) | |||
1775 | switch (menu->items[i]->type) | 1791 | switch (menu->items[i]->type) |
1776 | { | 1792 | { |
1777 | case menu_next: | 1793 | case menu_next: |
1778 | dptr->newtable = NAVIBROWSE; | 1794 | dptr->newtable = TABLE_NAVIBROWSE; |
1779 | dptr->extraseek = i; | 1795 | dptr->extraseek = i; |
1796 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1780 | break; | 1797 | break; |
1781 | 1798 | ||
1782 | case menu_load: | 1799 | case menu_load: |
1783 | dptr->newtable = ROOT; | 1800 | dptr->newtable = TABLE_ROOT; |
1784 | dptr->extraseek = menu->items[i]->link; | 1801 | dptr->extraseek = menu->items[i]->link; |
1802 | dptr->customaction = ONPLAY_NO_CUSTOMACTION; | ||
1803 | break; | ||
1804 | |||
1805 | case menu_shuffle_songs: | ||
1806 | dptr->newtable = TABLE_NAVIBROWSE; | ||
1807 | dptr->extraseek = i; | ||
1808 | dptr->customaction = ONPLAY_CUSTOMACTION_SHUFFLE_SONGS; | ||
1785 | break; | 1809 | break; |
1786 | } | 1810 | } |
1787 | 1811 | ||
@@ -1804,19 +1828,19 @@ int tagtree_load(struct tree_context* c) | |||
1804 | if (!table) | 1828 | if (!table) |
1805 | { | 1829 | { |
1806 | c->dirfull = false; | 1830 | c->dirfull = false; |
1807 | table = ROOT; | 1831 | table = TABLE_ROOT; |
1808 | c->currtable = table; | 1832 | c->currtable = table; |
1809 | c->currextra = rootmenu; | 1833 | c->currextra = rootmenu; |
1810 | } | 1834 | } |
1811 | 1835 | ||
1812 | switch (table) | 1836 | switch (table) |
1813 | { | 1837 | { |
1814 | case ROOT: | 1838 | case TABLE_ROOT: |
1815 | count = load_root(c); | 1839 | count = load_root(c); |
1816 | break; | 1840 | break; |
1817 | 1841 | ||
1818 | case ALLSUBENTRIES: | 1842 | case TABLE_ALLSUBENTRIES: |
1819 | case NAVIBROWSE: | 1843 | case TABLE_NAVIBROWSE: |
1820 | logf("navibrowse..."); | 1844 | logf("navibrowse..."); |
1821 | cpu_boost(true); | 1845 | cpu_boost(true); |
1822 | count = retrieve_entries(c, 0, true); | 1846 | count = retrieve_entries(c, 0, true); |
@@ -1921,16 +1945,16 @@ int tagtree_enter(struct tree_context* c, bool is_visible) | |||
1921 | core_pin(tagtree_handle); | 1945 | core_pin(tagtree_handle); |
1922 | 1946 | ||
1923 | switch (c->currtable) { | 1947 | switch (c->currtable) { |
1924 | case ROOT: | 1948 | case TABLE_ROOT: |
1925 | c->currextra = newextra; | 1949 | c->currextra = newextra; |
1926 | 1950 | ||
1927 | if (newextra == ROOT) | 1951 | if (newextra == TABLE_ROOT) |
1928 | { | 1952 | { |
1929 | menu = menus[seek]; | 1953 | menu = menus[seek]; |
1930 | c->currextra = seek; | 1954 | c->currextra = seek; |
1931 | } | 1955 | } |
1932 | 1956 | ||
1933 | else if (newextra == NAVIBROWSE) | 1957 | else if (newextra == TABLE_NAVIBROWSE) |
1934 | { | 1958 | { |
1935 | int i, j; | 1959 | int i, j; |
1936 | 1960 | ||
@@ -2005,9 +2029,9 @@ int tagtree_enter(struct tree_context* c, bool is_visible) | |||
2005 | 2029 | ||
2006 | break; | 2030 | break; |
2007 | 2031 | ||
2008 | case NAVIBROWSE: | 2032 | case TABLE_NAVIBROWSE: |
2009 | case ALLSUBENTRIES: | 2033 | case TABLE_ALLSUBENTRIES: |
2010 | if (newextra == PLAYTRACK) | 2034 | if (newextra == TABLE_PLAYTRACK) |
2011 | { | 2035 | { |
2012 | adjust_selection = false; | 2036 | adjust_selection = false; |
2013 | 2037 | ||
@@ -2102,13 +2126,46 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) | |||
2102 | return 0; | 2126 | return 0; |
2103 | } | 2127 | } |
2104 | 2128 | ||
2129 | int tagtree_get_custom_action(struct tree_context* c) | ||
2130 | { | ||
2131 | return tagtree_get_entry(c, c->selected_item)->customaction; | ||
2132 | } | ||
2133 | |||
2134 | static void swap_array_bool(bool *a, bool *b) { | ||
2135 | bool temp = *a; | ||
2136 | *a = *b; | ||
2137 | *b = temp; | ||
2138 | } | ||
2139 | |||
2140 | /** | ||
2141 | * Randomly shuffle an array using the Fisher-Yates algorithm : https://en.wikipedia.org/wiki/Random_permutation | ||
2142 | * This algorithm has a linear complexity. Don't forget to srand before call to use it with a relevant seed. | ||
2143 | */ | ||
2144 | static void shuffle_bool_array(bool array[], int size) { | ||
2145 | for (int i = size - 1; i > 0; i--) { | ||
2146 | int j = rand() % (i + 1); | ||
2147 | swap_array_bool(&array[i], &array[j]); | ||
2148 | } | ||
2149 | } | ||
2150 | |||
2151 | static bool fill_selective_random_playlist_indexes(int current_segment_n, int current_segment_max_available_space) { | ||
2152 | if (current_segment_n == 0 || current_segment_max_available_space == 0) | ||
2153 | return false; | ||
2154 | if (current_segment_max_available_space > current_segment_n) | ||
2155 | current_segment_max_available_space = current_segment_n; | ||
2156 | for (int i = 0; i < current_segment_n; i++) | ||
2157 | selective_random_playlist_indexes[i] = i < current_segment_max_available_space; | ||
2158 | srand(current_tick); | ||
2159 | shuffle_bool_array(selective_random_playlist_indexes, current_segment_n); | ||
2160 | return true; | ||
2161 | } | ||
2105 | 2162 | ||
2106 | static bool insert_all_playlist(struct tree_context *c, | 2163 | static bool insert_all_playlist(struct tree_context *c, |
2107 | const char* playlist, bool new_playlist, | 2164 | const char* playlist, bool new_playlist, |
2108 | int position, bool queue) | 2165 | int position, bool queue) |
2109 | { | 2166 | { |
2110 | struct tagcache_search tcs; | 2167 | struct tagcache_search tcs; |
2111 | int i, n; | 2168 | int n; |
2112 | int fd = -1; | 2169 | int fd = -1; |
2113 | unsigned long last_tick; | 2170 | unsigned long last_tick; |
2114 | char buf[MAX_PATH]; | 2171 | char buf[MAX_PATH]; |
@@ -2144,44 +2201,77 @@ static bool insert_all_playlist(struct tree_context *c, | |||
2144 | return false; | 2201 | return false; |
2145 | } | 2202 | } |
2146 | } | 2203 | } |
2147 | |||
2148 | last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */ | 2204 | 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 */ | 2205 | splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */ |
2150 | n = c->filesindir; | 2206 | n = c->filesindir; |
2151 | for (i = 0; i < n; i++) | 2207 | int segment_size = INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE; |
2152 | { | 2208 | int segments_count = n / segment_size; |
2153 | 2209 | int leftovers_segment_size = n % segment_size; | |
2154 | splash_progress(i, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT)); | 2210 | bool fill_randomly = false; |
2155 | if (TIME_AFTER(current_tick, last_tick + HZ/4)) | 2211 | if (playlist == NULL) { |
2156 | { | 2212 | bool will_exceed = n > playlist_get_current()->max_playlist_size; |
2157 | if (action_userabort(TIMEOUT_NOBLOCK)) | 2213 | fill_randomly = will_exceed; |
2158 | break; | 2214 | } |
2159 | last_tick = current_tick; | 2215 | if (leftovers_segment_size > 0 && fill_randomly) { |
2216 | // We need to re-balance the segments so the randomness will be coherent and balanced the same through all segments | ||
2217 | while (leftovers_segment_size + segments_count < segment_size) { | ||
2218 | segment_size--; // -1 to all other segments | ||
2219 | leftovers_segment_size += segments_count; | ||
2160 | } | 2220 | } |
2161 | 2221 | } | |
2162 | if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek, | 2222 | if (leftovers_segment_size > 0) |
2163 | tcs.type, buf, sizeof buf)) | 2223 | segments_count += 1; |
2164 | { | 2224 | int max_available_space = playlist_get_current()->max_playlist_size - playlist_get_current()->amount; |
2165 | continue; | 2225 | int max_available_space_per_segment = max_available_space / segments_count; |
2226 | if (fill_randomly) { | ||
2227 | talk_id(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY, true); | ||
2228 | splashf(HZ * 3, str(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY), max_available_space_per_segment * segments_count); | ||
2229 | //splashf(HZ * 5, "sz=%d lsz=%d sc=%d rcps=%d", segment_size, leftovers_segment_size, segments_count, max_available_space_per_segment); | ||
2230 | } | ||
2231 | for (int i = 0; i < segments_count; i++) { | ||
2232 | bool is_leftovers_segment = leftovers_segment_size > 0 && i + 1 >= segments_count; | ||
2233 | if (fill_randomly) { | ||
2234 | if (is_leftovers_segment) | ||
2235 | fill_randomly = fill_selective_random_playlist_indexes(leftovers_segment_size, max_available_space_per_segment); | ||
2236 | else | ||
2237 | fill_randomly = fill_selective_random_playlist_indexes(segment_size, max_available_space_per_segment); | ||
2166 | } | 2238 | } |
2167 | 2239 | bool exit_loop_now = false; | |
2168 | if (playlist == NULL) | 2240 | int cur_segment_start = i * segment_size; |
2169 | { | 2241 | int cur_segment_end; |
2170 | if (playlist_insert_track(NULL, buf, position, queue, false) < 0) | 2242 | if (is_leftovers_segment) |
2171 | { | 2243 | cur_segment_end = cur_segment_start + leftovers_segment_size; |
2172 | logf("playlist_insert_track failed"); | 2244 | else |
2173 | break; | 2245 | cur_segment_end = cur_segment_start + segment_size; |
2246 | for (int j = cur_segment_start; j < cur_segment_end && !exit_loop_now; j++) { | ||
2247 | if (fill_randomly && !selective_random_playlist_indexes[j % segment_size]) | ||
2248 | continue; | ||
2249 | splash_progress(j, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT)); | ||
2250 | if (TIME_AFTER(current_tick, last_tick + HZ/4)) { | ||
2251 | if (action_userabort(TIMEOUT_NOBLOCK)) { | ||
2252 | exit_loop_now = true; | ||
2253 | break; | ||
2254 | } | ||
2255 | last_tick = current_tick; | ||
2174 | } | 2256 | } |
2175 | } | 2257 | if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, j)->extraseek, tcs.type, buf, sizeof buf)) |
2176 | else if (fdprintf(fd, "%s\n", buf) <= 0) | 2258 | continue; |
2259 | if (playlist == NULL) { | ||
2260 | if (playlist_insert_track(NULL, buf, position, queue, false) < 0) { | ||
2261 | logf("playlist_insert_track failed"); | ||
2262 | exit_loop_now = true; | ||
2263 | break; | ||
2264 | } | ||
2265 | } else if (fdprintf(fd, "%s\n", buf) <= 0) { | ||
2266 | exit_loop_now = true; | ||
2177 | break; | 2267 | break; |
2178 | 2268 | } | |
2179 | yield(); | 2269 | yield(); |
2180 | 2270 | if (playlist == NULL && position == PLAYLIST_INSERT_FIRST) | |
2181 | if (playlist == NULL && position == PLAYLIST_INSERT_FIRST) | 2271 | position = PLAYLIST_INSERT; |
2182 | { | ||
2183 | position = PLAYLIST_INSERT; | ||
2184 | } | 2272 | } |
2273 | if (exit_loop_now) | ||
2274 | break; | ||
2185 | } | 2275 | } |
2186 | if (playlist == NULL) | 2276 | if (playlist == NULL) |
2187 | playlist_sync(NULL); | 2277 | playlist_sync(NULL); |
@@ -2196,14 +2286,14 @@ static bool insert_all_playlist(struct tree_context *c, | |||
2196 | static bool goto_allsubentries(int newtable) | 2286 | static bool goto_allsubentries(int newtable) |
2197 | { | 2287 | { |
2198 | int i = 0; | 2288 | int i = 0; |
2199 | while (i < 2 && (newtable == NAVIBROWSE || newtable == ALLSUBENTRIES)) | 2289 | while (i < 2 && (newtable == TABLE_NAVIBROWSE || newtable == TABLE_ALLSUBENTRIES)) |
2200 | { | 2290 | { |
2201 | tagtree_enter(tc, false); | 2291 | tagtree_enter(tc, false); |
2202 | tagtree_load(tc); | 2292 | tagtree_load(tc); |
2203 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; | 2293 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; |
2204 | i++; | 2294 | i++; |
2205 | } | 2295 | } |
2206 | return (newtable == PLAYTRACK); | 2296 | return (newtable == TABLE_PLAYTRACK); |
2207 | } | 2297 | } |
2208 | 2298 | ||
2209 | static void reset_tc_to_prev(int dirlevel, int selected_item) | 2299 | static void reset_tc_to_prev(int dirlevel, int selected_item) |
@@ -2233,7 +2323,7 @@ static bool tagtree_insert_selection(int position, bool queue, | |||
2233 | 2323 | ||
2234 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; | 2324 | newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; |
2235 | 2325 | ||
2236 | if (newtable == PLAYTRACK) /* Insert a single track? */ | 2326 | if (newtable == TABLE_PLAYTRACK) /* Insert a single track? */ |
2237 | { | 2327 | { |
2238 | if (tagtree_get_filename(tc, buf, sizeof buf) < 0) | 2328 | if (tagtree_get_filename(tc, buf, sizeof buf) < 0) |
2239 | return false; | 2329 | return false; |
@@ -2353,9 +2443,19 @@ static int tagtree_play_folder(struct tree_context* c) | |||
2353 | if (!insert_all_playlist(c, NULL, false, PLAYLIST_INSERT_LAST, false)) | 2443 | if (!insert_all_playlist(c, NULL, false, PLAYLIST_INSERT_LAST, false)) |
2354 | return -2; | 2444 | return -2; |
2355 | 2445 | ||
2446 | int n = c->filesindir; | ||
2447 | bool has_playlist_been_randomized = n > playlist_get_current()->max_playlist_size; | ||
2448 | if (has_playlist_been_randomized) { | ||
2449 | /* We need to recalculate the start index based on a percentage to put the user | ||
2450 | around its desired start position and avoid out of bounds */ | ||
2451 | |||
2452 | int percentage_start_index = 100 * start_index / n; | ||
2453 | start_index = percentage_start_index * playlist_get_current()->amount / 100; | ||
2454 | } | ||
2455 | |||
2356 | if (global_settings.playlist_shuffle) | 2456 | if (global_settings.playlist_shuffle) |
2357 | { | 2457 | { |
2358 | start_index = playlist_shuffle(current_tick, c->selected_item); | 2458 | start_index = playlist_shuffle(current_tick, start_index); |
2359 | if (!global_settings.play_selected) | 2459 | if (!global_settings.play_selected) |
2360 | start_index = 0; | 2460 | start_index = 0; |
2361 | } | 2461 | } |
@@ -2403,11 +2503,11 @@ char *tagtree_get_title(struct tree_context* c) | |||
2403 | { | 2503 | { |
2404 | switch (c->currtable) | 2504 | switch (c->currtable) |
2405 | { | 2505 | { |
2406 | case ROOT: | 2506 | case TABLE_ROOT: |
2407 | return menu->title; | 2507 | return menu->title; |
2408 | 2508 | ||
2409 | case NAVIBROWSE: | 2509 | case TABLE_NAVIBROWSE: |
2410 | case ALLSUBENTRIES: | 2510 | case TABLE_ALLSUBENTRIES: |
2411 | return current_title[c->currextra]; | 2511 | return current_title[c->currextra]; |
2412 | } | 2512 | } |
2413 | 2513 | ||
@@ -2419,7 +2519,7 @@ int tagtree_get_attr(struct tree_context* c) | |||
2419 | int attr = -1; | 2519 | int attr = -1; |
2420 | switch (c->currtable) | 2520 | switch (c->currtable) |
2421 | { | 2521 | { |
2422 | case NAVIBROWSE: | 2522 | case TABLE_NAVIBROWSE: |
2423 | if (csi->tagorder[c->currextra] == tag_title | 2523 | if (csi->tagorder[c->currextra] == tag_title |
2424 | || csi->tagorder[c->currextra] == tag_virt_basename) | 2524 | || csi->tagorder[c->currextra] == tag_virt_basename) |
2425 | attr = FILE_ATTR_AUDIO; | 2525 | attr = FILE_ATTR_AUDIO; |
@@ -2427,7 +2527,7 @@ int tagtree_get_attr(struct tree_context* c) | |||
2427 | attr = ATTR_DIRECTORY; | 2527 | attr = ATTR_DIRECTORY; |
2428 | break; | 2528 | break; |
2429 | 2529 | ||
2430 | case ALLSUBENTRIES: | 2530 | case TABLE_ALLSUBENTRIES: |
2431 | attr = FILE_ATTR_AUDIO; | 2531 | attr = FILE_ATTR_AUDIO; |
2432 | break; | 2532 | break; |
2433 | 2533 | ||