shithub: zuke

Download patch

ref: 49832e136f3bc962000ef14f1c8f1559fb699186
parent: 482f0ce1f33e655ab3085c3c9c2f5d71cd5b1c79
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Fri May 29 09:54:32 EDT 2020

minimize shuffle logic, store all shuffle indices instead of generating by one on the fly, fix searching in shuffled mode

--- a/shuffle.c
+++ /dev/null
@@ -1,92 +1,0 @@
-#include "shuffle.h"
-
-void
-shuffle_init(Shuffle *s, int (*rndrange)(int max_excluding), int total, int first)
-{
-	assert(first < total && total > 0);
-	s->m = s->n = total;
-	s->i = 0;
-	s->xi = s->x0 = first;
-
-	if(total < 4){
-		s->a = 1;
-		s->c = 3;
-		s->m = 7;
-		return;
-	}
-
-	s->m += 1;
-	s->m |= s->m >> 1;
-	s->m |= s->m >> 2;
-	s->m |= s->m >> 4;
-	s->m |= s->m >> 8;
-	s->m |= s->m >> 16;
-
-	s->a = 1 + rndrange(s->m/4)*4;     /* 1 ≤ a < m   && a mod 4 = 1 */
-	s->c = 3 + rndrange((s->m-2)/2)*2; /* 3 ≤ c < m-1 && c mod 2 = 1 */
-}
-
-void
-shuffle_resize(Shuffle *s, int total)
-{
-	assert(total > 0);
-	s->n = total;
-}
-
-static int
-next(Shuffle *s)
-{
-	int res;
-
-	res = s->xi;
-	if(s->n < 2){
-		/* if it's less than two items, just use the first one (if any) */
-		s->x0 = s->xi = s->i = 0;
-		return 0;
-	}else if(s->x0 >= s->n){
-		/* if items were removed up to this one -- update for a period */
-		s->x0 = 0;
-	}
-
-	for(;;){
-		s->xi = (s->a*s->xi + s->c) & s->m;
-		if(s->xi < s->n){
-			s->i++;
-			if(s->xi == s->x0)
-				s->i = 0;
-			break;
-		}
-	}
-
-	return res;
-}
-
-int
-shuffle_one(Shuffle *s, int index)
-{
-	if(s->n < 1 || index < 0)
-		return index;
-	index %= s->n;
-	while(s->i < s->n && s->i != index)
-		next(s);
-
-	return next(s);
-}
-
-int
-shuffle_for(Shuffle *s, int index)
-{
-	int i, r;
-
-	if(index < 0 || index >= s->n)
-		return index;
-	for(i = 0; i < s->n; i++){
-		r = s->i;
-		if(next(s) == index){
-			next(s);
-			return r;
-		}
-	}
-
-	return index;
-}
--- a/shuffle.h
+++ /dev/null
@@ -1,11 +1,0 @@
-typedef struct Shuffle Shuffle;
-
-struct Shuffle {
-	int i, n;
-	int m, a, c, x0, xi;
-};
-
-void shuffle_init(Shuffle *s, int (*rndrange)(int max_excluding), int total, int first);
-void shuffle_resize(Shuffle *s, int total);
-int shuffle_one(Shuffle *s, int index);
-int shuffle_for(Shuffle *s, int index);
--- a/zuke.c
+++ b/zuke.c
@@ -1,5 +1,4 @@
 #include "theme.c"
-#include "shuffle.c"
 #include <mouse.h>
 #include <keyboard.h>
 #include <ctype.h>
@@ -30,12 +29,6 @@
 	Relbufsz = Bps/5, /* 0.2 second */
 };
 
-static Meta *pl;
-static int plnum;
-static char *plraw;
-static int plrawsize;
-static int volume;
-
 struct Player
 {
 	Channel *ctl;
@@ -46,6 +39,13 @@
 
 int mainstacksize = 32768;
 
+static Meta *pl;
+static int plnum;
+static char *plraw;
+static int plrawsize;
+static int volume;
+static Player *playernext;
+static Player *playercurr;
 static int audio;
 static u64int byteswritten;
 static int pcur, pcurplaying;
@@ -58,8 +58,7 @@
 static int entering;
 static int colwidth[3];
 static int mincolwidth[3];
-static Shuffle shuffle;
-static int shuffled;
+static int *shuffle;
 static char *covers[] = {"folder", "cover", "Cover", "scans/CD", "Scans/Front", "Covers/Front"};
 
 static char *menu3i[] = {
@@ -117,7 +116,7 @@
 static Meta *
 getmeta(int i)
 {
-	return &pl[shuffled ? shuffle_one(&shuffle, i) : i];
+	return &pl[shuffle != nil ? shuffle[i] : i];
 }
 
 static void
@@ -223,9 +222,9 @@
 	}
 
 	if(pcurplaying >= 0)
-		snprint(tmp, sizeof(tmp), "%s%P/%P %d%%", shuffled ? "∫ " : "", (int)(byteswritten/Bps), getmeta(pcurplaying)->duration/1000, volume);
+		snprint(tmp, sizeof(tmp), "%s%P/%P %d%%", shuffle != nil ? "∫ " : "", (int)(byteswritten/Bps), getmeta(pcurplaying)->duration/1000, volume);
 	else
-		snprint(tmp, sizeof(tmp), "%s%d%%", shuffled ? "∫ " : "", volume);
+		snprint(tmp, sizeof(tmp), "%s%d%%", shuffle != nil ? "∫ " : "", volume);
 	r = screen->r;
 	r.min.x = r.max.x - stringwidth(f, tmp) - 4;
 	r.min.y = r.max.y - f->height - 4;
@@ -331,9 +330,6 @@
 	threadexits(nil);
 }
 
-static Player *playernext;
-static Player *playercurr;
-
 static int
 playerret(Player *player)
 {
@@ -678,10 +674,10 @@
 static void
 search(char d)
 {
-	char *s, *snext;
-	static char buf[48];
+	Meta *m;
+	static char buf[64];
 	static int sz;
-	int inc, i;
+	int inc, i, a;
 
 	inc = (d == '/' || d == 'n') ? 1 : -1;
 	if(d == '/' || d == '?'){
@@ -689,31 +685,26 @@
 		sz = enter(inc > 0 ? "forward:" : "backward:", buf, sizeof(buf), mctl, kctl, nil);
 		entering = 0;
 	}
-	i = getmeta(pcur) - pl;
-	if(sz < 1 || (inc > 0 && i >= plnum-1) || (inc < 0 && i < 1))
+	if(sz < 1)
 		return;
 
-	s = pl[i + (inc > 0 ? 0 : -1)].path;
-	s += strlen(s) + 1;
-	for(; s > plraw && s < plraw+plrawsize-sz; s += inc){
-		if(cistrncmp(s, buf, sz) != 0)
-			continue;
-		snext = s;
-		for(; s != plraw && *s; s--);
-		if(s == plraw || (s[1] != Partist && s[1] != Palbum && s[1] != Ptitle && s[1] != Pdate)){
-			if(inc > 0)
-				s = snext;
-			continue;
+	for(i = pcur+inc; i >= 0 && i < plnum; i += inc){
+		m = getmeta(i);
+		for(a = 0; a < m->numartist; a++){
+			if(cistrstr(m->artist[a], buf) != nil)
+				break;
 		}
-		for(s--; s != plraw; s--){
-			if(memcmp(s, "\0# ", 3) == 0 && isdigit(s[3])){
-				pcur = shuffled ? shuffle_for(&shuffle, atoi(s+3)) : atoi(s+3);
-				redraw(1);
-				return;
-			}
-		}
-		break;
+		if(m->album != nil && cistrstr(m->album, buf) != nil)
+			break;
+		if(m->title != nil && cistrstr(m->title, buf) != nil)
+			break;
+		if(cistrstr(m->path, buf) != nil)
+			break;
 	}
+	if(i >= 0 && i < plnum){
+		pcur = i;
+		redraw(1);
+	}
 }
 
 static void
@@ -766,14 +757,50 @@
 static void
 toggleshuffle(void)
 {
-	shuffled = !shuffled;
-	if(shuffled){
-		shuffle_init(&shuffle, nrand, plnum, pcurplaying < 0 ? pcur : pcurplaying);
-		pcur = shuffle_for(&shuffle, pcur);
-		pcurplaying = shuffle_for(&shuffle, pcurplaying);
+	int i, m, xi, a, c, pcurnew, pcurplayingnew;
+
+	if(shuffle == nil){
+		if(plnum < 2)
+			return;
+
+		m = plnum;
+		if(plnum < 4){
+			a = 1;
+			c = 3;
+			m = 7;
+		}else{
+			m += 1;
+			m |= m >> 1;
+			m |= m >> 2;
+			m |= m >> 4;
+			m |= m >> 8;
+			m |= m >> 16;
+			a = 1 + nrand(m/4)*4;     /* 1 ≤ a < m   && a mod 4 = 1 */
+			c = 3 + nrand((m-2)/2)*2; /* 3 ≤ c < m-1 && c mod 2 = 1 */
+		}
+
+		shuffle = malloc(plnum*sizeof(*shuffle));
+		xi = pcurplaying < 0 ? pcur : pcurplaying;
+		pcurplayingnew = -1;
+		pcurnew = 0;
+		for(i = 0; i < plnum;){
+			if(xi < plnum){
+				if(pcur == xi)
+					pcurnew = i;
+				if(pcurplaying == xi)
+					pcurplayingnew = i;
+				shuffle[i++] = xi;
+			}
+			xi = (a*xi + c) & m;
+		}
+		pcur = pcurnew;
+		pcurplaying = pcurplayingnew;
 	}else{
-		pcur = shuffle_one(&shuffle, pcur);
-		pcurplaying = shuffle_one(&shuffle, pcurplaying);
+		pcur = shuffle[pcur];
+		if(pcurplaying >= 0)
+			pcurplaying = shuffle[pcurplaying];
+		free(shuffle);
+		shuffle = nil;
 	}
 }