63131ebe8a
instead of an incorrectly implemented Knuth shuffle. Also on openbsd make sure we use arc4random_uniform for the random choice from the sequence to make sure we aren't modulo biased. Noticed when my mpd server played an unnatural amount of Rush out of the 80's playlist.
81 lines
2.0 KiB
Plaintext
81 lines
2.0 KiB
Plaintext
--- src/playlist.c.orig Fri Jun 13 22:16:16 2008
|
|
+++ src/playlist.c Mon Apr 6 08:57:25 2009
|
|
@@ -77,6 +77,13 @@
|
|
static int playPlaylistOrderNumber(int fd, int orderNum);
|
|
static void randomizeOrder(int start, int end);
|
|
|
|
+#ifdef __OpenBSD__
|
|
+#define RANDOM_UB(n) (arc4random_uniform(n))
|
|
+#else
|
|
+#define RANDOM_UB(n) (random() % (n))
|
|
+#endif
|
|
+
|
|
+
|
|
static void incrPlaylistVersion(void)
|
|
{
|
|
static unsigned long max = ((mpd_uint32) 1 << 31) - 1;
|
|
@@ -647,7 +654,7 @@
|
|
else
|
|
start = playlist.current + 1;
|
|
if (start < playlist.length) {
|
|
- swap = random() % (playlist.length - start);
|
|
+ swap = RANDOM_UB(playlist.length - start);
|
|
swap += start;
|
|
swapOrder(playlist.length - 1, swap);
|
|
}
|
|
@@ -1189,15 +1196,23 @@
|
|
}
|
|
}
|
|
|
|
- for (i = start; i <= end; i++) {
|
|
- ri = random() % (end - start + 1) + start;
|
|
- if (ri == playlist.current)
|
|
- playlist.current = i;
|
|
- else if (i == playlist.current)
|
|
- playlist.current = ri;
|
|
- swapOrder(i, ri);
|
|
+ /*
|
|
+ * Shuffle the Order.
|
|
+ * Use an unbiased Fisher-Yates shuffle.
|
|
+ */
|
|
+ i = end + 1;
|
|
+ while (i > start + 1) {
|
|
+ ri = RANDOM_UB(i - start); /* 0 <= ri <= len */
|
|
+ ri += start;
|
|
+ i--; /* i is now the last pertinent index */
|
|
+ if (i != ri) { /* do nothing if i == ri */
|
|
+ if (ri == playlist.current)
|
|
+ playlist.current = i;
|
|
+ else if (i == playlist.current)
|
|
+ playlist.current = ri;
|
|
+ swapOrder(i, ri);
|
|
+ }
|
|
}
|
|
-
|
|
}
|
|
|
|
int setPlaylistRandomStatus(int fd, int status)
|
|
@@ -1281,12 +1296,17 @@
|
|
i = 0;
|
|
playlist.current = -1;
|
|
}
|
|
- /* shuffle the rest of the list */
|
|
- for (; i < playlist.length; i++) {
|
|
- ri = random() % (playlist.length - 1) + 1;
|
|
- swapSongs(i, ri);
|
|
+ /*
|
|
+ * shuffle the rest of the list
|
|
+ * Use an unbiased Fisher-Yates shuffle.
|
|
+ */
|
|
+ i = playlist.length;
|
|
+ while (i > 1) {
|
|
+ ri = RANDOM_UB(i); /* 0 <= ri <= len */
|
|
+ i--; /* i is now the last pertinent index */
|
|
+ if (i != ri) /* do nothing if i == ri */
|
|
+ swapSongs(i, ri);
|
|
}
|
|
-
|
|
incrPlaylistVersion();
|
|
}
|
|
|