Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/sequencer.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/sequencer.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.30 retrieving revision 1.30.4.1 diff -u -p -r1.30 -r1.30.4.1 --- src/sys/dev/sequencer.c 2005/12/11 12:20:53 1.30 +++ src/sys/dev/sequencer.c 2006/09/09 02:49:09 1.30.4.1 @@ -1,4 +1,4 @@ -/* $NetBSD: sequencer.c,v 1.30 2005/12/11 12:20:53 christos Exp $ */ +/* $NetBSD: sequencer.c,v 1.30.4.1 2006/09/09 02:49:09 rpaulo Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.30 2005/12/11 12:20:53 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.30.4.1 2006/09/09 02:49:09 rpaulo Exp $"); #include "sequencer.h" @@ -83,98 +83,72 @@ int sequencerdebug = 0; #define DPRINTFN(n,x) #endif -#define SEQ_CMD(b) ((b)->arr[0]) - -#define SEQ_EDEV(b) ((b)->arr[1]) -#define SEQ_ECMD(b) ((b)->arr[2]) -#define SEQ_ECHAN(b) ((b)->arr[3]) -#define SEQ_ENOTE(b) ((b)->arr[4]) -#define SEQ_EPARM(b) ((b)->arr[5]) - -#define SEQ_EP1(b) ((b)->arr[4]) -#define SEQ_EP2(b) ((b)->arr[5]) - -#define SEQ_XCMD(b) ((b)->arr[1]) -#define SEQ_XDEV(b) ((b)->arr[2]) -#define SEQ_XCHAN(b) ((b)->arr[3]) -#define SEQ_XNOTE(b) ((b)->arr[4]) -#define SEQ_XVEL(b) ((b)->arr[5]) - -#define SEQ_TCMD(b) ((b)->arr[1]) -#define SEQ_TPARM(b) ((b)->arr[4]) - #define SEQ_NOTE_MAX 128 #define SEQ_NOTE_XXX 255 -#define SEQ_VEL_OFF 0 -#define RECALC_TICK(t) ((t)->tick = 60 * 1000000L / ((t)->tempo * (t)->timebase)) +#define RECALC_USPERDIV(t) \ +((t)->usperdiv = 60*1000000L/((t)->tempo_beatpermin*(t)->timebase_divperbeat)) struct sequencer_softc seqdevs[NSEQUENCER]; void sequencerattach(int); -void seq_reset(struct sequencer_softc *); -int seq_do_command(struct sequencer_softc *, seq_event_rec *); -int seq_do_extcommand(struct sequencer_softc *, seq_event_rec *); -int seq_do_chnvoice(struct sequencer_softc *, seq_event_rec *); -int seq_do_chncommon(struct sequencer_softc *, seq_event_rec *); -int seq_do_timing(struct sequencer_softc *, seq_event_rec *); -int seq_do_local(struct sequencer_softc *, seq_event_rec *); -int seq_do_sysex(struct sequencer_softc *, seq_event_rec *); -int seq_do_fullsize(struct sequencer_softc *, seq_event_rec *, struct uio *); -int seq_timer(struct sequencer_softc *, int, int, seq_event_rec *); -static int seq_input_event(struct sequencer_softc *, seq_event_rec *); -int seq_drain(struct sequencer_softc *); -void seq_startoutput(struct sequencer_softc *); -void seq_timeout(void *); -int seq_to_new(seq_event_rec *, struct uio *); +static void seq_reset(struct sequencer_softc *); +static int seq_do_command(struct sequencer_softc *, seq_event_t *); +static int seq_do_chnvoice(struct sequencer_softc *, seq_event_t *); +static int seq_do_chncommon(struct sequencer_softc *, seq_event_t *); +static void seq_timer_waitabs(struct sequencer_softc *, uint32_t); +static int seq_do_timing(struct sequencer_softc *, seq_event_t *); +static int seq_do_local(struct sequencer_softc *, seq_event_t *); +static int seq_do_sysex(struct sequencer_softc *, seq_event_t *); +static int seq_do_fullsize(struct sequencer_softc *, seq_event_t *, struct uio *); +static int seq_input_event(struct sequencer_softc *, seq_event_t *); +static int seq_drain(struct sequencer_softc *); +static void seq_startoutput(struct sequencer_softc *); +static void seq_timeout(void *); +static int seq_to_new(seq_event_t *, struct uio *); static int seq_sleep_timo(int *, const char *, int); static int seq_sleep(int *, const char *); static void seq_wakeup(int *); struct midi_softc; -int midiseq_out(struct midi_dev *, u_char *, u_int, int); -struct midi_dev *midiseq_open(int, int); -void midiseq_close(struct midi_dev *); -void midiseq_reset(struct midi_dev *); -int midiseq_noteon(struct midi_dev *, int, int, int); -int midiseq_noteoff(struct midi_dev *, int, int, int); -int midiseq_keypressure(struct midi_dev *, int, int, int); -int midiseq_pgmchange(struct midi_dev *, int, int); -int midiseq_chnpressure(struct midi_dev *, int, int); -int midiseq_ctlchange(struct midi_dev *, int, int, int); -int midiseq_pitchbend(struct midi_dev *, int, int); -int midiseq_loadpatch(struct midi_dev *, struct sysex_info *, struct uio *); -int midiseq_putc(struct midi_dev *, int); +static int midiseq_out(struct midi_dev *, u_char *, u_int, int); +static struct midi_dev *midiseq_open(int, int); +static void midiseq_close(struct midi_dev *); +static void midiseq_reset(struct midi_dev *); +static int midiseq_noteon(struct midi_dev *, int, int, seq_event_t *); +static int midiseq_noteoff(struct midi_dev *, int, int, seq_event_t *); +static int midiseq_keypressure(struct midi_dev *, int, int, seq_event_t *); +static int midiseq_pgmchange(struct midi_dev *, int, seq_event_t *); +static int midiseq_chnpressure(struct midi_dev *, int, seq_event_t *); +static int midiseq_ctlchange(struct midi_dev *, int, seq_event_t *); +static int midiseq_pitchbend(struct midi_dev *, int, seq_event_t *); +static int midiseq_loadpatch(struct midi_dev *, struct sysex_info *, struct uio *); void midiseq_in(struct midi_dev *, u_char *, int); -dev_type_open(sequenceropen); -dev_type_close(sequencerclose); -dev_type_read(sequencerread); -dev_type_write(sequencerwrite); -dev_type_ioctl(sequencerioctl); -dev_type_poll(sequencerpoll); -dev_type_kqfilter(sequencerkqfilter); +static dev_type_open(sequenceropen); +static dev_type_close(sequencerclose); +static dev_type_read(sequencerread); +static dev_type_write(sequencerwrite); +static dev_type_ioctl(sequencerioctl); +static dev_type_poll(sequencerpoll); +static dev_type_kqfilter(sequencerkqfilter); const struct cdevsw sequencer_cdevsw = { sequenceropen, sequencerclose, sequencerread, sequencerwrite, sequencerioctl, nostop, notty, sequencerpoll, nommap, - sequencerkqfilter, + sequencerkqfilter, D_OTHER, }; void -sequencerattach(n) - int n; +sequencerattach(int n) { for (n = 0; n < NSEQUENCER; n++) callout_init(&seqdevs[n].sc_callout); } -int -sequenceropen(dev, flags, ifmt, l) - dev_t dev; - int flags, ifmt; - struct lwp *l; +static int +sequenceropen(dev_t dev, int flags, int ifmt, struct lwp *l) { int unit = SEQUENCERUNIT(dev); struct sequencer_softc *sc; @@ -210,15 +184,15 @@ sequenceropen(dev, flags, ifmt, l) if (md) { sc->devs[sc->nmidi++] = md; md->seq = sc; + md->doingsysex = 0; } } - sc->timer.timebase = 100; - sc->timer.tempo = 60; - sc->doingsysex = 0; - RECALC_TICK(&sc->timer); - sc->timer.last = 0; - microtime(&sc->timer.start); + sc->timer.timebase_divperbeat = 100; + sc->timer.tempo_beatpermin = 60; + RECALC_USPERDIV(&sc->timer); + sc->timer.divs_lastevent = sc->timer.divs_lastchange = 0; + microtime(&sc->timer.reftime); SEQ_QINIT(&sc->inq); SEQ_QINIT(&sc->outq); @@ -231,10 +205,7 @@ sequenceropen(dev, flags, ifmt, l) } static int -seq_sleep_timo(chan, label, timo) - int *chan; - const char *label; - int timo; +seq_sleep_timo(int *chan, const char *label, int timo) { int st; @@ -253,16 +224,13 @@ seq_sleep_timo(chan, label, timo) } static int -seq_sleep(chan, label) - int *chan; - const char *label; +seq_sleep(int *chan, const char *label) { return seq_sleep_timo(chan, label, 0); } static void -seq_wakeup(chan) - int *chan; +seq_wakeup(int *chan) { if (*chan) { DPRINTFN(5, ("seq_wakeup: %p\n", chan)); @@ -271,9 +239,8 @@ seq_wakeup(chan) } } -int -seq_drain(sc) - struct sequencer_softc *sc; +static int +seq_drain(struct sequencer_softc *sc) { int error; @@ -285,9 +252,8 @@ seq_drain(sc) return (error); } -void -seq_timeout(addr) - void *addr; +static void +seq_timeout(void *addr) { struct sequencer_softc *sc = addr; DPRINTFN(4, ("seq_timeout: %p\n", sc)); @@ -302,12 +268,11 @@ seq_timeout(addr) } -void -seq_startoutput(sc) - struct sequencer_softc *sc; +static void +seq_startoutput(struct sequencer_softc *sc) { struct sequencer_queue *q = &sc->outq; - seq_event_rec cmd; + seq_event_t cmd; if (sc->timeout) return; @@ -318,11 +283,8 @@ seq_startoutput(sc) } } -int -sequencerclose(dev, flags, ifmt, l) - dev_t dev; - int flags, ifmt; - struct lwp *l; +static int +sequencerclose(dev_t dev, int flags, int ifmt, struct lwp *l) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; int n, s; @@ -345,15 +307,16 @@ sequencerclose(dev, flags, ifmt, l) } static int -seq_input_event(sc, cmd) - struct sequencer_softc *sc; - seq_event_rec *cmd; +seq_input_event(struct sequencer_softc *sc, seq_event_t *cmd) { struct sequencer_queue *q = &sc->inq; DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x %02x %02x %02x\n", - cmd->arr[0], cmd->arr[1], cmd->arr[2], cmd->arr[3], - cmd->arr[4], cmd->arr[5], cmd->arr[6], cmd->arr[7])); + cmd->tag, + cmd->unknown.byte[0], cmd->unknown.byte[1], + cmd->unknown.byte[2], cmd->unknown.byte[3], + cmd->unknown.byte[4], cmd->unknown.byte[5], + cmd->unknown.byte[6])); if (SEQ_QFULL(q)) return (ENOMEM); SEQ_QPUT(q, *cmd); @@ -365,48 +328,35 @@ seq_input_event(sc, cmd) } void -seq_event_intr(addr, iev) - void *addr; - seq_event_rec *iev; +seq_event_intr(void *addr, seq_event_t *iev) { struct sequencer_softc *sc = addr; - union { - u_int32_t l; - u_int8_t b[4]; - } u; u_long t; struct timeval now; - seq_event_rec ev; + int s; microtime(&now); - SUBTIMEVAL(&now, &sc->timer.start); + s = splsoftclock(); + if (!sc->timer.running) + now = sc->timer.stoptime; + SUBTIMEVAL(&now, &sc->timer.reftime); t = now.tv_sec * 1000000 + now.tv_usec; - t /= sc->timer.tick; + t /= sc->timer.usperdiv; + t += sc->timer.divs_lastchange; + splx(s); if (t != sc->input_stamp) { - ev.arr[0] = SEQ_TIMING; - ev.arr[1] = TMR_WAIT_ABS; - ev.arr[2] = 0; - ev.arr[3] = 0; - u.l = t; - ev.arr[4] = u.b[0]; - ev.arr[5] = u.b[1]; - ev.arr[6] = u.b[2]; - ev.arr[7] = u.b[3]; - seq_input_event(sc, &ev); - sc->input_stamp = t; + seq_input_event(sc, &SEQ_MK_TIMING(WAIT_ABS, .divisions=t)); + sc->input_stamp = t; /* XXX wha hoppen if timer is reset? */ } seq_input_event(sc, iev); } -int -sequencerread(dev, uio, ioflag) - dev_t dev; - struct uio *uio; - int ioflag; +static int +sequencerread(dev_t dev, struct uio *uio, int ioflag) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; struct sequencer_queue *q = &sc->inq; - seq_event_rec ev; + seq_event_t ev; int error, s; DPRINTFN(20, ("sequencerread: %p, count=%d, ioflag=%x\n", @@ -436,18 +386,15 @@ sequencerread(dev, uio, ioflag) return error; } -int -sequencerwrite(dev, uio, ioflag) - dev_t dev; - struct uio *uio; - int ioflag; +static int +sequencerwrite(dev_t dev, struct uio *uio, int ioflag) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; struct sequencer_queue *q = &sc->outq; int error; - seq_event_rec cmdbuf; + seq_event_t cmdbuf; int size; - + DPRINTFN(2, ("sequencerwrite: %p, count=%d\n", sc, (int) uio->uio_resid)); error = 0; @@ -459,7 +406,7 @@ sequencerwrite(dev, uio, ioflag) if (sc->mode == SEQ_OLD) if (seq_to_new(&cmdbuf, uio)) continue; - if (SEQ_CMD(&cmdbuf) == SEQ_FULLSIZE) { + if (cmdbuf.tag == SEQ_FULLSIZE) { /* We do it like OSS does, asynchronously */ error = seq_do_fullsize(sc, &cmdbuf, uio); if (error) @@ -487,19 +434,15 @@ sequencerwrite(dev, uio, ioflag) return error; } -int -sequencerioctl(dev, cmd, addr, flag, l) - dev_t dev; - u_long cmd; - caddr_t addr; - int flag; - struct lwp *l; +static int +sequencerioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct lwp *l) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; struct synth_info *si; struct midi_dev *md; int devno; int error; + int s; int t; DPRINTFN(2, ("sequencerioctl: %p cmd=0x%08lx\n", sc, cmd)); @@ -564,7 +507,9 @@ sequencerioctl(dev, cmd, addr, flag, l) *(u_char *)(addr+2), *(u_char *)(addr+3), *(u_char *)(addr+4), *(u_char *)(addr+5), *(u_char *)(addr+6), *(u_char *)(addr+7))); - error = seq_do_command(sc, (seq_event_rec *)addr); + if ( !(sc->flags & FWRITE ) ) + return EBADF; + error = seq_do_command(sc, (seq_event_t *)addr); break; case SEQUENCER_TMR_TIMEBASE: @@ -573,32 +518,40 @@ sequencerioctl(dev, cmd, addr, flag, l) t = 1; if (t > 10000) t = 10000; - sc->timer.timebase = t; *(int *)addr = t; - RECALC_TICK(&sc->timer); + s = splsoftclock(); + sc->timer.timebase_divperbeat = t; + sc->timer.divs_lastchange = sc->timer.divs_lastevent; + microtime(&sc->timer.reftime); + RECALC_USPERDIV(&sc->timer); + splx(s); break; case SEQUENCER_TMR_START: - error = seq_timer(sc, TMR_START, 0, 0); + s = splsoftclock(); + error = seq_do_timing(sc, &SEQ_MK_TIMING(START)); + splx(s); break; case SEQUENCER_TMR_STOP: - error = seq_timer(sc, TMR_STOP, 0, 0); + s = splsoftclock(); + error = seq_do_timing(sc, &SEQ_MK_TIMING(STOP)); + splx(s); break; case SEQUENCER_TMR_CONTINUE: - error = seq_timer(sc, TMR_CONTINUE, 0, 0); + s = splsoftclock(); + error = seq_do_timing(sc, &SEQ_MK_TIMING(CONTINUE)); + splx(s); break; case SEQUENCER_TMR_TEMPO: - t = *(int *)addr; - if (t < 8) - t = 8; - if (t > 250) - t = 250; - sc->timer.tempo = t; - *(int *)addr = t; - RECALC_TICK(&sc->timer); + s = splsoftclock(); + error = seq_do_timing(sc, + &SEQ_MK_TIMING(TEMPO, .bpm=*(int *)addr)); + splx(s); + if (!error) + *(int *)addr = sc->timer.tempo_beatpermin; break; case SEQUENCER_TMR_SOURCE: @@ -619,7 +572,10 @@ sequencerioctl(dev, cmd, addr, flag, l) break; case SEQUENCER_CTRLRATE: - *(int *)addr = (sc->timer.tempo*sc->timer.timebase + 30) / 60; + s = splsoftclock(); + *(int *)addr = (sc->timer.tempo_beatpermin + *sc->timer.timebase_divperbeat + 30) / 60; + splx(s); break; case SEQUENCER_GETTIME: @@ -627,9 +583,12 @@ sequencerioctl(dev, cmd, addr, flag, l) struct timeval now; u_long tx; microtime(&now); - SUBTIMEVAL(&now, &sc->timer.start); + s = splsoftclock(); + SUBTIMEVAL(&now, &sc->timer.reftime); tx = now.tv_sec * 1000000 + now.tv_usec; - tx /= sc->timer.tick; + tx /= sc->timer.usperdiv; + tx += sc->timer.divs_lastchange; + splx(s); *(int *)addr = tx; break; } @@ -642,11 +601,8 @@ sequencerioctl(dev, cmd, addr, flag, l) return error; } -int -sequencerpoll(dev, events, l) - dev_t dev; - int events; - struct lwp *l; +static int +sequencerpoll(dev_t dev, int events, struct lwp *l) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; int revents = 0; @@ -654,18 +610,18 @@ sequencerpoll(dev, events, l) DPRINTF(("sequencerpoll: %p events=0x%x\n", sc, events)); if (events & (POLLIN | POLLRDNORM)) - if (!SEQ_QEMPTY(&sc->inq)) + if ((sc->flags&FREAD) && !SEQ_QEMPTY(&sc->inq)) revents |= events & (POLLIN | POLLRDNORM); if (events & (POLLOUT | POLLWRNORM)) - if (SEQ_QLEN(&sc->outq) < sc->lowat) + if ((sc->flags&FWRITE) && SEQ_QLEN(&sc->outq) < sc->lowat) revents |= events & (POLLOUT | POLLWRNORM); if (revents == 0) { - if (events & (POLLIN | POLLRDNORM)) + if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) selrecord(l, &sc->rsel); - if (events & (POLLOUT | POLLWRNORM)) + if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM))) selrecord(l, &sc->wsel); } @@ -726,7 +682,7 @@ filt_sequencerwrite(struct knote *kn, lo static const struct filterops sequencerwrite_filtops = { 1, NULL, filt_sequencerwdetach, filt_sequencerwrite }; -int +static int sequencerkqfilter(dev_t dev, struct knote *kn) { struct sequencer_softc *sc = &seqdevs[SEQUENCERUNIT(dev)]; @@ -757,34 +713,36 @@ sequencerkqfilter(dev_t dev, struct knot return (0); } -void -seq_reset(sc) - struct sequencer_softc *sc; +static void +seq_reset(struct sequencer_softc *sc) { int i, chn; struct midi_dev *md; + if ( !(sc->flags & FWRITE) ) + return; for (i = 0; i < sc->nmidi; i++) { md = sc->devs[i]; midiseq_reset(md); for (chn = 0; chn < MAXCHAN; chn++) { - midiseq_ctlchange(md, chn, MIDI_CTRL_ALLOFF, 0); - midiseq_ctlchange(md, chn, MIDI_CTRL_RESET, 0); - midiseq_pitchbend(md, chn, MIDI_BEND_NEUTRAL); + midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, + .controller=MIDI_CTRL_NOTES_OFF)); + midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, + .controller=MIDI_CTRL_RESET)); + midiseq_pitchbend(md, chn, &SEQ_MK_CHN(PITCH_BEND, + .value=MIDI_BEND_NEUTRAL)); } } } -int -seq_do_command(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; +static int +seq_do_command(struct sequencer_softc *sc, seq_event_t *b) { int dev; - DPRINTFN(4, ("seq_do_command: %p cmd=0x%02x\n", sc, SEQ_CMD(b))); + DPRINTFN(4, ("seq_do_command: %p cmd=0x%02x\n", sc, b->timing.op)); - switch(SEQ_CMD(b)) { + switch(b->tag) { case SEQ_LOCAL: return seq_do_local(sc, b); case SEQ_TIMING: @@ -797,253 +755,224 @@ seq_do_command(sc, b) return seq_do_sysex(sc, b); /* COMPAT */ case SEQOLD_MIDIPUTC: - dev = b->arr[2]; + dev = b->putc.device; if (dev < 0 || dev >= sc->nmidi) return (ENXIO); - return midiseq_putc(sc->devs[dev], b->arr[1]); + return midiseq_out(sc->devs[dev], &b->putc.byte, 1, 0); default: - DPRINTFN(-1,("seq_do_command: unimpl command %02x\n", - SEQ_CMD(b))); + DPRINTFN(-1,("seq_do_command: unimpl command %02x\n", b->tag)); return (EINVAL); } } -int -seq_do_chnvoice(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; +static int +seq_do_chnvoice(struct sequencer_softc *sc, seq_event_t *b) { - int cmd, dev, chan, note, parm, voice; + int dev; int error; struct midi_dev *md; - dev = SEQ_EDEV(b); - if (dev < 0 || dev >= sc->nmidi) + dev = b->voice.device; + if (dev < 0 || dev >= sc->nmidi || + b->voice.channel > 15 || + b->voice.key >= SEQ_NOTE_MAX) return ENXIO; md = sc->devs[dev]; - cmd = SEQ_ECMD(b); - chan = SEQ_ECHAN(b); - note = SEQ_ENOTE(b); - parm = SEQ_EPARM(b); - DPRINTFN(2,("seq_do_chnvoice: cmd=%02x dev=%d chan=%d note=%d parm=%d\n", - cmd, dev, chan, note, parm)); - voice = chan; - if (cmd == MIDI_NOTEON && parm == 0) { - cmd = MIDI_NOTEOFF; - parm = MIDI_HALF_VEL; - } - switch(cmd) { - case MIDI_NOTEON: - DPRINTFN(5, ("seq_do_chnvoice: noteon %p %d %d %d\n", - md, voice, note, parm)); - error = midiseq_noteon(md, voice, note, parm); + switch(b->voice.op) { + case MIDI_NOTEON: /* no need to special-case hidden noteoff here */ + error = midiseq_noteon(md, b->voice.channel, b->voice.key, b); break; case MIDI_NOTEOFF: - error = midiseq_noteoff(md, voice, note, parm); + error = midiseq_noteoff(md, b->voice.channel, b->voice.key, b); break; case MIDI_KEY_PRESSURE: - error = midiseq_keypressure(md, voice, note, parm); + error = midiseq_keypressure(md, + b->voice.channel, b->voice.key, b); break; default: - DPRINTFN(-1,("seq_do_chnvoice: unimpl command %02x\n", cmd)); + DPRINTFN(-1,("seq_do_chnvoice: unimpl command %02x\n", + b->voice.op)); error = EINVAL; break; } return error; } -int -seq_do_chncommon(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; +static int +seq_do_chncommon(struct sequencer_softc *sc, seq_event_t *b) { - int cmd, dev, chan, p1, w14; + int dev; int error; struct midi_dev *md; - union { - int16_t s; - u_int8_t b[2]; - } u; - dev = SEQ_EDEV(b); - if (dev < 0 || dev >= sc->nmidi) + dev = b->common.device; + if (dev < 0 || dev >= sc->nmidi || + b->common.channel > 15) return ENXIO; md = sc->devs[dev]; - cmd = SEQ_ECMD(b); - chan = SEQ_ECHAN(b); - p1 = SEQ_EP1(b); - u.b[0] = b->arr[6]; - u.b[1] = b->arr[7]; - w14 = u.s; - DPRINTFN(2,("seq_do_chncommon: %02x\n", cmd)); + DPRINTFN(2,("seq_do_chncommon: %02x\n", b->common.op)); error = 0; - switch(cmd) { + switch(b->common.op) { case MIDI_PGM_CHANGE: - error = midiseq_pgmchange(md, chan, p1); + error = midiseq_pgmchange(md, b->common.channel, b); break; case MIDI_CTL_CHANGE: - if (chan > 15 || p1 > 127) - return 0; /* EINVAL */ - error = midiseq_ctlchange(md, chan, p1, w14); + error = midiseq_ctlchange(md, b->common.channel, b); break; case MIDI_PITCH_BEND: - error = midiseq_pitchbend(md, chan, w14); + error = midiseq_pitchbend(md, b->common.channel, b); break; case MIDI_CHN_PRESSURE: - error = midiseq_chnpressure(md, chan, p1); + error = midiseq_chnpressure(md, b->common.channel, b); break; default: - DPRINTFN(-1,("seq_do_chncommon: unimpl command %02x\n", cmd)); + DPRINTFN(-1,("seq_do_chncommon: unimpl command %02x\n", + b->common.op)); error = EINVAL; break; } - return (error); -} - -int -seq_do_timing(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; -{ - union { - int32_t i; - u_int8_t b[4]; - } u; - u.b[0] = b->arr[4]; - u.b[1] = b->arr[5]; - u.b[2] = b->arr[6]; - u.b[3] = b->arr[7]; - return seq_timer(sc, SEQ_TCMD(b), u.i, b); + return error; } -int -seq_do_local(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; +static int +seq_do_local(struct sequencer_softc *sc, seq_event_t *b) { return (EINVAL); } -int -seq_do_sysex(sc, b) - struct sequencer_softc *sc; - seq_event_rec *b; +static int +seq_do_sysex(struct sequencer_softc *sc, seq_event_t *b) { int dev, i; struct midi_dev *md; - u_int8_t c, *bf = &b->arr[2]; + uint8_t *bf = b->sysex.buffer; - dev = SEQ_EDEV(b); + dev = b->sysex.device; if (dev < 0 || dev >= sc->nmidi) return (ENXIO); DPRINTF(("seq_do_sysex: dev=%d\n", dev)); md = sc->devs[dev]; - if (!sc->doingsysex) { - c = MIDI_SYSEX_START; - midiseq_out(md, &c, 1, 0); - sc->doingsysex = 1; + if (!md->doingsysex) { + midiseq_out(md, (uint8_t[]){MIDI_SYSEX_START}, 1, 0); + md->doingsysex = 1; } for (i = 0; i < 6 && bf[i] != 0xff; i++) ; midiseq_out(md, bf, i, 0); if (i < 6 || (i > 0 && bf[i-1] == MIDI_SYSEX_END)) - sc->doingsysex = 0; - return (0); + md->doingsysex = 0; + return 0; } -int -seq_timer(sc, cmd, parm, b) - struct sequencer_softc *sc; - int cmd, parm; - seq_event_rec *b; +static void +seq_timer_waitabs(struct sequencer_softc *sc, uint32_t divs) { - struct syn_timer *t = &sc->timer; struct timeval when; - int ticks; - int error; long long usec; + struct syn_timer *t; + int ticks; - DPRINTFN(2,("seq_timer: %02x %d\n", cmd, parm)); - - error = 0; - switch(cmd) { - case TMR_WAIT_REL: - parm += t->last; - /* fall into */ - case TMR_WAIT_ABS: - t->last = parm; - usec = (long long)parm * (long long)t->tick; /* convert to usec */ - when.tv_sec = usec / 1000000; - when.tv_usec = usec % 1000000; - DPRINTFN(4, ("seq_timer: parm=%d, sleep when=%ld.%06ld", parm, - when.tv_sec, when.tv_usec)); - ADDTIMEVAL(&when, &t->start); /* abstime for end */ - ticks = hzto(&when); - DPRINTFN(4, (" when+start=%ld.%06ld, tick=%d\n", - when.tv_sec, when.tv_usec, ticks)); - if (ticks > 0) { + t = &sc->timer; + t->divs_lastevent = divs; + divs -= t->divs_lastchange; + usec = (long long)divs * (long long)t->usperdiv; /* convert to usec */ + when.tv_sec = usec / 1000000; + when.tv_usec = usec % 1000000; + DPRINTFN(4, ("seq_timer_waitabs: adjdivs=%d, sleep when=%ld.%06ld", + divs, when.tv_sec, when.tv_usec)); + ADDTIMEVAL(&when, &t->reftime); /* abstime for end */ + ticks = hzto(&when); + DPRINTFN(4, (" when+start=%ld.%06ld, tick=%d\n", + when.tv_sec, when.tv_usec, ticks)); + if (ticks > 0) { #ifdef DIAGNOSTIC - if (ticks > 20 * hz) { - /* Waiting more than 20s */ - printf("seq_timer: funny ticks=%d, usec=%lld, parm=%d, tick=%ld\n", - ticks, usec, parm, t->tick); - } -#endif - sc->timeout = 1; - callout_reset(&sc->sc_callout, ticks, - seq_timeout, sc); + if (ticks > 20 * hz) { + /* Waiting more than 20s */ + printf("seq_timer_waitabs: funny ticks=%d, " + "usec=%lld\n", ticks, usec); } +#endif + sc->timeout = 1; + callout_reset(&sc->sc_callout, ticks, + seq_timeout, sc); + } #ifdef SEQUENCER_DEBUG - else if (tick < 0) - DPRINTF(("seq_timer: ticks = %d\n", ticks)); + else if (tick < 0) + DPRINTF(("seq_timer_waitabs: ticks = %d\n", ticks)); #endif +} + +static int +seq_do_timing(struct sequencer_softc *sc, seq_event_t *b) +{ + struct syn_timer *t = &sc->timer; + struct timeval when; + int error; + + error = 0; + switch(b->timing.op) { + case TMR_WAIT_REL: + seq_timer_waitabs(sc, + b->t_WAIT_REL.divisions + t->divs_lastevent); + break; + case TMR_WAIT_ABS: + seq_timer_waitabs(sc, b->t_WAIT_ABS.divisions); break; case TMR_START: - microtime(&t->start); + microtime(&t->reftime); + t->divs_lastevent = t->divs_lastchange = 0; t->running = 1; break; case TMR_STOP: - microtime(&t->stop); + microtime(&t->stoptime); t->running = 0; break; case TMR_CONTINUE: + if (t->running) + break; microtime(&when); - SUBTIMEVAL(&when, &t->stop); - ADDTIMEVAL(&t->start, &when); + SUBTIMEVAL(&when, &t->stoptime); + ADDTIMEVAL(&t->reftime, &when); t->running = 1; break; case TMR_TEMPO: - /* parm is ticks per minute / timebase */ - if (parm < 8) - parm = 8; - if (parm > 360) - parm = 360; - t->tempo = parm; - RECALC_TICK(t); + /* bpm is unambiguously MIDI clocks per minute / 24 */ + /* (24 MIDI clocks are usually but not always a quarter note) */ + if (b->t_TEMPO.bpm < 8) /* where are these limits specified? */ + t->tempo_beatpermin = 8; + else if (b->t_TEMPO.bpm > 360) /* ? */ + t->tempo_beatpermin = 360; + else + t->tempo_beatpermin = b->t_TEMPO.bpm; + t->divs_lastchange = t->divs_lastevent; + microtime(&t->reftime); + RECALC_USPERDIV(t); break; case TMR_ECHO: error = seq_input_event(sc, b); break; case TMR_RESET: - t->last = 0; - microtime(&t->start); + t->divs_lastevent = t->divs_lastchange = 0; + microtime(&t->reftime); + break; + case TMR_SPP: + case TMR_TIMESIG: + DPRINTF(("seq_do_timing: unimplemented %02x\n", b->timing.op)); + error = EINVAL; /* not quite accurate... */ break; default: - DPRINTF(("seq_timer: unknown %02x\n", cmd)); + DPRINTF(("seq_timer: unknown %02x\n", b->timing.op)); error = EINVAL; break; } return (error); } -int -seq_do_fullsize(sc, b, uio) - struct sequencer_softc *sc; - seq_event_rec *b; - struct uio *uio; +static int +seq_do_fullsize(struct sequencer_softc *sc, seq_event_t *b, struct uio *uio) { struct sysex_info sysex; u_int dev; @@ -1056,32 +985,38 @@ seq_do_fullsize(sc, b, uio) #endif memcpy(&sysex, b, sizeof sysex); dev = sysex.device_no; + if (/* dev < 0 || */ dev >= sc->nmidi) + return (ENXIO); DPRINTFN(2, ("seq_do_fullsize: fmt=%04x, dev=%d, len=%d\n", sysex.key, dev, sysex.len)); return (midiseq_loadpatch(sc->devs[dev], &sysex, uio)); } -/* Convert an old sequencer event to a new one. */ -int -seq_to_new(ev, uio) - seq_event_rec *ev; - struct uio *uio; +/* + * Convert an old sequencer event to a new one. + * NOTE: on entry, *ev may contain valid data only in the first 4 bytes. + * That may be true even on exit (!) in the case of SEQOLD_MIDIPUTC; the + * caller will only look at the first bytes in that case anyway. Ugly? Sure. + */ +static int +seq_to_new(seq_event_t *ev, struct uio *uio) { int cmd, chan, note, parm; - u_int32_t tmp_delay; + uint32_t tmp_delay; int error; + uint8_t *bfp; - cmd = SEQ_CMD(ev); - chan = ev->arr[1]; - note = ev->arr[2]; - parm = ev->arr[3]; + cmd = ev->tag; + bfp = ev->unknown.byte; + chan = *bfp++; + note = *bfp++; + parm = *bfp++; DPRINTFN(3, ("seq_to_new: 0x%02x %d %d %d\n", cmd, chan, note, parm)); if (cmd >= 0x80) { /* Fill the event record */ if (uio->uio_resid >= sizeof *ev - SEQOLD_CMDSIZE) { - error = uiomove(&ev->arr[SEQOLD_CMDSIZE], - sizeof *ev - SEQOLD_CMDSIZE, uio); + error = uiomove(bfp, sizeof *ev - SEQOLD_CMDSIZE, uio); if (error) return error; } else @@ -1090,34 +1025,52 @@ seq_to_new(ev, uio) switch(cmd) { case SEQOLD_NOTEOFF: - note = 255; - SEQ_ECMD(ev) = MIDI_NOTEOFF; - goto onoff; + /* + * What's with the SEQ_NOTE_XXX? In OSS this seems to have + * been undocumented magic for messing with the overall volume + * of a 'voice', equated precariously with 'channel' and + * pretty much unimplementable except by directly frobbing a + * synth chip. For us, who treat everything as interfaced over + * MIDI, this will just be unceremoniously discarded as + * invalid in midiseq_noteoff, making the whole event an + * elaborate no-op, and that doesn't seem to be any different + * from what happens on linux with a MIDI-interfaced device, + * by the way. The moral is ... use the new /dev/music API, ok? + */ + *ev = SEQ_MK_CHN(NOTEOFF, .device=0, .channel=chan, + .key=SEQ_NOTE_XXX, .velocity=parm); + break; case SEQOLD_NOTEON: - SEQ_ECMD(ev) = MIDI_NOTEON; - onoff: - SEQ_CMD(ev) = SEQ_CHN_VOICE; - SEQ_EDEV(ev) = 0; - SEQ_ECHAN(ev) = chan; - SEQ_ENOTE(ev) = note; - SEQ_EPARM(ev) = parm; + *ev = SEQ_MK_CHN(NOTEON, + .device=0, .channel=chan, .key=note, .velocity=parm); break; case SEQOLD_WAIT: - tmp_delay = *(u_int32_t *)ev->arr >> 8; - SEQ_CMD(ev) = SEQ_TIMING; - SEQ_TCMD(ev) = TMR_WAIT_REL; - *(u_int32_t *)&ev->arr[4] = tmp_delay; + /* + * This event cannot even /exist/ on non-littleendian machines, + * and so help me, that's exactly the way OSS defined it. + * Also, the OSS programmer's guide states (p. 74, v1.11) + * that seqold time units are system clock ticks, unlike + * the new 'divisions' which are determined by timebase. In + * that case we would need to do scaling here - but no such + * behavior is visible in linux either--which also treats this + * value, surprisingly, as an absolute, not relative, time. + * My guess is that this event has gone unused so long that + * nobody could agree we got it wrong no matter what we do. + */ + tmp_delay = *(uint32_t *)ev >> 8; + *ev = SEQ_MK_TIMING(WAIT_ABS, .divisions=tmp_delay); break; case SEQOLD_SYNCTIMER: - SEQ_CMD(ev) = SEQ_TIMING; - SEQ_TCMD(ev) = TMR_RESET; + /* + * The TMR_RESET event is not defined in any OSS materials + * I can find; it may have been invented here just to provide + * an accurate _to_new translation of this event. + */ + *ev = SEQ_MK_TIMING(RESET); break; case SEQOLD_PGMCHANGE: - SEQ_ECMD(ev) = MIDI_PGM_CHANGE; - SEQ_CMD(ev) = SEQ_CHN_COMMON; - SEQ_EDEV(ev) = 0; - SEQ_ECHAN(ev) = chan; - SEQ_EP1(ev) = note; + *ev = SEQ_MK_CHN(PGM_CHANGE, + .device=0, .channel=chan, .program=note); break; case SEQOLD_MIDIPUTC: break; /* interpret in normal mode */ @@ -1127,7 +1080,7 @@ seq_to_new(ev, uio) default: DPRINTF(("seq_to_new: not impl 0x%02x\n", cmd)); return EINVAL; - /* In case new events show up */ + /* In case new-style events show up */ case SEQ_TIMING: case SEQ_CHN_VOICE: case SEQ_CHN_COMMON: @@ -1140,13 +1093,10 @@ seq_to_new(ev, uio) /**********************************************/ void -midiseq_in(md, msg, len) - struct midi_dev *md; - u_char *msg; - int len; +midiseq_in(struct midi_dev *md, u_char *msg, int len) { int unit = md->unit; - seq_event_rec ev; + seq_event_t ev; int status, chan; DPRINTFN(2, ("midiseq_in: %p %02x %02x %02x\n", @@ -1155,37 +1105,42 @@ midiseq_in(md, msg, len) status = MIDI_GET_STATUS(msg[0]); chan = MIDI_GET_CHAN(msg[0]); switch (status) { - case MIDI_NOTEON: - if (msg[2] == 0) { - status = MIDI_NOTEOFF; - msg[2] = MIDI_HALF_VEL; - } - /* fall into */ + case MIDI_NOTEON: /* midi(4) always canonicalizes hidden note-off */ + ev = SEQ_MK_CHN(NOTEON, .device=unit, .channel=chan, + .key=msg[1], .velocity=msg[2]); + break; case MIDI_NOTEOFF: + ev = SEQ_MK_CHN(NOTEOFF, .device=unit, .channel=chan, + .key=msg[1], .velocity=msg[2]); + break; case MIDI_KEY_PRESSURE: - SEQ_MK_CHN_VOICE(&ev, unit, status, chan, msg[1], msg[2]); + ev = SEQ_MK_CHN(KEY_PRESSURE, .device=unit, .channel=chan, + .key=msg[1], .pressure=msg[2]); break; - case MIDI_CTL_CHANGE: - SEQ_MK_CHN_COMMON(&ev, unit, status, chan, msg[1], 0, msg[2]); + case MIDI_CTL_CHANGE: /* XXX not correct for MSB */ + ev = SEQ_MK_CHN(CTL_CHANGE, .device=unit, .channel=chan, + .controller=msg[1], .value=msg[2]); break; case MIDI_PGM_CHANGE: + ev = SEQ_MK_CHN(PGM_CHANGE, .device=unit, .channel=chan, + .program=msg[1]); + break; case MIDI_CHN_PRESSURE: - SEQ_MK_CHN_COMMON(&ev, unit, status, chan, msg[1], 0, 0); + ev = SEQ_MK_CHN(CHN_PRESSURE, .device=unit, .channel=chan, + .pressure=msg[1]); break; case MIDI_PITCH_BEND: - SEQ_MK_CHN_COMMON(&ev, unit, status, chan, 0, 0, - (msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7)); + ev = SEQ_MK_CHN(PITCH_BEND, .device=unit, .channel=chan, + .value=(msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7)); break; - default: + default: /* this is now the point where MIDI_ACKs disappear */ return; } seq_event_intr(md->seq, &ev); } -struct midi_dev * -midiseq_open(unit, flags) - int unit; - int flags; +static struct midi_dev * +midiseq_open(int unit, int flags) { extern struct cfdriver midi_cd; extern const struct cdevsw midi_cdevsw; @@ -1194,6 +1149,11 @@ midiseq_open(unit, flags) struct midi_softc *sc; struct midi_info mi; + midi_getinfo(makedev(0, unit), &mi); + if ( !(mi.props & MIDI_PROP_CAN_INPUT) ) + flags &= ~FREAD; + if ( 0 == ( flags & ( FREAD | FWRITE ) ) ) + return 0; DPRINTFN(2, ("midiseq_open: %d %d\n", unit, flags)); error = (*midi_cdevsw.d_open)(makedev(0, unit), flags, 0, 0); if (error) @@ -1203,7 +1163,6 @@ midiseq_open(unit, flags) md = malloc(sizeof *md, M_DEVBUF, M_WAITOK|M_ZERO); sc->seq_md = md; md->msc = sc; - midi_getinfo(makedev(0, unit), &mi); md->unit = unit; md->name = mi.name; md->subtype = 0; @@ -1214,9 +1173,8 @@ midiseq_open(unit, flags) return (md); } -void -midiseq_close(md) - struct midi_dev *md; +static void +midiseq_close(struct midi_dev *md) { extern const struct cdevsw midi_cdevsw; @@ -1225,154 +1183,91 @@ midiseq_close(md) free(md, M_DEVBUF); } -void -midiseq_reset(md) - struct midi_dev *md; +static void +midiseq_reset(struct midi_dev *md) { /* XXX send GM reset? */ DPRINTFN(3, ("midiseq_reset: %d\n", md->unit)); } -int -midiseq_out(md, bf, cc, chk) - struct midi_dev *md; - u_char *bf; - u_int cc; - int chk; +static int +midiseq_out(struct midi_dev *md, u_char *bf, u_int cc, int chk) { DPRINTFN(5, ("midiseq_out: m=%p, unit=%d, bf[0]=0x%02x, cc=%d\n", md->msc, md->unit, bf[0], cc)); - /* The MIDI "status" byte does not have to be repeated. */ - if (chk && md->last_cmd == bf[0]) - bf++, cc--; - else - md->last_cmd = bf[0]; + /* midi(4) does running status compression where appropriate. */ return midi_writebytes(md->unit, bf, cc); } -int -midiseq_noteon(md, chan, note, vel) - struct midi_dev *md; - int chan, note, vel; +/* + * If the writing process hands us a hidden note-off in a note-on event, + * we will simply write it that way; no need to special case it here, + * as midi(4) will always canonicalize or compress as appropriate anyway. + */ +static int +midiseq_noteon(struct midi_dev *md, int chan, int key, seq_event_t *ev) { - u_char bf[3]; - - DPRINTFN(6, ("midiseq_noteon 0x%02x %d %d\n", - MIDI_NOTEON | chan, note, vel)); - if (chan < 0 || chan > 15 || - note < 0 || note > 127) - return EINVAL; - if (vel < 0) vel = 0; - if (vel > 127) vel = 127; - bf[0] = MIDI_NOTEON | chan; - bf[1] = note; - bf[2] = vel; - return midiseq_out(md, bf, 3, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_NOTEON | chan, key, ev->c_NOTEON.velocity & 0x7f}, 3, 1); } -int -midiseq_noteoff(md, chan, note, vel) - struct midi_dev *md; - int chan, note, vel; +static int +midiseq_noteoff(struct midi_dev *md, int chan, int key, seq_event_t *ev) { - u_char bf[3]; - - if (chan < 0 || chan > 15 || - note < 0 || note > 127) - return EINVAL; - if (vel < 0) vel = 0; - if (vel > 127) vel = 127; - bf[0] = MIDI_NOTEOFF | chan; - bf[1] = note; - bf[2] = vel; - return midiseq_out(md, bf, 3, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_NOTEOFF | chan, key, ev->c_NOTEOFF.velocity & 0x7f}, 3, 1); } -int -midiseq_keypressure(md, chan, note, vel) - struct midi_dev *md; - int chan, note, vel; +static int +midiseq_keypressure(struct midi_dev *md, int chan, int key, seq_event_t *ev) { - u_char bf[3]; - - if (chan < 0 || chan > 15 || - note < 0 || note > 127) - return EINVAL; - if (vel < 0) vel = 0; - if (vel > 127) vel = 127; - bf[0] = MIDI_KEY_PRESSURE | chan; - bf[1] = note; - bf[2] = vel; - return midiseq_out(md, bf, 3, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_KEY_PRESSURE | chan, key, + ev->c_KEY_PRESSURE.pressure & 0x7f}, 3, 1); } -int -midiseq_pgmchange(md, chan, parm) - struct midi_dev *md; - int chan, parm; +static int +midiseq_pgmchange(struct midi_dev *md, int chan, seq_event_t *ev) { - u_char bf[2]; - - if (chan < 0 || chan > 15 || - parm < 0 || parm > 127) + if (ev->c_PGM_CHANGE.program > 127) return EINVAL; - bf[0] = MIDI_PGM_CHANGE | chan; - bf[1] = parm; - return midiseq_out(md, bf, 2, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_PGM_CHANGE | chan, ev->c_PGM_CHANGE.program}, 2, 1); } -int -midiseq_chnpressure(md, chan, parm) - struct midi_dev *md; - int chan, parm; +static int +midiseq_chnpressure(struct midi_dev *md, int chan, seq_event_t *ev) { - u_char bf[2]; - - if (chan < 0 || chan > 15 || - parm < 0 || parm > 127) + if (ev->c_CHN_PRESSURE.pressure > 127) return EINVAL; - bf[0] = MIDI_CHN_PRESSURE | chan; - bf[1] = parm; - return midiseq_out(md, bf, 2, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_CHN_PRESSURE | chan, ev->c_CHN_PRESSURE.pressure}, 2, 1); } -int -midiseq_ctlchange(md, chan, parm, w14) - struct midi_dev *md; - int chan, parm, w14; +static int +midiseq_ctlchange(struct midi_dev *md, int chan, seq_event_t *ev) { - u_char bf[3]; - - if (chan < 0 || chan > 15 || - parm < 0 || parm > 127) + if (ev->c_CTL_CHANGE.controller > 127) return EINVAL; - bf[0] = MIDI_CTL_CHANGE | chan; - bf[1] = parm; - bf[2] = w14 & 0x7f; - return midiseq_out(md, bf, 3, 1); + return midiseq_out( md, (uint8_t[]){ + MIDI_CTL_CHANGE | chan, ev->c_CTL_CHANGE.controller, + ev->c_CTL_CHANGE.value & 0x7f /* XXX this is SO wrong */ + }, 3, 1); } -int -midiseq_pitchbend(md, chan, parm) - struct midi_dev *md; - int chan, parm; +static int +midiseq_pitchbend(struct midi_dev *md, int chan, seq_event_t *ev) { - u_char bf[3]; - - if (chan < 0 || chan > 15) - return EINVAL; - bf[0] = MIDI_PITCH_BEND | chan; - bf[1] = parm & 0x7f; - bf[2] = (parm >> 7) & 0x7f; - return midiseq_out(md, bf, 3, 1); + return midiseq_out(md, (uint8_t[]){ + MIDI_PITCH_BEND | chan, + ev->c_PITCH_BEND.value & 0x7f, + (ev->c_PITCH_BEND.value >> 7) & 0x7f}, 3, 1); } -int -midiseq_loadpatch(md, sysex, uio) - struct midi_dev *md; - struct sysex_info *sysex; - struct uio *uio; +static int +midiseq_loadpatch(struct midi_dev *md, + struct sysex_info *sysex, struct uio *uio) { u_char c, bf[128]; int i, cc, error; @@ -1407,6 +1302,11 @@ midiseq_loadpatch(md, sysex, uio) break; for(i = 0; i < cc && !MIDI_IS_STATUS(bf[i]); i++) ; + /* + * XXX midi(4)'s buffer might not accomodate this, and the + * function will not block us (though in this case we have + * a process and could in principle block). + */ error = midiseq_out(md, bf, i, 0); if (error) break; @@ -1414,7 +1314,8 @@ midiseq_loadpatch(md, sysex, uio) if (i != cc) break; } - /* Any leftover data in uio is rubbish; + /* + * Any leftover data in uio is rubbish; * the SYSEX should be one write ending in SYSEX_END. */ uio->uio_resid = 0; @@ -1422,20 +1323,10 @@ midiseq_loadpatch(md, sysex, uio) return midiseq_out(md, &c, 1, 0); } -int -midiseq_putc(md, data) - struct midi_dev *md; - int data; -{ - u_char c = data; - DPRINTFN(4,("midiseq_putc: 0x%02x\n", data)); - return midiseq_out(md, &c, 1, 0); -} - #include "midi.h" #if NMIDI == 0 -dev_type_open(midiopen); -dev_type_close(midiclose); +static dev_type_open(midiopen); +static dev_type_close(midiclose); const struct cdevsw midi_cdevsw = { midiopen, midiclose, noread, nowrite, noioctl, @@ -1453,11 +1344,8 @@ midi_unit_count() return (0); } -int -midiopen(dev, flags, ifmt, l) - dev_t dev; - int flags, ifmt; - struct lwp *l; +static int +midiopen(dev_t dev, int flags, int ifmt, struct lwp *l) { return (ENXIO); } @@ -1465,26 +1353,20 @@ midiopen(dev, flags, ifmt, l) struct cfdriver midi_cd; void -midi_getinfo(dev, mi) - dev_t dev; - struct midi_info *mi; +midi_getinfo(dev_t dev, struct midi_info *mi) { + mi->name = "Dummy MIDI device"; + mi->props = 0; } -int -midiclose(dev, flags, ifmt, l) - dev_t dev; - int flags, ifmt; - struct lwp *l; +static int +midiclose(dev_t dev, int flags, int ifmt, struct lwp *l) { return (ENXIO); } int -midi_writebytes(unit, bf, cc) - int unit; - u_char *bf; - int cc; +midi_writebytes(int unit, u_char *bf, int cc) { return (ENXIO); }