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