~foura/midifs

2db95d1f365bf2fc426174254f498972659be128 — james palmer a month ago 880e692 front
start overhaul of midi parsing
3 files changed, 63 insertions(+), 209 deletions(-)

M main.c
M midi.c
M midi.h
M main.c => main.c +2 -48
@@ 81,32 81,13 @@ fsattach(Req *r)
void
fsread(Req *r)
{
	Midi *dev = r->srv->aux;
	uvlong path = r->fid->qid.path;
	long count;
	char buf[512];
	
	switch(path) {
	case Qroot:
		dirread9p(r, rootgen, r);
		respond(r, nil);
		return;
	case Qctl:
		snprint(buf, sizeof buf, "channel %d\ncable %d\n", dev->chan, dev->cable);
		readstr(r, buf);
		respond(r, nil);
		return;
	case Qraw:
		/* FIXME: this may block the srv loop */
		count = read(dev->fd, r->ofcall.data, r->ifcall.count);
		if(count < 0) {
			respond(r, "couldn't read from device");
			return;
		}

		r->ofcall.count = count;
		respond(r, nil);
		return;
	}

	respond(r, "not implemented");


@@ 115,23 96,10 @@ fsread(Req *r)
void
fswrite(Req *r)
{
	Midi *dev = r->srv->aux;
	uvlong path = r->fid->qid.path;
	long count;

	switch(path) {
	case Qraw:
		/* FIXME: this may block the srv loop */
		count = write(dev->fd, r->ifcall.data, r->ifcall.count);
		if(count < 0) {
			respond(r, "couldn't write to device");
			return;
		}

		r->ofcall.count = count;
		respond(r, nil);
		return;
	}
	};

	respond(r, "not implemented");
}


@@ 171,20 139,12 @@ fswalk1(Fid *fid, char *name, Qid *qid)
	return "not found";
}

void
fsend(Srv *s)
{
	freedev(s->aux);
}

Srv fs = {
	.attach = fsattach,
	.read = fsread,
	.write = fswrite,
	.stat = fsstat,
	.walk1 = fswalk1,

	.end = fsend,
};

void


@@ 198,7 158,6 @@ usage(void)
void
main(int argc, char *argv[])
{
	Midi *dev;
	int pipe = 0;
	char *mtpt = "/mnt/midi";
	char *srvn = nil;


@@ 223,12 182,7 @@ main(int argc, char *argv[])
	if(argc < 1)
		usage();

	dev = pipe
		? mkpipedev(argv[0])
		: mkusbdev(argv[0]);
	if(!dev) sysfatal("couldn't create device: %r");
	fs.aux = dev;

	USED(pipe);
	postmountsrv(&fs, srvn, mtpt, MREPL);
	exits(nil);
}

M midi.c => midi.c +26 -149
@@ 3,155 3,32 @@

#include "midi.h"

static int
usbsend(Midi *m, Pkt *p)
{
	u8int buf[4];

	buf[0] = m->cable << 4;
	buf[0] |= p->type;
	buf[1] = p->type << 4;
	buf[1] |= m->chan;
	buf[2] = p->arg1;
	buf[3] = p->arg2;

	if(write(m->fd, buf, 4) < 4)
		return -1;

	return 0;
}

static int
usbrecv(Midi *m, Pkt *p)
{
	u8int buf[4];

again:
	if(read(m->fd, buf, 4) < 4)
		return -1;

	/* accept messages for our channel and cable */
	if(buf[0] >> 4 != m->cable)
		goto again;
	if(buf[1] & 0x0f != m->chan)
		goto again;

	p->type = buf[0] & 0x0f;
	p->arg1 = buf[2];
	p->arg2 = buf[3];

	return 0;
}

static int
midisend(Midi *m, Pkt *p)
{
	u8int buf[3];

	buf[0] = 0x80;
	buf[0] |= (p->type & 0x7f) << 4;
	buf[0] |= (m->chan & 0xf);
	buf[1] = p->arg1 & 0x7f;
	buf[2] = p->arg2 & 0x7f;

	if(write(m->fd, buf, 3) < 3)
		return -1;

	return 0;
}

static int
midirecv(Midi *m, Pkt *p)
{
	u8int buf[3];

again:
	if(read(m->fd, buf, 3) < 3)
		return -1;

	/* accept messages for our channel */
	if(buf[0] & 0x0f != m->chan)
		goto again;

	p->type = ((buf[0] >> 4) & 0x7f);
	p->arg1 = buf[1] & 0x7f;
	p->arg2 = buf[2] & 0x7f;

	return 0;
}

static int
pipeexec(char *prog)
{
	int fd[2];

	pipe(fd);
	switch(rfork(RFFDG|RFREND|RFPROC)) {
	case -1:
		werrstr("out of procs");
		return -1;
	case 0:
		dup(fd[1], 0);
		dup(fd[1], 1);
		close(fd[0]);
		
		execl("/bin/rc", "rc", "-c", prog, nil);
		abort();
	}

	close(fd[1]);
	return fd[0];
}

Midi *
mkusbdev(char *dev)
{
	Midi *m;

	m = malloc(sizeof(Midi));
	if(!m)
		return nil;

	m->fd = open(dev, ORDWR);
	if(m->fd < 0) {
		free(m);
		return nil;
	}

	m->chan = 0;
	m->cable = 0;
	m->send = usbsend;
	m->recv = usbrecv;

	return m;
}

Midi *
mkpipedev(char *prog)
{
	Midi *m;

	m = malloc(sizeof(Midi));
	if(!m)
		return nil;

	m->fd = pipeexec(prog);
	if(m->fd < 0) {
		free(m);
		return nil;
void
parsespecial(Midi *md, Msg *m, uchar byte)
{
	USED(md);
	USED(m);
	USED(byte);
}

int
parsemessage(Midi *md, Msg *m, uchar *buf, usize len)
{
	usize i;
	uchar byte;
	
	for(i=0;i<len;i++) {
		byte = buf[i];
	
		switch(byte & 0xf) {
		case 0xf:
			parsespecial(md, m, byte);
			break;
		default:
			/* FIXME write the rest of this parser */
			break;
		}
	}

	m->chan = 0;
	m->cable = 0;
	m->send = midisend;
	m->recv = midirecv;

	return m;
}

void
freedev(Midi *m)
{
	close(m->fd);
	free(m);
	return 0;
}

M midi.h => midi.h +35 -12
@@ 1,19 1,42 @@
typedef struct Pkt Pkt;
enum {
	Mnone,
	Mnoteon = 0x80,
	Mnoteoff = 0x90,
	Mkeyat = 0xa0,
	Mcontrol = 0xb0,
	Mprogram = 0xc0,
	Mchanat = 0xd0,
	Mpitchbend = 0xe0,
	Msysex = 0xf0,
	Mclock = 0xf8,
	Msense = 0xfe,
	Mreset = 0xff,
};

typedef struct Msg Msg;
typedef struct Midi Midi;

struct Pkt {
	u8int type;
	u8int arg1;
	u8int arg2;
struct Msg {
	int type;
	int chan;

	union {
		struct {
			int note;
			int velocity;
		} note;
		struct {
			int function;
			int value;
		} control;
	};
};

struct Midi {
	u8int cable, chan;
	int wait;
	int cbl, chan;
	int fd;
	int (*send)(Midi*, Pkt*);
	int (*recv)(Midi*, Pkt*);
};

Midi *	mkusbdev(char *);
Midi *	mkpipedev(char *);
void	freedev(Midi *);
	int (*read) (Midi*, Msg*);
	int (*write) (Midi*, Msg*);
};