Files
@ f6ca2b2fa154
Branch filter:
Location: light9/bcf2000.py
f6ca2b2fa154
4.1 KiB
text/x-python
72 dimmers, split up house lights
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #!/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"):
"""device was usually /dev/snd/midiC1D0 but then it showed up
once as C0D0. It should be autodetected"""
self.devPath = dev
self.dev = None
self.lastValue = {} # control name : value
self.reopen()
self.packet = ""
loop = LoopingCall(self.poll)
loop.start(.01)
def poll(self):
try:
bytes = self.dev.read(3)
except (IOError, AttributeError):
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)
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.lastValue.clear()
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"""
if self.dev is None:
return
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
#print "bcf: write %s %s" % (name, value)
self.dev.write(chr(0xb0) + chr(which[0]) + chr(int(value)))
def close(self):
self.dev.close()
self.dev = None
if __name__ == '__main__':
b = BCF2000()
reactor.run()
|