Ryan, > When we're rehearsing with an actual Bass player, I'd like to turn off > the Bass line and let the real Bass player play over the top (I realise > this last case is a little different, but it would be good if this > feature were also integrated into the same tool). I think it would be easier just to disconnect the bassline in kaconnect when the bass player is present. > I'm imagining the script/program needs to interpret the midi data in > order to route it. Is that a simple matter or a difficult one? Quite simple. A proof-of-concept implementation is attached. It's sort of crude, but you can glean the basic technique from it. Close to the top you'll find the configuration: It consists of a number of lists of sequencer clients, one for the input source, and one for each MIDI channel. In such a list, the more desirable sound sources are listed first. The tool will create one output port for each channel that's listed, plus one output port that'll catch everything that's not routed to any of the other ports. The names of clients don't have to be exact; capitalization doesn't matter, and it's enough to give a substring of the name you're after (as long as it's long enough to distinguish it from other names). I believe this is the basic functionality you're after. Let me know if you have any questions or comments. Peter PS: You'll need my PySeq library to run this: http://www.math.tu-berlin.de/~brinkman/software/pyseq/ -------------- next part -------------- from pyseq import * import time import sys SOURCE=[("mondrian", 0)] TARGETS={} TARGETS[0]=[("timidity", 0)] # default target, port; required TARGETS[1]=[("external rhodes", 0), ("timidity", 0)] # channel 1 TARGETS[2]=[("external bass", 0), ("timidity", 0)] # channel 2 TARGETS[10]=[("external drums", 0), ("timidity", 0)] # channel 10 class MidiRouter(PySeq): def __init__(self): PySeq.__init__(self, "MidiRouter") clin, dummy=getClients(SND_SEQ_PORT_CAP_SUBS_READ) clout, dummy=getClients(SND_SEQ_PORT_CAP_SUBS_WRITE) self.iport=self.createInPort() cl, pt=self.findMatch(clin, SOURCE) if cl!=None: self.connectFrom(self.iport, cl, pt) else: self.warn('no matching client: %s' % `SOURCE`) self.oports={} for k in TARGETS.keys(): self.oports[k]=self.createOutPort() cl, pt=self.findMatch(clout, TARGETS[k]) if cl!=None: self.connectTo(self.oports[k], cl, pt) else: self.warn('no matching client: %s' % `TARGETS[k]`) def findMatch(self, cls, lst): for subname, pt in lst: subname=subname.lower() for clid, clname, pts in cls: clname=clname.lower() pts=[p[0] for p in pts] if clname.find(subname)>=0: if pt in pts: return clid, pt else: self.warn('clname: desired port %d not available' % pt) return clid, pts[0] return None, None def warn(self, s): sys.stderr.write(s+'\n') def callback(self, ev): try: ch=dat.getData().channel+1 except: ch=0 ev.sendNow(self, self.oports[ch]) return 1 if __name__=='__main__': mr=MidiRouter() MidiThread(mr).start() while 1: time.sleep(1)