1
0
Fork 0
forked from len0rd/rockbox

Reworks to the shuffle system

spread remaining songs amongst segments
bit of code clean-up

Change-Id: I198b54978eb9d111e060bb9aca3d71c348cad7c9
This commit is contained in:
William Wilgus 2024-09-02 22:55:37 -04:00 committed by William Wilgus
parent 34e54b33f7
commit 55e1a78cf8
2 changed files with 66 additions and 33 deletions

View file

@ -2058,13 +2058,13 @@
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 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
user: core user: core
<source> <source>
*: "Selection too big, %d random tracks will be picked from it" *: "Selection too big, %d random tracks will be selected"
</source> </source>
<dest> <dest>
*: "Selection too big, %d random tracks will be picked from it" *: "Selection too big, %d random tracks will be selected"
</dest> </dest>
<voice> <voice>
*: "Selection too big, fewer random tracks will be picked from it" *: "Selection too big, fewer random tracks will be selected"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>

View file

@ -2139,8 +2139,10 @@ static void swap_array_bool(bool *a, bool *b)
} }
/** /**
* Randomly shuffle an array using the Fisher-Yates algorithm : https://en.wikipedia.org/wiki/Random_permutation * Randomly shuffle an array using the Fisher-Yates algorithm :
* This algorithm has a linear complexity. Don't forget to srand before call to use it with a relevant seed. * https://en.wikipedia.org/wiki/Random_permutation
* This algorithm has a linear complexity. Don't forget to srand
* before call to use it with a relevant seed.
*/ */
static void shuffle_bool_array(bool array[], int size) static void shuffle_bool_array(bool array[], int size)
{ {
@ -2151,14 +2153,15 @@ static void shuffle_bool_array(bool array[], int size)
} }
} }
static bool fill_selective_random_playlist_indexes(int current_segment_n, int current_segment_max_available_space) static bool fill_random_playlist_indexes(int current_segment_n,
int current_segment_max_space)
{ {
if (current_segment_n == 0 || current_segment_max_available_space == 0) if (current_segment_n == 0 || current_segment_max_space == 0)
return false; return false;
if (current_segment_max_available_space > current_segment_n) if (current_segment_max_space > current_segment_n)
current_segment_max_available_space = current_segment_n; current_segment_max_space = current_segment_n;
for (int i = 0; i < current_segment_n; i++) for (int i = 0; i < current_segment_n; i++)
selective_random_playlist_indexes[i] = i < current_segment_max_available_space; selective_random_playlist_indexes[i] = i < current_segment_max_space;
srand(current_tick); srand(current_tick);
shuffle_bool_array(selective_random_playlist_indexes, current_segment_n); shuffle_bool_array(selective_random_playlist_indexes, current_segment_n);
return true; return true;
@ -2205,20 +2208,27 @@ static bool insert_all_playlist(struct tree_context *c,
return false; return false;
} }
} }
last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */ last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */
splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */ splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
n = c->filesindir; n = c->filesindir;
int max_playlist_size = playlist_get_current()->max_playlist_size;
int playlist_amount = playlist_get_current()->amount;
int segment_size = INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE; int segment_size = INSERT_ALL_PLAYLIST_MAX_SEGMENT_SIZE;
int segments_count = n / segment_size; int segments_count = n / segment_size;
int leftovers_segment_size = n % segment_size; int leftovers_segment_size = n - (segments_count * segment_size);
bool fill_randomly = false; bool fill_randomly = false;
if (playlist == NULL) {
bool will_exceed = n > playlist_get_current()->max_playlist_size; if (playlist == NULL)
{
bool will_exceed = n > max_playlist_size;
fill_randomly = will_exceed; fill_randomly = will_exceed;
} }
if (leftovers_segment_size > 0 && fill_randomly) if (leftovers_segment_size > 0 && fill_randomly)
{ {
/* We need to re-balance the segments so the randomness will be coherent and balanced the same through all segments */ /* We need to re-balance the segments so the randomness will be
* coherent and balanced the same through all segments */
while (leftovers_segment_size + segments_count < segment_size) while (leftovers_segment_size + segments_count < segment_size)
{ {
segment_size--; // -1 to all other segments segment_size--; // -1 to all other segments
@ -2227,40 +2237,58 @@ static bool insert_all_playlist(struct tree_context *c,
} }
if (leftovers_segment_size > 0) if (leftovers_segment_size > 0)
segments_count += 1; segments_count += 1;
int max_available_space = playlist_get_current()->max_playlist_size - playlist_get_current()->amount;
int max_available_space_per_segment = max_available_space / segments_count; int max_available_space = max_playlist_size - playlist_amount;
int max_space_per_segment = max_available_space / segments_count;
int remaining_space =
max_available_space - (max_space_per_segment * segments_count);
if (fill_randomly) if (fill_randomly)
{ {
talk_id(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY, true); talk_id(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY, true);
splashf(HZ * 3, str(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY), splashf(HZ * 3, str(LANG_RANDOM_SHUFFLE_RANDOM_SELECTIVE_SONGS_SUMMARY),
max_available_space_per_segment * segments_count); max_space_per_segment * segments_count + remaining_space);
/* logf("sz=%d lsz=%d sc=%d rcps=%d", segment_size, leftovers_segment_size, /* logf("sz=%d lsz=%d sc=%d rcps=%d", segment_size, leftovers_segment_size,
segments_count, max_available_space_per_segment); */ segments_count, max_available_space_per_segment); */
} }
bool exit_loop_now = false;
for (int i = 0; i < segments_count; i++) for (int i = 0; i < segments_count; i++)
{ {
bool is_leftovers_segment = leftovers_segment_size > 0 && i + 1 >= segments_count; int cur_segment_size = segment_size;
if (fill_randomly)
{
if (is_leftovers_segment)
fill_randomly = fill_selective_random_playlist_indexes(leftovers_segment_size, max_available_space_per_segment);
else
fill_randomly = fill_selective_random_playlist_indexes(segment_size, max_available_space_per_segment);
}
bool exit_loop_now = false;
int cur_segment_start = i * segment_size; int cur_segment_start = i * segment_size;
int cur_segment_end; int cur_segment_end;
if (is_leftovers_segment) int space_per_segment = max_space_per_segment;
cur_segment_end = cur_segment_start + leftovers_segment_size;
else if (i + 1 >= segments_count && leftovers_segment_size > 0)
cur_segment_end = cur_segment_start + segment_size; {
/* add any remaining tracks to the last segment */
space_per_segment += remaining_space;
cur_segment_size = leftovers_segment_size;
}
else if (fill_randomly)
{
/* add an extra track to some of the segments */
if (remaining_space > 0 && (i & 7) != 7)
{
space_per_segment++;
remaining_space--;
}
}
if (fill_randomly)
{
fill_randomly = fill_random_playlist_indexes(cur_segment_size,
space_per_segment);
}
cur_segment_end = cur_segment_start + cur_segment_size;
for (int j = cur_segment_start; j < cur_segment_end && !exit_loop_now; j++) for (int j = cur_segment_start; j < cur_segment_end && !exit_loop_now; j++)
{ {
if (fill_randomly && !selective_random_playlist_indexes[j % segment_size])
continue;
splash_progress(j, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
if (TIME_AFTER(current_tick, last_tick + HZ/4)) if (TIME_AFTER(current_tick, last_tick + HZ/4))
{ {
splash_progress(j, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
if (action_userabort(TIMEOUT_NOBLOCK)) if (action_userabort(TIMEOUT_NOBLOCK))
{ {
exit_loop_now = true; exit_loop_now = true;
@ -2268,8 +2296,13 @@ static bool insert_all_playlist(struct tree_context *c,
} }
last_tick = current_tick; last_tick = current_tick;
} }
if (fill_randomly && !selective_random_playlist_indexes[j % segment_size])
continue;
if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, j)->extraseek, tcs.type, buf, sizeof buf)) if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, j)->extraseek, tcs.type, buf, sizeof buf))
continue; continue;
if (playlist == NULL) if (playlist == NULL)
{ {
if (playlist_insert_track(NULL, buf, position, queue, false) < 0) { if (playlist_insert_track(NULL, buf, position, queue, false) < 0) {