version 1.32, 2010/11/20 05:12:38 |
version 1.33, 2011/05/09 18:03:08 |
|
|
#include "conf.h" |
#include "conf.h" |
#include "dev.h" |
#include "dev.h" |
#include "midi.h" |
#include "midi.h" |
|
#include "sysex.h" |
#ifdef DEBUG |
#ifdef DEBUG |
#include "dbg.h" |
#include "dbg.h" |
#endif |
#endif |
|
|
#endif |
#endif |
|
|
/* |
/* |
|
* send a message to the given output |
|
*/ |
|
void |
|
ctl_copymsg(struct abuf *obuf, unsigned char *msg, unsigned len) |
|
{ |
|
unsigned ocount, itodo; |
|
unsigned char *odata, *idata; |
|
|
|
itodo = len; |
|
idata = msg; |
|
while (itodo > 0) { |
|
if (!ABUF_WOK(obuf)) { |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
abuf_dbg(obuf); |
|
dbg_puts(": overrun, discarding "); |
|
dbg_putu(obuf->used); |
|
dbg_puts(" bytes\n"); |
|
} |
|
#endif |
|
abuf_rdiscard(obuf, obuf->used); |
|
} |
|
odata = abuf_wgetblk(obuf, &ocount, 0); |
|
if (ocount > itodo) |
|
ocount = itodo; |
|
#ifdef DEBUG |
|
if (debug_level >= 4) { |
|
abuf_dbg(obuf); |
|
dbg_puts(": stored "); |
|
dbg_putu(ocount); |
|
dbg_puts(" bytes\n"); |
|
} |
|
#endif |
|
memcpy(odata, idata, ocount); |
|
abuf_wcommit(obuf, ocount); |
|
itodo -= ocount; |
|
idata += ocount; |
|
} |
|
} |
|
|
|
/* |
* broadcast a message to all output buffers on the behalf of ibuf. |
* broadcast a message to all output buffers on the behalf of ibuf. |
* ie. don't sent back the message to the sender |
* ie. don't sent back the message to the sender |
*/ |
*/ |
void |
void |
ctl_sendmsg(struct aproc *p, struct abuf *ibuf, unsigned char *msg, unsigned len) |
ctl_sendmsg(struct aproc *p, struct abuf *ibuf, unsigned char *msg, unsigned len) |
{ |
{ |
unsigned ocount, itodo; |
|
unsigned char *odata, *idata; |
|
struct abuf *i, *inext; |
struct abuf *i, *inext; |
|
|
for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) { |
for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) { |
inext = LIST_NEXT(i, oent); |
inext = LIST_NEXT(i, oent); |
if (i->duplex && i->duplex == ibuf) |
if (i->duplex && i->duplex == ibuf) |
continue; |
continue; |
itodo = len; |
ctl_copymsg(i, msg, len); |
idata = msg; |
|
while (itodo > 0) { |
|
if (!ABUF_WOK(i)) { |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
abuf_dbg(i); |
|
dbg_puts(": overrun, discarding "); |
|
dbg_putu(i->used); |
|
dbg_puts(" bytes\n"); |
|
} |
|
#endif |
|
abuf_rdiscard(i, i->used); |
|
} |
|
odata = abuf_wgetblk(i, &ocount, 0); |
|
if (ocount > itodo) |
|
ocount = itodo; |
|
#ifdef DEBUG |
|
if (debug_level >= 4) { |
|
abuf_dbg(i); |
|
dbg_puts(": stored "); |
|
dbg_putu(ocount); |
|
dbg_puts(" bytes\n"); |
|
} |
|
#endif |
|
memcpy(odata, idata, ocount); |
|
abuf_wcommit(i, ocount); |
|
itodo -= ocount; |
|
idata += ocount; |
|
} |
|
(void)abuf_flush(i); |
(void)abuf_flush(i); |
} |
} |
} |
} |
|
|
ctl_sendmsg(p, NULL, buf, 10); |
ctl_sendmsg(p, NULL, buf, 10); |
} |
} |
|
|
|
void |
|
ctl_msg_vol(struct aproc *p, int slot, char *msg) |
|
{ |
|
struct ctl_slot *s; |
|
|
|
s = p->u.ctl.slot + slot; |
|
msg[0] = MIDI_CTL | slot; |
|
msg[1] = MIDI_CTLVOL; |
|
msg[2] = s->vol; |
|
} |
|
|
/* |
/* |
* find the best matching free slot index (ie midi channel). |
* find the best matching free slot index (ie midi channel). |
* return -1, if there are no free slots anymore |
* return -1, if there are no free slots anymore |
|
|
{ |
{ |
int idx; |
int idx; |
struct ctl_slot *s; |
struct ctl_slot *s; |
|
unsigned char msg[sizeof(struct sysex)]; |
|
|
if (!APROC_OK(p)) { |
if (!APROC_OK(p)) { |
#ifdef DEBUG |
#ifdef DEBUG |
|
|
s->arg = arg; |
s->arg = arg; |
s->tstate = tr ? CTL_STOP : CTL_OFF; |
s->tstate = tr ? CTL_STOP : CTL_OFF; |
s->ops->vol(s->arg, s->vol); |
s->ops->vol(s->arg, s->vol); |
ctl_slotvol(p, idx, s->vol); |
ctl_msg_vol(p, idx, msg); |
|
ctl_sendmsg(p, NULL, msg, 3); |
return idx; |
return idx; |
} |
} |
|
|
|
|
} |
} |
#endif |
#endif |
p->u.ctl.slot[slot].vol = vol; |
p->u.ctl.slot[slot].vol = vol; |
msg[0] = MIDI_CTL | slot; |
ctl_msg_vol(p, slot, msg); |
msg[1] = MIDI_CTLVOL; |
|
msg[2] = vol; |
|
ctl_sendmsg(p, NULL, msg, 3); |
ctl_sendmsg(p, NULL, msg, 3); |
} |
} |
|
|
|
|
{ |
{ |
unsigned chan; |
unsigned chan; |
struct ctl_slot *slot; |
struct ctl_slot *slot; |
unsigned fps; |
struct sysex *x; |
|
unsigned fps, len; |
#ifdef DEBUG |
#ifdef DEBUG |
unsigned i; |
unsigned i; |
|
|
|
|
} |
} |
#endif |
#endif |
if ((ibuf->r.midi.msg[0] & MIDI_CMDMASK) == MIDI_CTL && |
if ((ibuf->r.midi.msg[0] & MIDI_CMDMASK) == MIDI_CTL && |
ibuf->r.midi.msg[1] == MIDI_CTLVOL) { |
(ibuf->r.midi.msg[1] == MIDI_CTLVOL)) { |
chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK; |
chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK; |
if (chan >= CTL_NSLOT) |
if (chan >= CTL_NSLOT) |
return; |
return; |
|
|
slot->ops->vol(slot->arg, slot->vol); |
slot->ops->vol(slot->arg, slot->vol); |
ctl_sendmsg(p, ibuf, ibuf->r.midi.msg, ibuf->r.midi.len); |
ctl_sendmsg(p, ibuf, ibuf->r.midi.msg, ibuf->r.midi.len); |
} |
} |
if (ibuf->r.midi.idx == 6 && |
x = (struct sysex *)ibuf->r.midi.msg; |
ibuf->r.midi.msg[0] == 0xf0 && |
len = ibuf->r.midi.idx; |
ibuf->r.midi.msg[1] == 0x7f && /* type is realtime */ |
if (x->start != SYSEX_START) |
ibuf->r.midi.msg[3] == 0x06 && /* subtype is mmc */ |
return; |
ibuf->r.midi.msg[5] == 0xf7) { /* subtype is mmc */ |
if (len < SYSEX_SIZE(empty)) |
switch (ibuf->r.midi.msg[4]) { |
return; |
case 0x01: /* mmc stop */ |
switch (x->type) { |
|
case SYSEX_TYPE_RT: |
|
if (x->id0 != SYSEX_MMC) |
|
return; |
|
switch (x->id1) { |
|
case SYSEX_MMC_STOP: |
|
if (len != SYSEX_SIZE(stop)) |
|
return; |
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 3) { |
if (debug_level >= 3) { |
abuf_dbg(ibuf); |
abuf_dbg(ibuf); |
|
|
#endif |
#endif |
ctl_stop(p); |
ctl_stop(p); |
break; |
break; |
case 0x02: /* mmc start */ |
case SYSEX_MMC_START: |
|
if (len != SYSEX_SIZE(start)) |
|
return; |
#ifdef DEBUG |
#ifdef DEBUG |
if (debug_level >= 3) { |
if (debug_level >= 3) { |
abuf_dbg(ibuf); |
abuf_dbg(ibuf); |
|
|
#endif |
#endif |
ctl_start(p); |
ctl_start(p); |
break; |
break; |
} |
case SYSEX_MMC_LOC: |
} |
if (len != SYSEX_SIZE(loc) || |
if (ibuf->r.midi.idx == 13 && |
x->u.loc.len != SYSEX_MMC_LOC_LEN || |
ibuf->r.midi.msg[0] == 0xf0 && |
x->u.loc.cmd != SYSEX_MMC_LOC_CMD) |
ibuf->r.midi.msg[1] == 0x7f && |
return; |
ibuf->r.midi.msg[3] == 0x06 && |
switch (x->u.loc.hr >> 5) { |
ibuf->r.midi.msg[4] == 0x44 && |
case MTC_FPS_24: |
ibuf->r.midi.msg[5] == 0x06 && |
fps = 24; |
ibuf->r.midi.msg[6] == 0x01 && |
break; |
ibuf->r.midi.msg[12] == 0xf7) { |
case MTC_FPS_25: |
switch (ibuf->r.midi.msg[7] >> 5) { |
fps = 25; |
case MTC_FPS_24: |
break; |
fps = 24; |
case MTC_FPS_30: |
|
fps = 30; |
|
break; |
|
default: |
|
p->u.ctl.origin = 0; |
|
return; |
|
} |
|
ctl_loc(p, |
|
(x->u.loc.hr & 0x1f) * 3600 * MTC_SEC + |
|
x->u.loc.min * 60 * MTC_SEC + |
|
x->u.loc.sec * MTC_SEC + |
|
x->u.loc.fr * (MTC_SEC / fps) + |
|
x->u.loc.cent * (MTC_SEC / 100 / fps)); |
break; |
break; |
case MTC_FPS_25: |
|
fps = 25; |
|
break; |
|
case MTC_FPS_30: |
|
fps = 30; |
|
break; |
|
default: |
|
p->u.ctl.origin = 0; |
|
return; |
|
} |
} |
ctl_loc(p, |
break; |
(ibuf->r.midi.msg[7] & 0x1f) * 3600 * MTC_SEC + |
|
ibuf->r.midi.msg[8] * 60 * MTC_SEC + |
|
ibuf->r.midi.msg[9] * MTC_SEC + |
|
ibuf->r.midi.msg[10] * (MTC_SEC / fps) + |
|
ibuf->r.midi.msg[11] * (MTC_SEC / 100 / fps)); |
|
} |
} |
} |
} |
|
|