xref: /plan9/acme/bin/source/acd/main.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
1 #include "acd.h"
2 
3 int debug;
4 
5 void
usage(void)6 usage(void)
7 {
8 	fprint(2, "usage: acd dev\n");
9 	threadexitsall("usage");
10 }
11 
12 Alt
mkalt(Channel * c,void * v,int op)13 mkalt(Channel *c, void *v, int op)
14 {
15 	Alt a;
16 
17 	memset(&a, 0, sizeof(a));
18 	a.c = c;
19 	a.v = v;
20 	a.op = op;
21 	return a;
22 }
23 
24 void
freetoc(Toc * t)25 freetoc(Toc *t)
26 {
27 	int i;
28 
29 	free(t->title);
30 	for(i=0; i<t->ntrack; i++)
31 		free(t->track[i].title);
32 }
33 
34 void
eventwatcher(Drive * d)35 eventwatcher(Drive *d)
36 {
37 	enum { STATUS, WEVENT, TOCDISP, DBREQ, DBREPLY, NALT };
38 	Alt alts[NALT+1];
39 	Toc nt, tdb;
40 	Event *e;
41 	Window *w;
42 	Cdstatus s;
43 	char buf[40];
44 
45 	w = d->w;
46 
47 	alts[STATUS] = mkalt(d->cstatus, &s, CHANRCV);
48 	alts[WEVENT] = mkalt(w->cevent, &e, CHANRCV);
49 	alts[TOCDISP] = mkalt(d->ctocdisp, &nt, CHANRCV);
50 	alts[DBREQ] = mkalt(d->cdbreq, &tdb, CHANNOP);
51 	alts[DBREPLY] = mkalt(d->cdbreply, &nt, CHANRCV);
52 	alts[NALT] = mkalt(nil, nil, CHANEND);
53 	for(;;) {
54 		switch(alt(alts)) {
55 		case STATUS:
56 			//DPRINT(2, "s...");
57 			d->status = s;
58 			if(s.state == Scompleted) {
59 				s.state = Sunknown;
60 				advancetrack(d, w);
61 			}
62 			//DPRINT(2, "status %d %d %d %M %M\n", s.state, s.track, s.index, s.abs, s.rel);
63 			sprint(buf, "%d:%2.2d", s.rel.m, s.rel.s);
64 			setplaytime(w, buf);
65 			break;
66 		case WEVENT:
67 			//DPRINT(2, "w...");
68 			acmeevent(d, w, e);
69 			break;
70 		case TOCDISP:
71 			//DPRINT(2,"td...");
72 			freetoc(&d->toc);
73 			d->toc = nt;
74 			drawtoc(w, d, &d->toc);
75 			tdb = nt;
76 			alts[DBREQ].op = CHANSND;
77 			break;
78 		case DBREQ:	/* sent */
79 			//DPRINT(2,"dreq...");
80 			alts[DBREQ].op = CHANNOP;
81 			break;
82 		case DBREPLY:
83 			//DPRINT(2,"drep...");
84 			freetoc(&d->toc);
85 			d->toc = nt;
86 			redrawtoc(w, &d->toc);
87 			break;
88 		}
89 	}
90 }
91 
92 void
threadmain(int argc,char ** argv)93 threadmain(int argc, char **argv)
94 {
95 	Scsi *s;
96 	Drive *d;
97 	char buf[80];
98 
99 	ARGBEGIN{
100 	case 'v':
101 		debug++;
102 		scsiverbose++;
103 	}ARGEND
104 
105 	if(argc != 1)
106 		usage();
107 
108 	fmtinstall('M', msfconv);
109 
110 	if((s = openscsi(argv[0])) == nil)
111 		error("opening scsi: %r");
112 
113 	d = malloc(sizeof(*d));
114 	if(d == nil)
115 		error("out of memory");
116 	memset(d, 0, sizeof d);
117 
118 	d->scsi = s;
119 	d->w = newwindow();
120 	d->ctocdisp = chancreate(sizeof(Toc), 0);
121 	d->cdbreq = chancreate(sizeof(Toc), 0);
122 	d->cdbreply = chancreate(sizeof(Toc), 0);
123 	d->cstatus = chancreate(sizeof(Cdstatus), 0);
124 
125 	proccreate(wineventproc, d->w, STACK);
126 	proccreate(cddbproc, d, STACK);
127 	proccreate(cdstatusproc, d, STACK);
128 
129 	cleanname(argv[0]);
130 	snprint(buf, sizeof(buf), "%s/", argv[0]);
131 	winname(d->w, buf);
132 
133 	wintagwrite(d->w, "Stop Pause Resume Eject Ingest ", 5+6+7+6+7);
134 	eventwatcher(d);
135 }
136