#include #include #include #include #include "abuf.h" #include "rollc.h" enum { Argsmax = 8, Maxstack = 16384, }; Channel *rollchan; static int rfd; static double beat; static Biobuf bin; static char *actions[] = { "none", "play", "repeat", "stop", "quit", 0, }; static int lookup(char **keywords, char *s) { int k; for(k=0; keywords[k]; k++) if(strcmp(keywords[k], s) == 0) return k; return -1; } static void parse(Action *act, char *line) { char *argv[8]; int argc; Note *note, **np; argc = tokenize(line, argv, 8); if(argc < 4) return; if(atoi(argv[3]) == 0){ act->len = atof(argv[0]) * beat; return; } note = malloc(sizeof *note); note->t = atof(argv[0]) * beat; note->len = atof(argv[3]) * beat; note->vol = atoi(argv[2]); note->name = strdup(argv[1]); for(np=&act->notes; *np; np=&(*np)->next){ if((*np)->t >= note->t) break; } note->next = *np; *np = note; } void rollproc(void *) { char *line; Action a; int k; Binit(&bin, rfd, OREAD); do{ a.action = Aquit; a.notes = 0; a.len = 0; for(;;){ line = Brdstr(&bin, '\n', 1); if(line == 0) break; k = lookup(actions, line); if(k != -1){ a.action = k; break; } parse(&a, line); free(line); } send(rollchan, &a); }while(a.action != Aquit); Bterm(&bin); threadexits(0); } void rollstart(char *path, double bpm) { rollchan = chancreate(sizeof(Action), 16); if(path == 0) return; rfd = open(path, OREAD); if(rfd < 0) sysfatal("roll: %r"); beat = SRATE * 60 / bpm / pow(2, 14); proccreate(rollproc, 0, Maxstack); } void discardact(Action *a) { Note *note, *next; for(note=a->notes; note; note=next){ next = note->next; free(note->name); free(note); } } void dumpact(Action *a) { Note *note; fprint(2, "action=%s songlen=%d\n", actions[a->action], a->len); for(note=a->notes; note; note=note->next) fprint(2, "t=%d len=%d v=%d name=%s\n", note->t, note->len, note->vol, note->name); }