Files @ a6662d61ebcd
Branch filter:

Location: light9/bcf2000.py - annotation

Drew Perttula
SC, KC, CC now run and seem to load and save ok. CC does not have any rdf for its data files
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
c7478a778992
#!/usr/bin/python
from __future__ import division
import math
import twisted.internet.fdesc
from twisted.internet import reactor
from twisted.internet.task import LoopingCall

class BCF2000(object):

    control = {81 : "slider1", 82 : "slider2", 83 : "slider3", 84 : "slider4",
               85 : "slider5", 86 : "slider6", 87 : "slider7", 88 : "slider8",

                1 : "knob1",  2 : "knob2",  3 : "knob3",  4 : "knob4",
                5 : "knob5",  6 : "knob6",  7 : "knob7",  8 : "knob8",

               33 : "button-knob1", 34 : "button-knob2",
               35 : "button-knob3", 36 : "button-knob4",
               37 : "button-knob5", 38 : "button-knob6",
               39 : "button-knob7", 40 : "button-knob8",
               
               65 : "button-upper1",  66 : "button-upper2",
               67 : "button-upper3",  68 : "button-upper4",
               69 : "button-upper5",  70 : "button-upper6",
               71 : "button-upper7",  72 : "button-upper8",
               73 : "button-lower1",  74 : "button-lower2",
               75 : "button-lower3",  76 : "button-lower4",
               77 : "button-lower5",  78 : "button-lower6",
               79 : "button-lower7",  80 : "button-lower8",
               89 : "button-corner1", 90 : "button-corner2",
               91 : "button-corner3", 92 : "button-corner4",
               }
               
    def __init__(self, dev="/dev/snd/midiC1D0"):
        self.devPath = dev
        self.dev = None
        self.reopen()
        self.lastValue = {} # control name : value
        self.packet = ""
        loop = LoopingCall(self.poll)
        loop.start(.02)

    def poll(self):
        try:
            bytes = self.dev.read(3)
        except IOError, e:
            return
        if len(bytes) == 0:
            print "midi stall, reopen slider device"
            self.reopen()
            return
        self.packet += bytes
        if len(self.packet) == 3:
            p = self.packet
            self.packet = ""
            self.packetReceived(p)

        return
        
        while 1:
            packet = self.dev.read(3)
            while len(packet) < 3:
                if len(packet) == 0:
                    self.reopen()
                packet += self.dev.read(3 - len(packet))

    def packetReceived(self, packet):
        b0, which, value = [ord(b) for b in packet]
        if b0 != 0xb0:
            return
        if which in self.control:
            name = self.control[which]
            if name.startswith("button-"):
                value = value > 0
            self.lastValue[name] = value
            self.valueIn(name, value)
        else:
            print "unknown control %s to %s" % (which, value)

    def reopen(self):
        if self.dev is not None:
            try:
                self.dev.close()
            except IOError:
                pass

        self.dev = open(self.devPath, "r+")
        twisted.internet.fdesc.setNonBlocking(self.dev)
                    
    def valueIn(self, name, value):
        """override this with your handler for when events come in
        from the hardware"""
        print "slider %s to %s" % (name, value)
        if name == 'slider1':
            for x in range(2,8+1):
                v2 = int(64 + 64 * math.sin(x / 3 + value / 10))
                self.valueOut('slider%d' % x, v2)
            for x in range(1,8+1):
                self.valueOut('button-upper%s' % x, value > x*15)
                self.valueOut('button-lower%s' % x, value > (x*15+7))

    def valueOut(self, name, value):
        """call this to send an event to the hardware"""
        value = int(value)
        if self.lastValue.get(name) == value:
            return
        self.lastValue[name] = value
        which = [k for k,v in self.control.items() if v == name]
        assert len(which) == 1, "unknown control name %r" % name
        if isinstance(value, bool):
            value = value * 127
        self.dev.write(chr(0xb0) + chr(which[0]) + chr(int(value)))
        

if __name__ == '__main__':
    b = BCF2000()
    reactor.run()