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