=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sndiod/midi.c,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** src/usr.bin/sndiod/midi.c 2012/11/23 07:03:28 1.1 --- src/usr.bin/sndiod/midi.c 2012/11/30 20:30:24 1.2 *************** *** 1,4 **** ! /* $OpenBSD: midi.c,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * --- 1,4 ---- ! /* $OpenBSD: midi.c,v 1.2 2012/11/30 20:30:24 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * *************** *** 60,66 **** unsigned int midi_portnum = 0; struct midithru { ! unsigned txmask; #define MIDITHRU_NMAX 32 } midithru[MIDITHRU_NMAX]; --- 60,66 ---- unsigned int midi_portnum = 0; struct midithru { ! unsigned int txmask, rxmask; #define MIDITHRU_NMAX 32 } midithru[MIDITHRU_NMAX]; *************** *** 120,137 **** ep->idx = 0; ep->st = 0; ep->txmask = 0; ! ep->rxmask = 1 << i; ep->mode = mode; /* ! * client output is our input (ibuf) and our output (obuf) goes ! * to client input */ ! if (ep->mode & MODE_MIDIOUT) { ! abuf_init(&ep->ibuf, MIDI_BUFSZ); ! } ! if (ep->mode & MODE_MIDIIN) { abuf_init(&ep->obuf, MIDI_BUFSZ); ! } return ep; } --- 120,135 ---- ep->idx = 0; ep->st = 0; ep->txmask = 0; ! ep->self = 1 << i; ! ep->tickets = 0; ep->mode = mode; + /* ! * the output buffer is the client intput */ ! if (ep->mode & MODE_MIDIIN) abuf_init(&ep->obuf, MIDI_BUFSZ); ! midi_tickets(ep); return ep; } *************** *** 139,202 **** midi_del(struct midi *ep) { int i; ! for (i = 0; i < MIDI_NEP; i++) ! midi_ep[i].txmask &= ~ep->rxmask; ! for (i = 0; i < MIDITHRU_NMAX; i++) ! midithru[i].txmask &= ~ep->rxmask; ! ! /* XXX: drain output */ ! ep->ops = NULL; ! if (ep->mode & MODE_MIDIOUT) { ! abuf_done(&ep->ibuf); } if (ep->mode & MODE_MIDIIN) { abuf_done(&ep->obuf); } } /* ! * add the midi endpoint in the ``tag'' midi thru box */ void ! midi_tag(struct midi *ep, unsigned int tag) { ! int i; ! struct midi *m; ! unsigned members; ! ! members = midithru[tag].txmask; ! midithru[tag].txmask |= ep->rxmask; ! ! for (i = 0, m = midi_ep; i < MIDI_NEP; i++, m++) { ! if (!(members & (1 << i))) ! continue; ! if (ep->mode & MODE_MIDIOUT) ! ep->txmask |= m->rxmask; ! if (ep->mode & MODE_MIDIIN) ! m->txmask |= ep->rxmask; } } /* ! * remove the midi endpoint from the ``tag'' midi thru box */ void ! midi_untag(struct midi *ep, unsigned int tag) { int i; - struct midi *m; - unsigned members; ! members = midithru[tag].txmask; ! midithru[tag].txmask &= ~ep->rxmask; ! ! for (i = 0, m = midi_ep;; i++, m++) { ! if (!(members & (1 << i))) ! continue; ! ep->txmask &= ~m->rxmask; ! m->txmask &= ~ep->rxmask; } } /* --- 137,218 ---- midi_del(struct midi *ep) { int i; + struct midi *peer; ! ep->txmask = 0; ! for (i = 0; i < MIDI_NEP; i++) { ! peer = midi_ep + i; ! if (peer->txmask & ep->self) { ! peer->txmask &= ~ep->self; ! midi_tickets(peer); ! } } + for (i = 0; i < MIDITHRU_NMAX; i++) { + midithru[i].txmask &= ~ep->self; + midithru[i].rxmask &= ~ep->self; + } + ep->ops = NULL; if (ep->mode & MODE_MIDIIN) { abuf_done(&ep->obuf); } } /* ! * connect two midi endpoints */ void ! midi_link(struct midi *ep, struct midi *peer) { ! if (ep->mode & MODE_MIDIOUT) { ! ep->txmask |= peer->self; ! midi_tickets(ep); } + if (ep->mode & MODE_MIDIIN) { + #ifdef DEBUG + if (ep->obuf.used > 0) { + midi_log(ep); + log_puts(": linked with non-empty buffer\n"); + panic(); + } + #endif + /* ep has empry buffer, so no need to call midi_tickets() */ + peer->txmask |= ep->self; + } } /* ! * add the midi endpoint in the ``tag'' midi thru box */ void ! midi_tag(struct midi *ep, unsigned int tag) { + struct midi *peer; + struct midithru *t = midithru + tag; int i; ! if (ep->mode & MODE_MIDIOUT) { ! ep->txmask |= t->txmask; ! midi_tickets(ep); } + if (ep->mode & MODE_MIDIIN) { + #ifdef DEBUG + if (ep->obuf.used > 0) { + midi_log(ep); + log_puts(": tagged with non-empty buffer\n"); + panic(); + } + #endif + for (i = 0; i < MIDI_NEP; i++) { + if (!(t->rxmask & (1 << i))) + continue; + peer = midi_ep + i; + peer->txmask |= ep->self; + } + } + if (ep->mode & MODE_MIDIOUT) + t->rxmask |= ep->self; + if (ep->mode & MODE_MIDIIN) + t->txmask |= ep->self; } /* *************** *** 241,267 **** } void ! midi_fill(struct midi *oep) { ! int i, count; ! struct midi *iep; for (i = 0; i < MIDI_NEP ; i++) { ! if ((oep->rxmask & (1 << i)) == 0) continue; iep = midi_ep + i; ! count = midi_in(iep); ! if (count) ! iep->ops->fill(iep->arg, count); } } /* ! * parse the give data chunk, and calling imsg() for each message */ void ! midi_parse(struct midi *iep, unsigned char *idata, int icount) { int i; unsigned char c; --- 257,314 ---- } + /* + * determine if we have gained more input tickets, and if so call the + * fill() call-back to notify the i/o layer that it can send more data + */ void ! midi_tickets(struct midi *iep) { ! int i, tickets, avail, maxavail; ! struct midi *oep; + maxavail = MIDI_BUFSZ; for (i = 0; i < MIDI_NEP ; i++) { ! if ((iep->txmask & (1 << i)) == 0) continue; + oep = midi_ep + i; + avail = oep->obuf.len - oep->obuf.used; + if (maxavail > avail) + maxavail = avail; + } + + /* + * in the worst case output message is twice the + * input message (2-byte messages with running status) + */ + tickets = maxavail / 2 - iep->tickets; + if (tickets > 0) { + iep->tickets += tickets; + iep->ops->fill(iep->arg, tickets); + } + } + + /* + * recalculate tickets of endpoints sending data to this one + */ + void + midi_fill(struct midi *oep) + { + int i; + struct midi *iep; + + for (i = 0; i < MIDI_NEP; i++) { iep = midi_ep + i; ! if (iep->txmask & oep->self) ! midi_tickets(iep); } } /* ! * parse then give data chunk, and calling imsg() for each message */ void ! midi_in(struct midi *iep, unsigned char *idata, int icount) { int i; unsigned char c; *************** *** 304,366 **** } } } } /* - * process input data stored in ep->ibuf - */ - int - midi_in(struct midi *iep) - { - unsigned char *idata; - int i, icount, maxavail, avail, idone; - struct midi *oep; - - /* - * calculate the max message size we can process - */ - maxavail = MIDI_BUFSZ; - for (i = 0; i < MIDI_NEP ; i++) { - if ((iep->txmask & (1 << i)) == 0) - continue; - oep = midi_ep + i; - avail = oep->obuf.len - oep->obuf.used; - if (maxavail > avail) - maxavail = avail; - } - - /* - * in the works case output message is twice the - * input message (2-byte messages with running status) - */ - maxavail /= 2; - idone = 0; - for (;;) { - idata = abuf_rgetblk(&iep->ibuf, &icount); - if (icount > maxavail) - icount = maxavail; - if (icount == 0) - break; - maxavail -= icount; - #ifdef DEBUG - if (log_level >= 4) { - midi_log(iep); - log_puts(": in:"); - for (i = 0; i < icount; i++) { - log_puts(" "); - log_putx(idata[i]); - } - log_puts("\n"); - } - #endif - midi_parse(iep, idata, icount); - abuf_rdiscard(&iep->ibuf, icount); - idone += icount; - } - return idone; - } - - /* * store the given message in the output buffer */ void --- 351,362 ---- } } } + iep->tickets -= icount; + if (iep->tickets < 0) + iep->tickets = 0; } /* * store the given message in the output buffer */ void *************** *** 377,383 **** #ifdef DEBUG if (log_level >= 2) { midi_log(oep); ! log_puts(": overrun, discarding "); log_putu(oep->obuf.used); log_puts(" bytes\n"); } --- 373,379 ---- #ifdef DEBUG if (log_level >= 2) { midi_log(oep); ! log_puts(": too slow, discarding "); log_putu(oep->obuf.used); log_puts(" bytes\n"); }