openbsd-ports/audio/mpd/patches/patch-src_playlist_c
beck 63131ebe8a make mpd use a reaonable Fisher-Yates shuffle for randomizing play order
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.
2009-04-10 00:52:07 +00:00

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();
}