📄 audiofs.c
字号:
p = seprint(p, e, " %ld", c->step); } p = seprint(p, e, "\n"); } } assert(strlen(a->s) < 1024); a->ns = p - a->s; return a->ns;}voidreadproc(void *x){ Fcall *rhdr; Audioctldata *a; Fid *f; uchar *mdata; int n, cnt; long off; Worker *w; ulong event; w = x; mdata = emalloc(8*1024+IOHDRSZ); while(event = recvul(w->eventc)){ if (event != Work) continue; f = w->fid; rhdr = w->rhdr; a = f->fiddata; off = rhdr->offset; cnt = rhdr->count; assert(a->offoff == off); /* f is already locked */ for(;;){ qunlock(f); event = recvul(w->eventc); qlock(f); if (debug & Dbgproc) fprint(2, "readproc unblocked fid %d %lld\n", f->fid, f->dir->qid.path); switch (event & 0xffff) { case Work: sysfatal("readproc phase error"); case Check: if (f->fiddata && makeaudioctldata(f) == 0) continue; break; case Flush: if ((event >> 16) == rhdr->tag) { if (debug & Dbgproc) fprint(2, "readproc flushing fid %d, tag %d\n", f->fid, rhdr->tag); goto flush; } continue; } if (f->fiddata){ rhdr->data = a->s; rhdr->count = a->ns; break; } yield(); } if (rhdr->count > cnt) rhdr->count = cnt; if (rhdr->count) f->flags &= ~Eof; if(debug & (Dbgproc|Dbgfs)) fprint(2, "readproc:->%F\n", rhdr); n = convS2M(rhdr, mdata, messagesize); if(write(mfd[1], mdata, n) != n) sysfatal("mount write");flush: w->tag = NOTAG; f->readers--; assert(f->readers == 0); free(rhdr); w->rhdr = nil; qunlock(f); sendp(procchan, w); } threadexits(nil);}char*rread(Fid *f){ long off; int i, n, cnt, rec; char *p; static char buf[1024]; Audiocontrol *c; Audioctldata *a; Worker *w; rhdr.count = 0; off = thdr.offset; cnt = thdr.count; if(cnt > messagesize - IOHDRSZ) cnt = messagesize - IOHDRSZ; rhdr.data = (char*)mbuf; if(f->dir == &dirs[Qdir]){ n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ); rhdr.count = n; return nil; } if(f->dir == &dirs[Qvolume]){ p = buf; n = sizeof buf; for (rec = 0; rec < 2; rec++){ c = &controls[rec][Volume_control]; if (c->readable){ i = snprint(p, n, "audio %s %ld\n", rec?"in":"out", (c->min != Undef) ? 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]); p+=i; n-=i; } c = &controls[rec][Treble_control]; if (c->readable){ i = snprint(p, n, "treb %s %ld\n", rec?"in":"out", (c->min != Undef) ? 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]); p+=i; n-=i; } c = &controls[rec][Bass_control]; if (c->readable){ i = snprint(p, n, "bass %s %ld\n", rec?"in":"out", (c->min != Undef) ? 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]); p+=i; n-=i; } c = &controls[rec][Speed_control]; if (c->readable){ i = snprint(p, n, "speed %s %ld\n", rec?"in":"out", c->value[0]); p+=i; n-=i; } } n = sizeof buf - n; if (off > n) rhdr.count = 0; else{ rhdr.data = buf + off; rhdr.count = n - off; if (rhdr.count > cnt) rhdr.count = cnt; } return nil; } if(f->dir == &dirs[Qaudioctl]){ Fcall *hdr; qlock(f); a = f->fiddata; if (off - a->offoff < 0){ /* there was a seek */ a->offoff = off; a->ns = 0; } do { if (off - a->offoff < a->ns){ rhdr.data = a->s + (off - a->offoff); rhdr.count = a->ns - (off - a->offoff); if (rhdr.count > cnt) rhdr.count = cnt; qunlock(f); return nil; } if (a->offoff != off){ a->ns = 0; a->offoff = off; rhdr.count = 0; qunlock(f); return nil; } } while (makeaudioctldata(f) != 0); assert(a->offoff == off); /* Wait for data off line */ f->readers++; w = nbrecvp(procchan); if (w == nil){ w = emallocz(sizeof(Worker), 1); w->eventc = chancreate(sizeof(ulong), 1); w->next = workers; workers = w; proccreate(readproc, w, 4096); } hdr = emalloc(sizeof(Fcall)); w->fid = f; w->tag = thdr.tag; assert(w->rhdr == nil); w->rhdr = hdr; hdr->count = cnt; hdr->offset = off; hdr->type = thdr.type+1; hdr->fid = thdr.fid; hdr->tag = thdr.tag; sendul(w->eventc, Work); return (char*)~0; } return Eperm;}char*rwrite(Fid *f){ long cnt, value; char *lines[2*Ncontrol], *fields[4], *subfields[9], *err, *p; int nlines, i, nf, nnf, rec, ctl; Audiocontrol *c; Worker *w; static char buf[256]; rhdr.count = 0; cnt = thdr.count; if(cnt > messagesize - IOHDRSZ) cnt = messagesize - IOHDRSZ; err = nil; if(f->dir == &dirs[Qvolume] || f->dir == &dirs[Qaudioctl]){ thdr.data[cnt] = '\0'; nlines = getfields(thdr.data, lines, 2*Ncontrol, 1, "\n"); for(i = 0; i < nlines; i++){ if (debug) fprint(2, "line: %s\n", lines[i]); nf = tokenize(lines[i], fields, 4); if (nf == 0) continue; if (nf == 3){ if (strcmp(fields[1], "in") == 0 || strcmp(fields[1], "record") == 0) rec = 1; else if (strcmp(fields[1], "out") == 0 || strcmp(fields[1], "playback") == 0) rec = 0; else { if (debug) fprint(2, "bad1\n"); return Ebadctl; } }else if (nf == 2) rec = 0; else { if (debug) fprint(2, "bad2 %d\n", nf); return Ebadctl; } c = nil; if (strcmp(fields[0], "audio") == 0) /* special case */ fields[0] = "volume"; for (ctl = 0; ctl < Ncontrol; ctl++){ c = &controls[rec][ctl]; if (strcmp(fields[0], c->name) == 0) break; } if (ctl == Ncontrol){ if (debug) fprint(2, "bad3\n"); return Ebadctl; } if (f->dir == &dirs[Qvolume] && c->min != Undef && c->max != Undef){ nnf = tokenize(fields[nf-1], subfields, nelem(subfields)); if (nnf <= 0 || nnf > 8){ if (debug) fprint(2, "bad4\n"); return Ebadctl; } p = buf; for (i = 0; i < nnf; i++){ value = strtol(subfields[i], nil, 0); value = ((100 - value) * c->min + value * c->max) / 100; if (debug) { if (p == buf) fprint(2, "rwrite: %s %s '%ld", c->name, rec?"record":"playback", value); else fprint(2, " %ld", value); } if (p == buf) p = seprint(p, buf+sizeof buf, "0x%p %s %s '%ld", replchan, c->name, rec?"record":"playback", value); else p = seprint(p, buf+sizeof buf, " %ld", value); } if (debug) fprint(2, "'\n"); seprint(p, buf+sizeof buf, "'"); chanprint(controlchan, buf); } else { if (debug) fprint(2, "rwrite: %s %s %q", c->name, rec?"record":"playback", fields[nf-1]); chanprint(controlchan, "0x%p %s %s %q", replchan, c->name, rec?"record":"playback", fields[nf-1]); } p = recvp(replchan); if (p){ if (strcmp(p, "ok") == 0){ free(p); p = nil; } if (err == nil) err = p; } } for (w = workers; w; w = w->next) nbsendul(w->eventc, Qaudioctl << 16 | Check); rhdr.count = thdr.count; return err; } return Eperm;}char *rclunk(Fid *f){ Audioctldata *a; qlock(f); f->flags &= ~(Open|Busy); assert (f->readers ==0); if (f->fiddata){ a = f->fiddata; if (a->s) free(a->s); free(a); f->fiddata = nil; } qunlock(f); return 0;}char *rremove(Fid *){ return Eperm;}char *rstat(Fid *f){ Audioctldata *a; if (f->dir == &dirs[Qaudio] && endpt[Play] < 0) return Enotexist; if (f->dir == &dirs[Qaudioin] && endpt[Record] < 0) return Enotexist; if (f->dir == &dirs[Qaudioctl]){ qlock(f); if (f->fiddata == nil) f->fiddata = allocaudioctldata(); a = f->fiddata; if (a->ns == 0) makeaudioctldata(f); f->dir->length = a->offoff + a->ns; qunlock(f); } rhdr.nstat = convD2M(f->dir, mbuf, messagesize - IOHDRSZ); rhdr.stat = mbuf; return 0;}char *rwstat(Fid*){ return Eperm;}Fid *newfid(int fid){ Fid *f, *ff; ff = nil; for(f = fids; f; f = f->next) if(f->fid == fid){ return f; }else if(ff == nil && (f->flags & Busy) == 0) ff = f; if(ff == nil){ ff = emallocz(sizeof *ff, 1); ff->next = fids; fids = ff; } ff->fid = fid; ff->flags &= ~(Busy|Open); ff->dir = nil; return ff;}voidio(void *){ char *err, e[32]; int n; close(p[1]); procchan = chancreate(sizeof(Channel*), 8); replchan = chancreate(sizeof(char*), 0); for(;;){ /* * reading from a pipe or a network device * will give an error after a few eof reads * however, we cannot tell the difference * between a zero-length read and an interrupt * on the processes writing to us, * so we wait for the error */ n = read9pmsg(mfd[0], mdata, messagesize); if(n == 0) continue; if(n < 0){ rerrstr(e, sizeof e); if (strcmp(e, "interrupted") == 0){ if (debug) fprint(2, "read9pmsg interrupted\n"); continue; } return; } if(convM2S(mdata, n, &thdr) == 0) continue; if(debug & Dbgfs) fprint(2, "io:<-%F\n", &thdr); rhdr.data = (char*)mdata + messagesize; if(!fcalls[thdr.type]) err = "bad fcall type"; else err = (*fcalls[thdr.type])(newfid(thdr.fid)); if (err == (char*)~0) continue; /* handled off line */ if(err){ rhdr.type = Rerror; rhdr.ename = err; }else{ rhdr.type = thdr.type + 1; rhdr.fid = thdr.fid; } rhdr.tag = thdr.tag; if(debug & Dbgfs) fprint(2, "io:->%F\n", &rhdr); n = convS2M(&rhdr, mdata, messagesize); if(write(mfd[1], mdata, n) != n) sysfatal("mount write"); }}intnewid(void){ int rv; static int id; static Lock idlock; lock(&idlock); rv = ++id; unlock(&idlock); return rv;}voidctlevent(void){ Worker *w; for (w = workers; w; w = w->next) nbsendul(w->eventc, Qaudioctl << 16 | Check);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -