xref: /plan9/acme/bin/source/acd/acme.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
19a747e4fSDavid du Colombier #include "acd.h"
29a747e4fSDavid du Colombier 
39a747e4fSDavid du Colombier static int
iscmd(char * s,char * cmd)49a747e4fSDavid du Colombier iscmd(char *s, char *cmd)
59a747e4fSDavid du Colombier {
69a747e4fSDavid du Colombier 	int len;
79a747e4fSDavid du Colombier 
89a747e4fSDavid du Colombier 	len = strlen(cmd);
99a747e4fSDavid du Colombier 	return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
109a747e4fSDavid du Colombier }
119a747e4fSDavid du Colombier 
129a747e4fSDavid du Colombier static char*
skip(char * s,char * cmd)139a747e4fSDavid du Colombier skip(char *s, char *cmd)
149a747e4fSDavid du Colombier {
159a747e4fSDavid du Colombier 	s += strlen(cmd);
169a747e4fSDavid du Colombier 	while(*s==' ' || *s=='\t' || *s=='\n')
179a747e4fSDavid du Colombier 		s++;
189a747e4fSDavid du Colombier 	return s;
199a747e4fSDavid du Colombier }
209a747e4fSDavid du Colombier 
219a747e4fSDavid du Colombier //#define PLAYSTRING "/^[0-9:]+>"
229a747e4fSDavid du Colombier //#define PLAYSTRINGSPACE "/^[0-9:]+> ?"
239a747e4fSDavid du Colombier //#define INITSTRING "0:00> "
249a747e4fSDavid du Colombier 
259a747e4fSDavid du Colombier #define INITSTRING "> "
269a747e4fSDavid du Colombier #define PLAYSTRING "/^>"
279a747e4fSDavid du Colombier #define PLAYSTRINGSPACE "/^> ?"
289a747e4fSDavid du Colombier 
299a747e4fSDavid du Colombier /*
309a747e4fSDavid du Colombier  * find the playing string, leave in addr
319a747e4fSDavid du Colombier  * if q0, q1 are non-nil, set them to the addr of the string.
329a747e4fSDavid du Colombier  */
339a747e4fSDavid du Colombier int
findplay(Window * w,char * s,ulong * q0,ulong * q1)349a747e4fSDavid du Colombier findplay(Window *w, char *s, ulong *q0, ulong *q1)
359a747e4fSDavid du Colombier {
369a747e4fSDavid du Colombier 	char xbuf[25];
379a747e4fSDavid du Colombier 	if(w->data < 0)
389a747e4fSDavid du Colombier 		w->data = winopenfile(w, "data");
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 	if(!winsetaddr(w, "#0", 1) || !winsetaddr(w, s, 1))
419a747e4fSDavid du Colombier 		return 0;
429a747e4fSDavid du Colombier 
439a747e4fSDavid du Colombier 	seek(w->addr, 0, 0);
449a747e4fSDavid du Colombier 	if(read(w->addr, xbuf, 24) != 24)
459a747e4fSDavid du Colombier 		return 0;
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier 	xbuf[24] = 0;
489a747e4fSDavid du Colombier 	if(q0)
499a747e4fSDavid du Colombier 		*q0 = atoi(xbuf);
509a747e4fSDavid du Colombier 	if(q1)
519a747e4fSDavid du Colombier 		*q1 = atoi(xbuf+12);
529a747e4fSDavid du Colombier 
539a747e4fSDavid du Colombier 	return 1;
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier 
569a747e4fSDavid du Colombier /*
579a747e4fSDavid du Colombier  * find the playing string and replace the time
589a747e4fSDavid du Colombier  */
599a747e4fSDavid du Colombier int
setplaytime(Window * w,char * new)609a747e4fSDavid du Colombier setplaytime(Window *w, char *new)
619a747e4fSDavid du Colombier {
629a747e4fSDavid du Colombier 	char buf[40];
639a747e4fSDavid du Colombier 	ulong q0, q1;
649a747e4fSDavid du Colombier 
659a747e4fSDavid du Colombier return 1;
669a747e4fSDavid du Colombier 	if(!findplay(w, PLAYSTRING, &q0, &q1))
679a747e4fSDavid du Colombier 		return 0;
689a747e4fSDavid du Colombier 
699a747e4fSDavid du Colombier 	q1--;	/* > */
709a747e4fSDavid du Colombier 	sprint(buf, "#%lud,#%lud", q0, q1);
719a747e4fSDavid du Colombier 	DPRINT(2, "setaddr %s\n", buf);
729a747e4fSDavid du Colombier 	if(!winsetaddr(w, buf, 1))
739a747e4fSDavid du Colombier 		return 0;
749a747e4fSDavid du Colombier 
759a747e4fSDavid du Colombier 	if(write(w->data, new, strlen(new)) != strlen(new))
769a747e4fSDavid du Colombier 		return 0;
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	return 1;
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier 
819a747e4fSDavid du Colombier /*
829a747e4fSDavid du Colombier  * find the playing string, and remove it.
839a747e4fSDavid du Colombier  * return the string at the beginning of hte next line in buf
849a747e4fSDavid du Colombier  * (presumably a track number).
859a747e4fSDavid du Colombier  */
869a747e4fSDavid du Colombier static int
unmarkplay(Window * w,char * buf,int n,ulong * q0,ulong * q1,ulong * qbegin)879a747e4fSDavid du Colombier unmarkplay(Window *w, char *buf, int n, ulong *q0, ulong *q1, ulong *qbegin)
889a747e4fSDavid du Colombier {
899a747e4fSDavid du Colombier 	char xbuf[24];
909a747e4fSDavid du Colombier 
919a747e4fSDavid du Colombier 	if(!findplay(w, PLAYSTRINGSPACE, q0, q1))
929a747e4fSDavid du Colombier 		return 0;
939a747e4fSDavid du Colombier 
949a747e4fSDavid du Colombier 	if(write(w->data, "", 0) < 0 || !winsetaddr(w, "+1+#0", 1))
959a747e4fSDavid du Colombier 		return 0;
969a747e4fSDavid du Colombier 
979a747e4fSDavid du Colombier 	if(qbegin) {
989a747e4fSDavid du Colombier 		seek(w->addr, 0, 0);
999a747e4fSDavid du Colombier 		if(read(w->addr, xbuf, 24) != 24)
1009a747e4fSDavid du Colombier 			return 0;
1019a747e4fSDavid du Colombier 		*qbegin = atoi(xbuf);
1029a747e4fSDavid du Colombier 	}
1039a747e4fSDavid du Colombier 
1049a747e4fSDavid du Colombier 	if(buf) {
1059a747e4fSDavid du Colombier 		if((n = read(w->data, buf, n-1)) < 0)
1069a747e4fSDavid du Colombier 			return 0;
1079a747e4fSDavid du Colombier 
1089a747e4fSDavid du Colombier 		buf[n] = '\0';
1099a747e4fSDavid du Colombier 	}
1109a747e4fSDavid du Colombier 
1119a747e4fSDavid du Colombier 	return 1;
1129a747e4fSDavid du Colombier }
1139a747e4fSDavid du Colombier 
1149a747e4fSDavid du Colombier int
markplay(Window * w,ulong q0)1159a747e4fSDavid du Colombier markplay(Window *w, ulong q0)
1169a747e4fSDavid du Colombier {
1179a747e4fSDavid du Colombier 	char buf[20];
1189a747e4fSDavid du Colombier 
1199a747e4fSDavid du Colombier 	if(w->data < 0)
1209a747e4fSDavid du Colombier 		w->data = winopenfile(w, "data");
1219a747e4fSDavid du Colombier 
1229a747e4fSDavid du Colombier 	sprint(buf, "#%lud", q0);
1239a747e4fSDavid du Colombier 	DPRINT(2, "addr %s\n", buf);
1249a747e4fSDavid du Colombier 	if(!winsetaddr(w, buf, 1) || !winsetaddr(w, "-0", 1))
1259a747e4fSDavid du Colombier 		return 0;
1269a747e4fSDavid du Colombier 	if(write(w->data, INITSTRING, strlen(INITSTRING)) != strlen(INITSTRING))
1279a747e4fSDavid du Colombier 		return 0;
1289a747e4fSDavid du Colombier 	return 1;
1299a747e4fSDavid du Colombier }
1309a747e4fSDavid du Colombier 
1319a747e4fSDavid du Colombier /* return 1 if handled, 0 otherwise */
1329a747e4fSDavid du Colombier int
cdcommand(Window * w,Drive * d,char * s)1339a747e4fSDavid du Colombier cdcommand(Window *w, Drive *d, char *s)
1349a747e4fSDavid du Colombier {
1359a747e4fSDavid du Colombier 	s = skip(s, "");
1369a747e4fSDavid du Colombier 
1379a747e4fSDavid du Colombier 	if(iscmd(s, "Del")){
1389a747e4fSDavid du Colombier 		if(windel(w, 0))
1399a747e4fSDavid du Colombier 			threadexitsall(nil);
1409a747e4fSDavid du Colombier 		return 1;
1419a747e4fSDavid du Colombier 	}
1429a747e4fSDavid du Colombier 	if(iscmd(s, "Stop")){
1439a747e4fSDavid du Colombier 		unmarkplay(w, nil, 0, nil, nil, nil);
1449a747e4fSDavid du Colombier 		stop(d);
1459a747e4fSDavid du Colombier 		return 1;
1469a747e4fSDavid du Colombier 	}
1479a747e4fSDavid du Colombier 	if(iscmd(s, "Eject")){
1489a747e4fSDavid du Colombier 		unmarkplay(w, nil, 0, nil, nil, nil);
1499a747e4fSDavid du Colombier 		eject(d);
1509a747e4fSDavid du Colombier 		return 1;
1519a747e4fSDavid du Colombier 	}
1529a747e4fSDavid du Colombier 	if(iscmd(s, "Ingest")){
1539a747e4fSDavid du Colombier 		unmarkplay(w, nil, 0, nil, nil, nil);
1549a747e4fSDavid du Colombier 		ingest(d);
1559a747e4fSDavid du Colombier 		return 1;
1569a747e4fSDavid du Colombier 	}
1579a747e4fSDavid du Colombier 	if(iscmd(s, "Pause")){
1589a747e4fSDavid du Colombier 		pause(d);
1599a747e4fSDavid du Colombier 		return 1;
1609a747e4fSDavid du Colombier 	}
1619a747e4fSDavid du Colombier 	if(iscmd(s, "Resume")){
1629a747e4fSDavid du Colombier 		resume(d);
1639a747e4fSDavid du Colombier 		return 1;
1649a747e4fSDavid du Colombier 	}
1659a747e4fSDavid du Colombier 	return 0;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier 
1689a747e4fSDavid du Colombier void
drawtoc(Window * w,Drive * d,Toc * t)1699a747e4fSDavid du Colombier drawtoc(Window *w, Drive *d, Toc *t)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier 	int i, playing;
1729a747e4fSDavid du Colombier 
1739a747e4fSDavid du Colombier 	if(w->data < 0)
1749a747e4fSDavid du Colombier 		w->data = winopenfile(w, "data");
1759a747e4fSDavid du Colombier 	if(!winsetaddr(w, ",", 1))
1769a747e4fSDavid du Colombier 		return;
1779a747e4fSDavid du Colombier 
178*3ff48bf5SDavid du Colombier 	fprint(w->data, "Title\n\n");
1799a747e4fSDavid du Colombier 	playing = -1;
1809a747e4fSDavid du Colombier 	if(d->status.state == Splaying || d->status.state == Spaused)
1819a747e4fSDavid du Colombier 		playing = d->status.track-t->track0;
1829a747e4fSDavid du Colombier 
1839a747e4fSDavid du Colombier 	for(i=0; i<t->ntrack; i++)
184*3ff48bf5SDavid du Colombier 		fprint(w->data, "%s%d/ Track %d\n", i==playing ? "> " : "", i+1, i+1);
185*3ff48bf5SDavid du Colombier 	fprint(w->data, "");
1869a747e4fSDavid du Colombier }
1879a747e4fSDavid du Colombier 
1889a747e4fSDavid du Colombier void
redrawtoc(Window * w,Toc * t)1899a747e4fSDavid du Colombier redrawtoc(Window *w, Toc *t)
1909a747e4fSDavid du Colombier {
1919a747e4fSDavid du Colombier 	int i;
1929a747e4fSDavid du Colombier 	char old[50];
1939a747e4fSDavid du Colombier 
1949a747e4fSDavid du Colombier 	if(w->data < 0)
1959a747e4fSDavid du Colombier 		w->data = winopenfile(w, "data");
1969a747e4fSDavid du Colombier 	if(t->title) {
1979a747e4fSDavid du Colombier 		if(winsetaddr(w, "/Title", 1))
1989a747e4fSDavid du Colombier 			write(w->data, t->title, strlen(t->title));
1999a747e4fSDavid du Colombier 	}
2009a747e4fSDavid du Colombier 	for(i=0; i<t->ntrack; i++) {
2019a747e4fSDavid du Colombier 		if(t->track[i].title) {
2029a747e4fSDavid du Colombier 			sprint(old, "/Track %d", i+1);
2039a747e4fSDavid du Colombier 			if(winsetaddr(w, old, 1))
2049a747e4fSDavid du Colombier 				write(w->data, t->track[i].title, strlen(t->track[i].title));
2059a747e4fSDavid du Colombier 		}
2069a747e4fSDavid du Colombier 	}
2079a747e4fSDavid du Colombier }
2089a747e4fSDavid du Colombier 
2099a747e4fSDavid du Colombier void
advancetrack(Drive * d,Window * w)2109a747e4fSDavid du Colombier advancetrack(Drive *d, Window *w)
2119a747e4fSDavid du Colombier {
2129a747e4fSDavid du Colombier 	int n;
2139a747e4fSDavid du Colombier 	ulong q0, q1, qnext;
2149a747e4fSDavid du Colombier 	char buf[20];
2159a747e4fSDavid du Colombier 
2169a747e4fSDavid du Colombier 	q0 = q1 = 0;
2179a747e4fSDavid du Colombier 	if(!unmarkplay(w, buf, sizeof(buf), &q0, &q1, &qnext)) {
2189a747e4fSDavid du Colombier 		DPRINT(2, "unmark: %r\n");
2199a747e4fSDavid du Colombier 		return;
2209a747e4fSDavid du Colombier 	}
2219a747e4fSDavid du Colombier 
2229a747e4fSDavid du Colombier 	DPRINT(2, "buf: %s\n", buf);
2239a747e4fSDavid du Colombier 	if(strncmp(buf, "repeat", 6) == 0) {
2249a747e4fSDavid du Colombier 		if(!winsetaddr(w, "#0", 1) || !findplay(w, "/^[0-9]+\\/", &qnext, nil)) {
2259a747e4fSDavid du Colombier 			DPRINT(2, "set/find: %r\n");
2269a747e4fSDavid du Colombier 			return;
2279a747e4fSDavid du Colombier 		}
2289a747e4fSDavid du Colombier 		if(w->data < 0)
2299a747e4fSDavid du Colombier 			w->data = winopenfile(w, "data");
2309a747e4fSDavid du Colombier 		if((n = read(w->data, buf, sizeof(buf)-1)) <= 0) {
2319a747e4fSDavid du Colombier 			DPRINT(2, "read %d: %r\n", n);
2329a747e4fSDavid du Colombier 			return;
2339a747e4fSDavid du Colombier 		}
2349a747e4fSDavid du Colombier 		buf[n] = 0;
2359a747e4fSDavid du Colombier 		DPRINT(2, "buf: %s\n", buf);
2369a747e4fSDavid du Colombier 	}
2379a747e4fSDavid du Colombier 
2389a747e4fSDavid du Colombier 	if((n = atoi(buf)) == 0)
2399a747e4fSDavid du Colombier 		return;
2409a747e4fSDavid du Colombier 
2419a747e4fSDavid du Colombier 	if(!markplay(w, qnext))
2429a747e4fSDavid du Colombier 		DPRINT(2, "err: %r");
2439a747e4fSDavid du Colombier 
2449a747e4fSDavid du Colombier 	playtrack(d, n-1, n-1);
2459a747e4fSDavid du Colombier }
2469a747e4fSDavid du Colombier 
2479a747e4fSDavid du Colombier void
acmeevent(Drive * d,Window * w,Event * e)2489a747e4fSDavid du Colombier acmeevent(Drive *d, Window *w, Event *e)
2499a747e4fSDavid du Colombier {
2509a747e4fSDavid du Colombier 	Event *ea, *e2, *eq;
2519a747e4fSDavid du Colombier 	char *s, *t, *buf;
2529a747e4fSDavid du Colombier 	int n, na;
2539a747e4fSDavid du Colombier 	ulong q0, q1;
2549a747e4fSDavid du Colombier 
2559a747e4fSDavid du Colombier 	switch(e->c1){	/* origin of action */
2569a747e4fSDavid du Colombier 	default:
2579a747e4fSDavid du Colombier 	Unknown:
258*3ff48bf5SDavid du Colombier 		fprint(2, "unknown message %c%c\n", e->c1, e->c2);
2599a747e4fSDavid du Colombier 		break;
2609a747e4fSDavid du Colombier 
2619a747e4fSDavid du Colombier 	case 'E':	/* write to body or tag; can't affect us */
2629a747e4fSDavid du Colombier 		break;
2639a747e4fSDavid du Colombier 
2649a747e4fSDavid du Colombier 	case 'F':	/* generated by our actions; ignore */
2659a747e4fSDavid du Colombier 		break;
2669a747e4fSDavid du Colombier 
2679a747e4fSDavid du Colombier 	case 'K':	/* type away; we don't care */
2689a747e4fSDavid du Colombier 		break;
2699a747e4fSDavid du Colombier 
2709a747e4fSDavid du Colombier 	case 'M':	/* mouse event */
2719a747e4fSDavid du Colombier 		switch(e->c2){		/* type of action */
2729a747e4fSDavid du Colombier 		case 'x':	/* mouse: button 2 in tag */
2739a747e4fSDavid du Colombier 		case 'X':	/* mouse: button 2 in body */
2749a747e4fSDavid du Colombier 			ea = nil;
2759a747e4fSDavid du Colombier 		//	e2 = nil;
2769a747e4fSDavid du Colombier 			s = e->b;
2779a747e4fSDavid du Colombier 			if(e->flag & 2){	/* null string with non-null expansion */
2789a747e4fSDavid du Colombier 				e2 = recvp(w->cevent);
2799a747e4fSDavid du Colombier 				if(e->nb==0)
2809a747e4fSDavid du Colombier 					s = e2->b;
2819a747e4fSDavid du Colombier 			}
2829a747e4fSDavid du Colombier 			if(e->flag & 8){	/* chorded argument */
2839a747e4fSDavid du Colombier 				ea = recvp(w->cevent);	/* argument */
2849a747e4fSDavid du Colombier 				na = ea->nb;
2859a747e4fSDavid du Colombier 				recvp(w->cevent);		/* ignore origin */
2869a747e4fSDavid du Colombier 			}else
2879a747e4fSDavid du Colombier 				na = 0;
2889a747e4fSDavid du Colombier 
2899a747e4fSDavid du Colombier 			/* append chorded arguments */
2909a747e4fSDavid du Colombier 			if(na){
2919a747e4fSDavid du Colombier 				t = emalloc(strlen(s)+1+na+1);
2929a747e4fSDavid du Colombier 				sprint(t, "%s %s", s, ea->b);
2939a747e4fSDavid du Colombier 				s = t;
2949a747e4fSDavid du Colombier 			}
2959a747e4fSDavid du Colombier 			/* if it's a known command, do it */
2969a747e4fSDavid du Colombier 			/* if it's a long message, it can't be for us anyway */
2979a747e4fSDavid du Colombier 			DPRINT(2, "exec: %s\n", s);
2989a747e4fSDavid du Colombier 			if(!cdcommand(w, d, s))	/* send it back */
2999a747e4fSDavid du Colombier 				winwriteevent(w, e);
3009a747e4fSDavid du Colombier 			if(na)
3019a747e4fSDavid du Colombier 				free(s);
3029a747e4fSDavid du Colombier 			break;
3039a747e4fSDavid du Colombier 
3049a747e4fSDavid du Colombier 		case 'l':	/* mouse: button 3 in tag */
3059a747e4fSDavid du Colombier 		case 'L':	/* mouse: button 3 in body */
3069a747e4fSDavid du Colombier 		//	buf = nil;
3079a747e4fSDavid du Colombier 			eq = e;
3089a747e4fSDavid du Colombier 			if(e->flag & 2){
3099a747e4fSDavid du Colombier 				e2 = recvp(w->cevent);
3109a747e4fSDavid du Colombier 				eq = e2;
3119a747e4fSDavid du Colombier 			}
3129a747e4fSDavid du Colombier 			s = eq->b;
3139a747e4fSDavid du Colombier 			if(eq->q1>eq->q0 && eq->nb==0){
3149a747e4fSDavid du Colombier 				buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
3159a747e4fSDavid du Colombier 				winread(w, eq->q0, eq->q1, buf);
3169a747e4fSDavid du Colombier 				s = buf;
3179a747e4fSDavid du Colombier 			}
3189a747e4fSDavid du Colombier 			DPRINT(2, "load %s\n", s);
3199a747e4fSDavid du Colombier 			if((n = atoi(s)) != 0) {
3209a747e4fSDavid du Colombier 				DPRINT(2, "mark %d\n", n);
3219a747e4fSDavid du Colombier 				q0 = q1 = 0;
3229a747e4fSDavid du Colombier 				unmarkplay(w, nil, 0, &q0, &q1, nil);
3239a747e4fSDavid du Colombier 
3249a747e4fSDavid du Colombier 				/* adjust eq->q* for deletion */
3259a747e4fSDavid du Colombier 				if(eq->q0 > q1) {
3269a747e4fSDavid du Colombier 					eq->q0 -= (q1-q0);
3279a747e4fSDavid du Colombier 					eq->q1 -= (q1-q0);
3289a747e4fSDavid du Colombier 				}
3299a747e4fSDavid du Colombier 				if(!markplay(w, eq->q0))
3309a747e4fSDavid du Colombier 					DPRINT(2, "err: %r\n");
3319a747e4fSDavid du Colombier 
3329a747e4fSDavid du Colombier 				playtrack(d, n-1, n-1);
3339a747e4fSDavid du Colombier 			} else
3349a747e4fSDavid du Colombier 				winwriteevent(w, e);
3359a747e4fSDavid du Colombier 			break;
3369a747e4fSDavid du Colombier 
3379a747e4fSDavid du Colombier 		case 'i':	/* mouse: text inserted in tag */
3389a747e4fSDavid du Colombier 		case 'I':	/* mouse: text inserted in body */
3399a747e4fSDavid du Colombier 		case 'd':	/* mouse: text deleted from tag */
3409a747e4fSDavid du Colombier 		case 'D':	/* mouse: text deleted from body */
3419a747e4fSDavid du Colombier 			break;
3429a747e4fSDavid du Colombier 
3439a747e4fSDavid du Colombier 		default:
3449a747e4fSDavid du Colombier 			goto Unknown;
3459a747e4fSDavid du Colombier 		}
3469a747e4fSDavid du Colombier 	}
3479a747e4fSDavid du Colombier }
348