[linux-audio-user] Managing instruments

Peter Brinkmann brinkman at math.TU-Berlin.DE
Mon Aug 1 10:20:50 EDT 2005


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)



More information about the linux-audio-user mailing list