⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiofs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
						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 + -