Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#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; i<t->ntrack; 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);
}