Exemple #1
0
void
decexec(void *a)
{
	char buf[256];
	Playfd *pfd;
	Pacbuf *pb;

	threadsetname("decexec");
	pfd = a;
	close(pfd->cfd);	/* read fd */
	if(pfd->fd != 1){
		dup(pfd->fd, 1);
		close(pfd->fd);
	}
	close(0); open("/dev/null", OREAD);
	close(2); open("/dev/null", OWRITE);
	strncpy(buf, pfd->filename, sizeof(buf)-1);
	buf[sizeof(buf)-1] = 0;
	free(pfd->filename);
	free(pfd);
	procexecl(nil, "/bin/play", "play", "-o", "/fd/1", buf, nil);
	if((pb = nbrecvp(spare)) == nil)
		pb = malloc(sizeof(Pacbuf));
	pb->cmd = Error;
	pb->off = 0;
	pb->len = snprint(pb->data, sizeof(pb->data), "startplay: exec play failed");
	sendp(full, pb);
	threadexits("exec");
}
Exemple #2
0
static Buf*
allocbuf(Ether *e)
{
	Buf *bp;

	bp = nbrecvp(e->bc);
	if(bp == nil){
		qlock(e);
		if(e->nabufs < Nbufs){
			bp = emallocz(sizeof(Buf), 1);
			e->nabufs++;
			setmalloctag(bp, getcallerpc(&e));
			deprint(2, "%s: %d buffers\n", argv0, e->nabufs);
		}
		qunlock(e);
	}
	if(bp == nil){
		deprint(2, "%s: blocked waiting for allocbuf\n", argv0);
		bp = recvp(e->bc);
	}
	bp->rp = bp->data + Hdrsize;
	bp->ndata = 0;
	if(0)deprint(2, "%s: allocbuf %#p\n", argv0, bp);
	qlock(e);
	e->nbufs++;
	qunlock(e);
	return bp;
}
Exemple #3
0
static void
etherfree(Ether *e)
{
	int i;
	Buf *bp;

	if(e->free != nil)
		e->free(e);
	closedev(e->epin);
	closedev(e->epout);
	if(e->rc == nil){	/* not really started */
		free(e);
		return;
	}
	for(i = 0; i < e->nconns; i++)
		if(e->conns[i] != nil){
			while((bp = nbrecvp(e->conns[i]->rc)) != nil)
				free(bp);
			chanfree(e->conns[i]->rc);
			free(e->conns[i]);
		}
	shutdownchan(e->bc);
	shutdownchan(e->rc);
	shutdownchan(e->wc);
	e->epin = e->epout = nil;
	devctl(e->dev, "detach");
	free(e);
}
Exemple #4
0
static void
shutdownchan(Channel *c)
{
    Packser *bp;

    while((bp=nbrecvp(c)) != nil)
        free(bp);
    chanfree(c);
}
Exemple #5
0
static void
etherreadproc(void *a)
{
	int i, n, nwants;
	Buf *bp, *dbp;
	Ether *e = a;

	threadsetname("etherread");
	while(e->exiting == 0){
		bp = nbrecvp(e->rc);
		if(bp == nil){
			bp = allocbuf(e);	/* leak() may think we leak */
			if(e->bread(e, bp) < 0){
				freebuf(e, bp);
				break;
			}
			if(bp->ndata == 0){
				/* may be a short packet; continue */
				if(0)dprint(2, "%s: read: short\n", argv0);
				freebuf(e, bp);
				continue;
			}else
				setbuftype(bp);
		}
		e->nin++;
		nwants = 0;
		for(i = 0; i < e->nconns; i++)
			nwants += cwantsbp(e->conns[i], bp);
		for(i = 0; nwants > 0 && i < e->nconns; i++)
			if(cwantsbp(e->conns[i], bp)){
				n = bp->ndata;
				if(e->conns[i]->type == -2 && n > 64)
					n = 64;
				if(nwants-- == 1){
					bp->ndata = n;
					dbp = bp;
					bp = nil;
				}else{
					dbp = allocbuf(e);
					memmove(dbp->rp, bp->rp, n);
					dbp->ndata = n;
					dbp->type = bp->type;
				}
				if(nbsendp(e->conns[i]->rc, dbp) == 0){
					deprint(2, "%s: (in) packet lost\n", argv0);
					e->nierrs++;
					freebuf(e, dbp);
				}
			}
		freebuf(e, bp);
	}
	deprint(2, "%s: writeproc exiting\n", argv0);
	etherexiting(e);
	closedev(e->dev);
	usbfsdel(&e->fs);
}
Exemple #6
0
Req*
reqalloc(void)
{
	Req *r;

	if(reqs == nil)
		reqs = chancreate(sizeof(Req*), 256);
	if(r = nbrecvp(reqs))
		return r;
	r = malloc(sizeof(Req));
	return r;
}
Exemple #7
0
int
sendmsg(Channel *q, Wmsg *m)
{
	Worker *w;

	while(w = nbrecvp(q)){
		/* Test for markerdom (see bcastmsg) */
		if(w->eventc){
			send(w->eventc, m);
			return 1;
		}
		sendp(q, w);	/* put back */
	}
	return 0;
}
Exemple #8
0
void
nbnstransactionfree(NbnsTransaction **tp)
{
	NbnsTransaction **tp2;
	NbnsMessage *s;
	NbnsTransaction *t;

	t = *tp;
	if (t) {
		qlock(&transactionlist);
		while ((s = nbrecvp(t->c)) != nil)
			nbnsmessagefree(&s);
		for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
			;
		if (*tp2) {
			*tp2 = t->next;
			free(t);
		}
		qunlock(&transactionlist);
		*tp = nil;
	}
}
Exemple #9
0
static void
fsclunk(Usbfs *fs, Fid *fid)
{
	int qt;
	int64_t qid;
	Buf *bp;
	Conn *c;
	Ether *e;

	e = fs->aux;
	qid = fid->qid.path & ~fs->qid;
	qt = qtype(qid);
	switch(qt){
	case Qndata:
	case Qnctl:
	case Qnifstats:
	case Qnstats:
	case Qntype:
		if(fid->omode != ONONE){
			c = getconn(e, qnum(qid), 0);
			if(c == nil)
				sysfatal("usb: ether: fsopen bug");
			if(decref(c) == 0){
				while((bp = nbrecvp(c->rc)) != nil)
					freebuf(e, bp);
				qlock(e);
				if(c->prom != 0)
					if(decref(&e->prom) == 0)
						prom(e, 0);
				c->prom = c->type = 0;
				qunlock(e);
			}
		}
		break;
	}
	etherdump(e);
}
Exemple #10
0
void
pcmproc(void*)
{
	Pmsg localstate, newstate, prevstate;
	int fd, n;
	Pacbuf *pb, *b;
	Alt a[3] = {
		{full, &pb, CHANRCV},
		{playout, &pb, CHANRCV},
		{nil, nil, CHANEND},
	};

	/*
	 * This is the real-time proc.
	 * It gets its input from two sources, full data/control buffers from the decproc
	 * which mixes decoded data with control messages, and data buffers from the pcmproc's
	 * (*this* proc's) own internal playout buffer.
	 * When a command is received on the `full' channel containing a command that warrants
	 * an immediate change of audio source (e.g., to silence or to another number), we just
	 * toss everything in the pipeline -- i.e., the playout channel
	 * Finally, we report all state changes using `playupdate' (another message channel)
	 */
	threadsetname("pcmproc");
	close(srvfd[1]);
	fd = -1;
	localstate.cmd = 0;	/* Force initial playupdate */
	newstate.cmd = Stop;
	newstate.off = 0;
//	rtsched();
	boost();
	for(;;){
		if(newstate.m != localstate.m){
			playupdate(newstate, nil);
			localstate = newstate;
		}
		switch(alt(a)){
		case 0:
			/* buffer received from decproc */
			if((debug & DbgPcm) && localstate.m != prevstate.m){
				fprint(2, "pcm, full: %s-%d, local state is %s-%d\n",
					statetxt[pb->cmd], pb->off,
					statetxt[localstate.cmd], localstate.off);
				prevstate.m = localstate.m;
			}
			switch(pb->cmd){
			default:
				sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off);
			case Resume:
				a[1].op = CHANRCV;
				newstate.cmd = Play;
				break;
			case Pause:
				a[1].op = CHANNOP;
				newstate.cmd = Pause;
				if(fd >= 0){
					close(fd);
					fd = -1;
				}
				break;
			case Stop:
				/* Dump all data in the buffer */
				while(b = nbrecvp(playout))
					if(b->cmd == Error){
						playupdate(b->Pmsg, b->data);
						sendp(spare, b);
					}else
						sendp(empty, b);
				newstate.m = pb->m;
				a[1].op = CHANRCV;
				if(fd >= 0){
					close(fd);
					fd = -1;
				}
				break;
			case Skip:
				/* Dump all data in the buffer, then fall through */
				while(b = nbrecvp(playout))
					if(b->cmd == Error){
						playupdate(pb->Pmsg, pb->data);
						sendp(spare, pb);
					}else
						sendp(empty, b);
				a[1].op = CHANRCV;
				newstate.cmd = Play;
			case Error:
			case Play:
				/* deal with at playout, just requeue */
				sendp(playout, pb);
				pb = nil;
				localstate = newstate;
				break;
			}
			/* If we still have a buffer, free it */
			if(pb)
				sendp(spare, pb);
			break;
		case 1:
			/* internal buffer */
			if((debug & DbgPlayer) && localstate.m != prevstate.m){
				fprint(2, "pcm, playout: %s-%d, local state is %s-%d\n",
					statetxt[pb->cmd], pb->off,
					statetxt[localstate.cmd], localstate.off);
				prevstate.m = localstate.m;
			}
			switch(pb->cmd){
			default:
				sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off);
			case Error:
				playupdate(pb->Pmsg, pb->data);
				localstate = newstate;
				sendp(spare, pb);
				break;
			case Play:
				if(fd < 0 && (fd = open("/dev/audio", OWRITE)) < 0){
					a[1].op = CHANNOP;
					newstate.cmd = Pause;
					pb->cmd = Error;
					snprint(pb->data, sizeof(pb->data),
						"/dev/audio: %r");
					playupdate(pb->Pmsg, pb->data);
					sendp(empty, pb);
					break;
				}
				/* play out this buffer */
				totbytes += pb->len;
				totbuffers++;
				n = write(fd, pb->data, pb->len);
				if (n != pb->len){
					if (debug & DbgPlayer)
						fprint(2, "pcmproc: file %d: %r\n", pb->off);
					if (n < 0)
						sysfatal("pcmproc: write: %r");
				}
				newstate.m = pb->m;
				sendp(empty, pb);
				break;
			}
			break;
		}
	}
}