version 1.37, 2011/10/12 07:20:04 |
version 1.38, 2011/11/15 20:41:54 |
|
|
* send the message stored in of ibuf->r.midi.msg to obuf |
* send the message stored in of ibuf->r.midi.msg to obuf |
*/ |
*/ |
void |
void |
thru_flush(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) |
thru_flush(struct abuf *ibuf, struct abuf *obuf) |
{ |
{ |
unsigned ocount, itodo; |
unsigned ocount, itodo; |
unsigned char *odata, *idata; |
unsigned char *odata, *idata; |
|
|
idata = ibuf->r.midi.msg; |
idata = ibuf->r.midi.msg; |
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 4) { |
if (debug_level >= 4) { |
aproc_dbg(p); |
abuf_dbg(obuf); |
dbg_puts(": flushing "); |
dbg_puts(": flushing "); |
dbg_putu(itodo); |
dbg_putu(itodo); |
dbg_puts(" byte message\n"); |
dbg_puts(" byte message\n"); |
|
|
if (!ABUF_WOK(obuf)) { |
if (!ABUF_WOK(obuf)) { |
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 3) { |
if (debug_level >= 3) { |
aproc_dbg(p); |
abuf_dbg(obuf); |
dbg_puts(": overrun, discarding "); |
dbg_puts(": overrun, discarding "); |
dbg_putu(obuf->used); |
dbg_putu(obuf->used); |
dbg_puts(" bytes\n"); |
dbg_puts(" bytes\n"); |
} |
} |
#endif |
#endif |
abuf_rdiscard(obuf, obuf->used); |
abuf_rdiscard(obuf, obuf->used); |
if (p->u.thru.owner == ibuf) |
if (obuf->w.midi.owner == ibuf) |
p->u.thru.owner = NULL; |
obuf->w.midi.owner = NULL; |
return; |
return; |
} |
} |
odata = abuf_wgetblk(obuf, &ocount, 0); |
odata = abuf_wgetblk(obuf, &ocount, 0); |
|
|
idata += ocount; |
idata += ocount; |
} |
} |
ibuf->r.midi.used = 0; |
ibuf->r.midi.used = 0; |
p->u.thru.owner = ibuf; |
obuf->w.midi.owner = ibuf; |
} |
} |
|
|
/* |
/* |
* send the real-time message (one byte) to obuf, similar to thrui_flush() |
* send the real-time message (one byte) to obuf, similar to thru_flush() |
*/ |
*/ |
void |
void |
thru_rt(struct aproc *p, struct abuf *ibuf, struct abuf *obuf, unsigned c) |
thru_rt(struct abuf *ibuf, struct abuf *obuf, unsigned c) |
{ |
{ |
unsigned ocount; |
unsigned ocount; |
unsigned char *odata; |
unsigned char *odata; |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 4) { |
if (debug_level >= 4) { |
aproc_dbg(p); |
abuf_dbg(obuf); |
dbg_puts(": "); |
dbg_puts(": "); |
dbg_putx(c); |
dbg_putx(c); |
dbg_puts(": flushing realtime message\n"); |
dbg_puts(": flushing realtime message\n"); |
|
|
if (!ABUF_WOK(obuf)) { |
if (!ABUF_WOK(obuf)) { |
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 3) { |
if (debug_level >= 3) { |
aproc_dbg(p); |
abuf_dbg(obuf); |
dbg_puts(": overrun, discarding "); |
dbg_puts(": overrun, discarding "); |
dbg_putu(obuf->used); |
dbg_putu(obuf->used); |
dbg_puts(" bytes\n"); |
dbg_puts(" bytes\n"); |
} |
} |
#endif |
#endif |
abuf_rdiscard(obuf, obuf->used); |
abuf_rdiscard(obuf, obuf->used); |
if (p->u.thru.owner == ibuf) |
if (obuf->w.midi.owner == ibuf) |
p->u.thru.owner = NULL; |
obuf->w.midi.owner = NULL; |
} |
} |
odata = abuf_wgetblk(obuf, &ocount, 0); |
odata = abuf_wgetblk(obuf, &ocount, 0); |
odata[0] = c; |
odata[0] = c; |
|
|
* use at most ``todo'' bytes (for throttling) |
* use at most ``todo'' bytes (for throttling) |
*/ |
*/ |
void |
void |
thru_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf, unsigned todo) |
thru_bcopy(struct abuf *ibuf, struct abuf *obuf, unsigned todo) |
{ |
{ |
unsigned char *idata; |
unsigned char *idata; |
unsigned c, icount, ioffs; |
unsigned c, icount, ioffs; |
|
|
ibuf->r.midi.msg[ibuf->r.midi.used++] = c; |
ibuf->r.midi.msg[ibuf->r.midi.used++] = c; |
ibuf->r.midi.idx++; |
ibuf->r.midi.idx++; |
if (ibuf->r.midi.idx == ibuf->r.midi.len) { |
if (ibuf->r.midi.idx == ibuf->r.midi.len) { |
thru_flush(p, ibuf, obuf); |
thru_flush(ibuf, obuf); |
if (ibuf->r.midi.st >= 0xf0) |
if (ibuf->r.midi.st >= 0xf0) |
ibuf->r.midi.st = 0; |
ibuf->r.midi.st = 0; |
ibuf->r.midi.idx = 0; |
ibuf->r.midi.idx = 0; |
} |
} |
if (ibuf->r.midi.used == MIDI_MSGMAX) { |
if (ibuf->r.midi.used == MIDI_MSGMAX) { |
if (ibuf->r.midi.used == ibuf->r.midi.idx || |
if (ibuf->r.midi.used == ibuf->r.midi.idx || |
p->u.thru.owner == ibuf) |
obuf->w.midi.owner == ibuf) |
thru_flush(p, ibuf, obuf); |
thru_flush(ibuf, obuf); |
else |
else |
ibuf->r.midi.used = 0; |
ibuf->r.midi.used = 0; |
} |
} |
} else if (c < 0xf8) { |
} else if (c < 0xf8) { |
if (ibuf->r.midi.used == ibuf->r.midi.idx || |
if (ibuf->r.midi.used == ibuf->r.midi.idx || |
p->u.thru.owner == ibuf) { |
obuf->w.midi.owner == ibuf) { |
thru_flush(p, ibuf, obuf); |
thru_flush(ibuf, obuf); |
} else |
} else |
ibuf->r.midi.used = 0; |
ibuf->r.midi.used = 0; |
ibuf->r.midi.msg[0] = c; |
ibuf->r.midi.msg[0] = c; |
|
|
common_len[c & 7] : |
common_len[c & 7] : |
voice_len[(c >> 4) & 7]; |
voice_len[(c >> 4) & 7]; |
if (ibuf->r.midi.len == 1) { |
if (ibuf->r.midi.len == 1) { |
thru_flush(p, ibuf, obuf); |
thru_flush(ibuf, obuf); |
ibuf->r.midi.idx = 0; |
ibuf->r.midi.idx = 0; |
ibuf->r.midi.st = 0; |
ibuf->r.midi.st = 0; |
ibuf->r.midi.len = 0; |
ibuf->r.midi.len = 0; |
|
|
ibuf->r.midi.idx = 1; |
ibuf->r.midi.idx = 1; |
} |
} |
} else { |
} else { |
thru_rt(p, ibuf, obuf, c); |
thru_rt(ibuf, obuf, c); |
} |
} |
} |
} |
} |
} |
|
|
inext = LIST_NEXT(i, oent); |
inext = LIST_NEXT(i, oent); |
if (ibuf->duplex == i) |
if (ibuf->duplex == i) |
continue; |
continue; |
thru_bcopy(p, ibuf, i, todo); |
thru_bcopy(ibuf, i, todo); |
(void)abuf_flush(i); |
(void)abuf_flush(i); |
} |
} |
abuf_rdiscard(ibuf, todo); |
abuf_rdiscard(ibuf, todo); |
|
|
} |
} |
|
|
void |
void |
|
thru_newout(struct aproc *p, struct abuf *obuf) |
|
{ |
|
obuf->w.midi.owner = NULL; |
|
} |
|
|
|
void |
thru_done(struct aproc *p) |
thru_done(struct aproc *p) |
{ |
{ |
timo_del(&p->u.thru.timo); |
timo_del(&p->u.thru.timo); |
|
|
thru_eof, |
thru_eof, |
thru_hup, |
thru_hup, |
thru_newin, |
thru_newin, |
NULL, /* newout */ |
thru_newout, |
NULL, /* ipos */ |
NULL, /* ipos */ |
NULL, /* opos */ |
NULL, /* opos */ |
thru_done |
thru_done |
|
|
struct aproc *p; |
struct aproc *p; |
|
|
p = aproc_new(&thru_ops, name); |
p = aproc_new(&thru_ops, name); |
p->u.thru.owner = NULL; |
|
timo_set(&p->u.thru.timo, thru_cb, p); |
timo_set(&p->u.thru.timo, thru_cb, p); |
timo_add(&p->u.thru.timo, MIDITHRU_TIMO); |
timo_add(&p->u.thru.timo, MIDITHRU_TIMO); |
return p; |
return p; |