diff options
author | Paul Sauro <olsroparadise@proton.me> | 2024-08-28 22:55:52 +0200 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2024-08-31 10:44:20 -0400 |
commit | c16dbbfd1fb7bf4bc268a4693bbed21497456b30 (patch) | |
tree | 3faea1f6d294f5835f72075b9a27e996525aef0a /apps | |
parent | f6e8c20188276251d8b3ec512be81f2460ce39e7 (diff) | |
download | rockbox-c16dbbfd1fb7bf4bc268a4693bbed21497456b30.tar.gz rockbox-c16dbbfd1fb7bf4bc268a4693bbed21497456b30.zip |
Reworks to the shuffle system to improve performance and allow fast shuffling from a big library (but this work for all database views)
This improvement brings a huge performance improvement to start a random mix of your library. Previously, the only way to do this was to increase the size of a playlist with absurd sizes number. Now it will respect the limitation but will insert random songs from the current view.
Database: Add true random songs in playlist if it is gonna exceed its maximum capacity
More context is available here : https://www.reddit.com/r/rockbox/comments/1ez0mq4/i_developped_true_full_library_shuffle_for/
Also :
- Improved layout in the DB browser
- New default max playlists capacity is now 2000 on old PortalPlayer targets to give a better user experience and not having to wait dozens of seconds while creating a playlist
- "Show insert shuffled" option is now true by default
- Add a new shortcut to play all songs shuffled in the DB browser
- Now the feature is fully optional and enabled only on targets that have more than 2MB of RAM
- Add entries about this feature in the manual to explain it to the users
Change-Id: I1aebaf7ebcff2bf907080f1861027d530619097c
Change-Id: I3354923b148eeef1975171990e814a1a505d1df0
Diffstat (limited to 'apps')
-rw-r--r-- | apps/gui/wps.c | 4 | ||||
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/lang/francais.lang | 14 | ||||
-rw-r--r-- | apps/onplay.c | 13 | ||||
-rw-r--r-- | apps/onplay.h | 7 | ||||
-rw-r--r-- | apps/playlist_viewer.c | 2 | ||||
-rw-r--r-- | apps/settings_list.c | 8 | ||||
-rw-r--r-- | apps/tagnavi.config | 15 | ||||
-rw-r--r-- | apps/tagtree.c | 228 | ||||
-rw-r--r-- | apps/tagtree.h | 1 | ||||
-rw-r--r-- | apps/tree.c | 27 | ||||
-rw-r--r-- | apps/tree.h | 3 |
12 files changed, 248 insertions, 88 deletions
diff --git a/apps/gui/wps.c b/apps/gui/wps.c index 0de805bd02..82b0394a53 100644 --- a/apps/gui/wps.c +++ b/apps/gui/wps.c | |||
@@ -806,7 +806,7 @@ long gui_wps_show(void) | |||
806 | theme_enabled = false; | 806 | theme_enabled = false; |
807 | gwps_leave_wps(theme_enabled); | 807 | gwps_leave_wps(theme_enabled); |
808 | onplay(state->id3->path, | 808 | onplay(state->id3->path, |
809 | FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey); | 809 | FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey, ONPLAY_NO_CUSTOMACTION); |
810 | if (!audio_status()) | 810 | if (!audio_status()) |
811 | { | 811 | { |
812 | /* re-enable theme since we're returning to SBS */ | 812 | /* re-enable theme since we're returning to SBS */ |
@@ -823,7 +823,7 @@ long gui_wps_show(void) | |||
823 | { | 823 | { |
824 | gwps_leave_wps(true); | 824 | gwps_leave_wps(true); |
825 | int retval = onplay(state->id3->path, | 825 | int retval = onplay(state->id3->path, |
826 | FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey); | 826 | FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey, ONPLAY_NO_CUSTOMACTION); |
827 | /* if music is stopped in the context menu we want to exit the wps */ | 827 | /* if music is stopped in the context menu we want to exit the wps */ |
828 | if (retval == ONPLAY_MAINMENU | 828 | if (retval == ONPLAY_MAINMENU |
829 | || !audio_status()) | 829 | || !audio_status()) |
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index b0c7aed8f7..348f339239 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -2054,6 +2054,20 @@ | |||
2054 | </voice> | 2054 | </voice> |
2055 | </phrase> | 2055 | </phrase> |
2056 | <phrase> | 2056 | <phrase> |
2057 | id: LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY | ||
2058 | desc: a summary splash screen that appear on the database browser when you try to create a playlist from the database browser that exceeds your system limit | ||
2059 | user: core | ||
2060 | <source> | ||
2061 | *: "Selection too big, %d random tracks will be picked from it" | ||
2062 | </source> | ||
2063 | <dest> | ||
2064 | *: "Selection too big, %d random tracks will be picked from it" | ||
2065 | </dest> | ||
2066 | <voice> | ||
2067 | *: "Selection too big, fewer random tracks will be picked from it" | ||
2068 | </voice> | ||
2069 | </phrase> | ||
2070 | <phrase> | ||
2057 | id: LANG_TAGCACHE_RAM | 2071 | id: LANG_TAGCACHE_RAM |
2058 | desc: in tag cache settings | 2072 | desc: in tag cache settings |
2059 | user: core | 2073 | user: core |
diff --git a/apps/lang/francais.lang b/apps/lang/francais.lang index ce907372b0..518b48fb96 100644 --- a/apps/lang/francais.lang +++ b/apps/lang/francais.lang | |||
@@ -2028,6 +2028,20 @@ | |||
2028 | </voice> | 2028 | </voice> |
2029 | </phrase> | 2029 | </phrase> |
2030 | <phrase> | 2030 | <phrase> |
2031 | id: LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY | ||
2032 | desc: a summary splash screen that appear on the database browser when you try to create a playlist from the database browser that exceeds your system limit | ||
2033 | user: core | ||
2034 | <source> | ||
2035 | *: "Selection too big, %d random tracks will be picked from it" | ||
2036 | </source> | ||
2037 | <dest> | ||
2038 | *: "Selection trop grande, %d pistes seront sélectionnées aléatoirement depuis celle-ci" | ||
2039 | </dest> | ||
2040 | <voice> | ||
2041 | *: "Selection trop grande, donc des pistes seront sélectionnées aléatoirement depuis celle-ci" | ||
2042 | </voice> | ||
2043 | </phrase> | ||
2044 | <phrase> | ||
2031 | id: LANG_TAGCACHE_RAM | 2045 | id: LANG_TAGCACHE_RAM |
2032 | desc: in tag cache settings | 2046 | desc: in tag cache settings |
2033 | user: core | 2047 | user: core |
diff --git a/apps/onplay.c b/apps/onplay.c index 4f748204df..045af275bc 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -302,7 +302,7 @@ static int add_to_playlist(void* arg) | |||
302 | 302 | ||
303 | /* warn if replacing the playlist */ | 303 | /* warn if replacing the playlist */ |
304 | if (new_playlist && !warn_on_pl_erase()) | 304 | if (new_playlist && !warn_on_pl_erase()) |
305 | return 0; | 305 | return 1; |
306 | 306 | ||
307 | splash(0, ID2P(LANG_WAIT)); | 307 | splash(0, ID2P(LANG_WAIT)); |
308 | 308 | ||
@@ -340,7 +340,7 @@ static int add_to_playlist(void* arg) | |||
340 | } | 340 | } |
341 | 341 | ||
342 | playlist_set_modified(NULL, true); | 342 | playlist_set_modified(NULL, true); |
343 | return false; | 343 | return 0; |
344 | } | 344 | } |
345 | 345 | ||
346 | static bool view_playlist(void) | 346 | static bool view_playlist(void) |
@@ -1255,7 +1255,7 @@ static int execute_hotkey(bool is_wps) | |||
1255 | } | 1255 | } |
1256 | #endif /* HOTKEY */ | 1256 | #endif /* HOTKEY */ |
1257 | 1257 | ||
1258 | int onplay(char* file, int attr, int from_context, bool hotkey) | 1258 | int onplay(char* file, int attr, int from_context, bool hotkey, int customaction) |
1259 | { | 1259 | { |
1260 | const struct menu_item_ex *menu; | 1260 | const struct menu_item_ex *menu; |
1261 | onplay_result = ONPLAY_OK; | 1261 | onplay_result = ONPLAY_OK; |
@@ -1294,6 +1294,13 @@ int onplay(char* file, int attr, int from_context, bool hotkey) | |||
1294 | #else | 1294 | #else |
1295 | (void)hotkey; | 1295 | (void)hotkey; |
1296 | #endif | 1296 | #endif |
1297 | if (customaction == ONPLAY_CUSTOMACTION_SHUFFLE_SONGS) { | ||
1298 | int returnCode = add_to_playlist(&addtopl_replace_shuffled); | ||
1299 | if (returnCode == 1) | ||
1300 | // User did not want to erase his current playlist, so let's show again the database main menu | ||
1301 | return ONPLAY_RELOAD_DIR; | ||
1302 | return ONPLAY_START_PLAY; | ||
1303 | } | ||
1297 | 1304 | ||
1298 | push_current_activity(ACTIVITY_CONTEXTMENU); | 1305 | push_current_activity(ACTIVITY_CONTEXTMENU); |
1299 | if (from_context == CONTEXT_WPS) | 1306 | if (from_context == CONTEXT_WPS) |
diff --git a/apps/onplay.h b/apps/onplay.h index 74dc045db3..03861e9cf6 100644 --- a/apps/onplay.h +++ b/apps/onplay.h | |||
@@ -25,7 +25,12 @@ | |||
25 | #include "menu.h" | 25 | #include "menu.h" |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | int onplay(char* file, int attr, int from_context, bool hotkey); | 28 | enum { |
29 | ONPLAY_NO_CUSTOMACTION, | ||
30 | ONPLAY_CUSTOMACTION_SHUFFLE_SONGS, | ||
31 | }; | ||
32 | |||
33 | int onplay(char* file, int attr, int from_context, bool hotkey, int customaction); | ||
29 | int get_onplay_context(void); | 34 | int get_onplay_context(void); |
30 | 35 | ||
31 | enum { | 36 | enum { |
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 70072f59f5..5bf547a3fc 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c | |||
@@ -1107,7 +1107,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename, | |||
1107 | } | 1107 | } |
1108 | } | 1108 | } |
1109 | else | 1109 | else |
1110 | onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true); | 1110 | onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true, ONPLAY_NO_CUSTOMACTION); |
1111 | break; | 1111 | break; |
1112 | } | 1112 | } |
1113 | #endif /* HAVE_HOTKEY */ | 1113 | #endif /* HAVE_HOTKEY */ |
diff --git a/apps/settings_list.c b/apps/settings_list.c index 8ec434bd9b..3b29703fe9 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -1120,7 +1120,11 @@ const struct settings_list settings[] = { | |||
1120 | SYSTEM_SETTING(NVRAM(4), topruntime, 0), | 1120 | SYSTEM_SETTING(NVRAM(4), topruntime, 0), |
1121 | INT_SETTING(F_BANFROMQS, max_files_in_playlist, | 1121 | INT_SETTING(F_BANFROMQS, max_files_in_playlist, |
1122 | LANG_MAX_FILES_IN_PLAYLIST, | 1122 | LANG_MAX_FILES_IN_PLAYLIST, |
1123 | #if MEMORYSIZE > 1 | 1123 | #if CONFIG_CPU == PP5002 || CONFIG_CPU == PP5020 || CONFIG_CPU == PP5022 |
1124 | /** Slow CPU benefits greatly from building smaller playlists | ||
1125 | On the iPod Mini 2nd gen, creating a playlist of 2000 entries takes around 10 seconds */ | ||
1126 | 2000, | ||
1127 | #elif MEMORYSIZE > 1 | ||
1124 | 10000, | 1128 | 10000, |
1125 | #else | 1129 | #else |
1126 | 400, | 1130 | 400, |
@@ -1854,7 +1858,7 @@ const struct settings_list settings[] = { | |||
1854 | true, "warn when erasing dynamic playlist",NULL), | 1858 | true, "warn when erasing dynamic playlist",NULL), |
1855 | OFFON_SETTING(0, keep_current_track_on_replace_playlist, LANG_KEEP_CURRENT_TRACK_ON_REPLACE, | 1859 | OFFON_SETTING(0, keep_current_track_on_replace_playlist, LANG_KEEP_CURRENT_TRACK_ON_REPLACE, |
1856 | true, "keep current track when replacing playlist",NULL), | 1860 | true, "keep current track when replacing playlist",NULL), |
1857 | OFFON_SETTING(0, show_shuffled_adding_options, LANG_SHOW_SHUFFLED_ADDING_OPTIONS, false, | 1861 | OFFON_SETTING(0, show_shuffled_adding_options, LANG_SHOW_SHUFFLED_ADDING_OPTIONS, true, |
1858 | "show shuffled adding options", NULL), | 1862 | "show shuffled adding options", NULL), |
1859 | CHOICE_SETTING(0, show_queue_options, LANG_SHOW_QUEUE_OPTIONS, 0, | 1863 | CHOICE_SETTING(0, show_queue_options, LANG_SHOW_QUEUE_OPTIONS, 0, |
1860 | "show queue options", "off,on,in submenu", | 1864 | "show queue options", "off,on,in submenu", |
diff --git a/apps/tagnavi.config b/apps/tagnavi.config index 6eda05ec44..6baa6e1328 100644 --- a/apps/tagnavi.config +++ b/apps/tagnavi.config | |||
@@ -176,20 +176,21 @@ | |||
176 | 176 | ||
177 | # Define the title of the main menu | 177 | # Define the title of the main menu |
178 | %menu_start "main" "Database" | 178 | %menu_start "main" "Database" |
179 | "Artist" -> canonicalartist -> album -> title = "fmt_title" | ||
180 | "Album Artist" -> albumartist -> album -> title = "fmt_title" | 179 | "Album Artist" -> albumartist -> album -> title = "fmt_title" |
180 | "Artist" -> canonicalartist -> album -> title = "fmt_title" | ||
181 | "Album" -> album -> title = "fmt_title" | 181 | "Album" -> album -> title = "fmt_title" |
182 | "Genre" -> genre -> canonicalartist -> album -> title = "fmt_title" | 182 | "Genre" -> genre -> canonicalartist -> album -> title = "fmt_title" |
183 | "Year" -> year ? year > "0" -> canonicalartist -> album -> title = "fmt_title" | ||
183 | "Composer" -> composer -> album -> title = "fmt_title" | 184 | "Composer" -> composer -> album -> title = "fmt_title" |
185 | "A to Z" ==> "a2z" | ||
184 | "Track" ==> "track" | 186 | "Track" ==> "track" |
185 | "Year" -> year ? year > "0" -> canonicalartist -> album -> title = "fmt_title" | 187 | "Shuffle Songs" ~> title = "fmt_title" |
188 | "Search" ==> "search" | ||
186 | "User Rating" -> rating -> title = "fmt_title" | 189 | "User Rating" -> rating -> title = "fmt_title" |
187 | "Recently Added" -> album ? entryage < "4" & commitid > "0" -> title = "fmt_title" | 190 | "Recently Added" -> album ? entryage < "4" & commitid > "0" -> title = "fmt_title" |
188 | "A to Z..." ==> "a2z" | 191 | "History" ==> "runtime" |
189 | "History..." ==> "runtime" | 192 | "Same as current" ==> "same" |
190 | "Same as current..." ==> "same" | 193 | "Custom view" ==> "custom" |
191 | "Search..." ==> "search" | ||
192 | "Custom view..." ==> "custom" | ||
193 | 194 | ||
194 | # And finally set main menu as our root menu | 195 | # And finally set main menu as our root menu |
195 | %root_menu "main" | 196 | %root_menu "main" |
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 | ||
diff --git a/apps/tagtree.h b/apps/tagtree.h index 39ab545bd0..a57a5c2f80 100644 --- a/apps/tagtree.h +++ b/apps/tagtree.h | |||
@@ -45,6 +45,7 @@ char *tagtree_get_title(struct tree_context* c); | |||
45 | int tagtree_get_attr(struct tree_context* c); | 45 | int tagtree_get_attr(struct tree_context* c); |
46 | int tagtree_get_icon(struct tree_context* c); | 46 | int tagtree_get_icon(struct tree_context* c); |
47 | int tagtree_get_filename(struct tree_context* c, char *buf, int buflen); | 47 | int tagtree_get_filename(struct tree_context* c, char *buf, int buflen); |
48 | int tagtree_get_custom_action(struct tree_context* c); | ||
48 | bool tagtree_get_subentry_filename(char *buf, size_t bufsize); | 49 | bool tagtree_get_subentry_filename(char *buf, size_t bufsize); |
49 | bool tagtree_subentries_do_action(bool (*action_cb)(const char *file_name)); | 50 | bool tagtree_subentries_do_action(bool (*action_cb)(const char *file_name)); |
50 | 51 | ||
diff --git a/apps/tree.c b/apps/tree.c index 71a7ee3f62..b4cd9d77b0 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -735,6 +735,17 @@ static int dirbrowse(void) | |||
735 | oldbutton = button; | 735 | oldbutton = button; |
736 | gui_synclist_do_button(&tree_lists, &button); | 736 | gui_synclist_do_button(&tree_lists, &button); |
737 | tc.selected_item = gui_synclist_get_sel_pos(&tree_lists); | 737 | tc.selected_item = gui_synclist_get_sel_pos(&tree_lists); |
738 | int customaction = ONPLAY_NO_CUSTOMACTION; | ||
739 | bool do_restore_display = true; | ||
740 | #ifdef HAVE_TAGCACHE | ||
741 | if (id3db && (button == ACTION_STD_OK || button == ACTION_STD_CONTEXT)) { | ||
742 | customaction = tagtree_get_custom_action(&tc); | ||
743 | if (customaction == ONPLAY_CUSTOMACTION_SHUFFLE_SONGS) { | ||
744 | button = ACTION_STD_CONTEXT; /** The code to insert shuffled is on the context branch of the switch so we always go here */ | ||
745 | do_restore_display = false; | ||
746 | } | ||
747 | } | ||
748 | #endif | ||
738 | switch ( button ) { | 749 | switch ( button ) { |
739 | case ACTION_STD_OK: | 750 | case ACTION_STD_OK: |
740 | /* nothing to do if no files to display */ | 751 | /* nothing to do if no files to display */ |
@@ -773,7 +784,7 @@ static int dirbrowse(void) | |||
773 | default: | 784 | default: |
774 | break; | 785 | break; |
775 | } | 786 | } |
776 | restore = true; | 787 | restore = do_restore_display; |
777 | break; | 788 | break; |
778 | 789 | ||
779 | case ACTION_STD_CANCEL: | 790 | case ACTION_STD_CANCEL: |
@@ -798,12 +809,12 @@ static int dirbrowse(void) | |||
798 | if (ft_exit(&tc) == 3) | 809 | if (ft_exit(&tc) == 3) |
799 | exit_func = true; | 810 | exit_func = true; |
800 | 811 | ||
801 | restore = true; | 812 | restore = do_restore_display; |
802 | break; | 813 | break; |
803 | 814 | ||
804 | case ACTION_TREE_STOP: | 815 | case ACTION_TREE_STOP: |
805 | if (list_stop_handler()) | 816 | if (list_stop_handler()) |
806 | restore = true; | 817 | restore = do_restore_display; |
807 | break; | 818 | break; |
808 | 819 | ||
809 | case ACTION_STD_MENU: | 820 | case ACTION_STD_MENU: |
@@ -851,7 +862,7 @@ static int dirbrowse(void) | |||
851 | skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL); | 862 | skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL); |
852 | } | 863 | } |
853 | 864 | ||
854 | restore = true; | 865 | restore = do_restore_display; |
855 | break; | 866 | break; |
856 | } | 867 | } |
857 | #endif | 868 | #endif |
@@ -872,7 +883,7 @@ static int dirbrowse(void) | |||
872 | break; | 883 | break; |
873 | 884 | ||
874 | if(!numentries) | 885 | if(!numentries) |
875 | onplay_result = onplay(NULL, 0, curr_context, hotkey); | 886 | onplay_result = onplay(NULL, 0, curr_context, hotkey, customaction); |
876 | else { | 887 | else { |
877 | #ifdef HAVE_TAGCACHE | 888 | #ifdef HAVE_TAGCACHE |
878 | if (id3db) | 889 | if (id3db) |
@@ -902,7 +913,7 @@ static int dirbrowse(void) | |||
902 | ft_assemble_path(buf, sizeof(buf), currdir, entry->name); | 913 | ft_assemble_path(buf, sizeof(buf), currdir, entry->name); |
903 | 914 | ||
904 | } | 915 | } |
905 | onplay_result = onplay(buf, attr, curr_context, hotkey); | 916 | onplay_result = onplay(buf, attr, curr_context, hotkey, customaction); |
906 | } | 917 | } |
907 | switch (onplay_result) | 918 | switch (onplay_result) |
908 | { | 919 | { |
@@ -911,7 +922,7 @@ static int dirbrowse(void) | |||
911 | break; | 922 | break; |
912 | 923 | ||
913 | case ONPLAY_OK: | 924 | case ONPLAY_OK: |
914 | restore = true; | 925 | restore = do_restore_display; |
915 | break; | 926 | break; |
916 | 927 | ||
917 | case ONPLAY_RELOAD_DIR: | 928 | case ONPLAY_RELOAD_DIR: |
@@ -988,7 +999,7 @@ static int dirbrowse(void) | |||
988 | 999 | ||
989 | lastfilter = *tc.dirfilter; | 1000 | lastfilter = *tc.dirfilter; |
990 | lastsortcase = global_settings.sort_case; | 1001 | lastsortcase = global_settings.sort_case; |
991 | restore = true; | 1002 | restore = do_restore_display; |
992 | } | 1003 | } |
993 | 1004 | ||
994 | if (exit_func) | 1005 | if (exit_func) |
diff --git a/apps/tree.h b/apps/tree.h index d13c75d434..e958bbf109 100644 --- a/apps/tree.h +++ b/apps/tree.h | |||
@@ -33,6 +33,9 @@ struct entry { | |||
33 | char *name; | 33 | char *name; |
34 | int attr; /* FAT attributes + file type flags */ | 34 | int attr; /* FAT attributes + file type flags */ |
35 | unsigned time_write; /* Last write time */ | 35 | unsigned time_write; /* Last write time */ |
36 | #ifdef HAVE_TAGCACHE | ||
37 | int customaction; /* db use */ | ||
38 | #endif | ||
36 | }; | 39 | }; |
37 | 40 | ||
38 | #define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */ | 41 | #define BROWSE_SELECTONLY 0x0001 /* exit on selecting a file */ |