#include "acd.h" int debug; void usage(void) { fprint(2, "usage: acd dev\n"); threadexitsall("usage"); } Alt mkalt(Channel *c, void *v, int op) { Alt a; memset(&a, 0, sizeof(a)); a.c = c; a.v = v; a.op = op; return a; } void freetoc(Toc *t) { int i; free(t->title); for(i=0; intrack; i++) free(t->track[i].title); } void eventwatcher(Drive *d) { enum { STATUS, WEVENT, TOCDISP, DBREQ, DBREPLY, NALT }; Alt alts[NALT+1]; Toc nt, tdb; Event *e; Window *w; Cdstatus s; char buf[40]; w = d->w; alts[STATUS] = mkalt(d->cstatus, &s, CHANRCV); alts[WEVENT] = mkalt(w->cevent, &e, CHANRCV); alts[TOCDISP] = mkalt(d->ctocdisp, &nt, CHANRCV); alts[DBREQ] = mkalt(d->cdbreq, &tdb, CHANNOP); alts[DBREPLY] = mkalt(d->cdbreply, &nt, CHANRCV); alts[NALT] = mkalt(nil, nil, CHANEND); for(;;) { switch(alt(alts)) { case STATUS: //DPRINT(2, "s..."); d->status = s; if(s.state == Scompleted) { s.state = Sunknown; advancetrack(d, w); } //DPRINT(2, "status %d %d %d %M %M\n", s.state, s.track, s.index, s.abs, s.rel); sprint(buf, "%d:%2.2d", s.rel.m, s.rel.s); setplaytime(w, buf); break; case WEVENT: //DPRINT(2, "w..."); acmeevent(d, w, e); break; case TOCDISP: //DPRINT(2,"td..."); freetoc(&d->toc); d->toc = nt; drawtoc(w, d, &d->toc); tdb = nt; alts[DBREQ].op = CHANSND; break; case DBREQ: /* sent */ //DPRINT(2,"dreq..."); alts[DBREQ].op = CHANNOP; break; case DBREPLY: //DPRINT(2,"drep..."); freetoc(&d->toc); d->toc = nt; redrawtoc(w, &d->toc); break; } } } void threadmain(int argc, char **argv) { Scsi *s; Drive *d; char buf[80]; ARGBEGIN{ case 'v': debug++; scsiverbose++; }ARGEND if(argc != 1) usage(); fmtinstall('M', msfconv); if((s = openscsi(argv[0])) == nil) error("opening scsi: %r"); d = malloc(sizeof(*d)); if(d == nil) error("out of memory"); memset(d, 0, sizeof d); d->scsi = s; d->w = newwindow(); d->ctocdisp = chancreate(sizeof(Toc), 0); d->cdbreq = chancreate(sizeof(Toc), 0); d->cdbreply = chancreate(sizeof(Toc), 0); d->cstatus = chancreate(sizeof(Cdstatus), 0); proccreate(wineventproc, d->w, STACK); proccreate(cddbproc, d, STACK); proccreate(cdstatusproc, d, STACK); cleanname(argv[0]); snprint(buf, sizeof(buf), "%s/", argv[0]); winname(d->w, buf); wintagwrite(d->w, "Stop Pause Resume Eject Ingest ", 5+6+7+6+7); eventwatcher(d); }