Mercurial > code > home > repos > light9
comparison bcf2000.py @ 350:c7478a778992
junky first pass at bcf2000 for keyboardcomposer
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Sun, 10 Jun 2007 07:41:48 +0000 |
parents | |
children | bd8a89743226 |
comparison
equal
deleted
inserted
replaced
349:768d0d12c3a4 | 350:c7478a778992 |
---|---|
1 #!/usr/bin/python | |
2 from __future__ import division | |
3 import math | |
4 import twisted.internet.fdesc | |
5 from twisted.internet import reactor | |
6 from twisted.internet.task import LoopingCall | |
7 | |
8 class BCF2000(object): | |
9 | |
10 control = {81 : "slider1", 82 : "slider2", 83 : "slider3", 84 : "slider4", | |
11 85 : "slider5", 86 : "slider6", 87 : "slider7", 88 : "slider8", | |
12 | |
13 1 : "knob1", 2 : "knob2", 3 : "knob3", 4 : "knob4", | |
14 5 : "knob5", 6 : "knob6", 7 : "knob7", 8 : "knob8", | |
15 | |
16 33 : "button-knob1", 34 : "button-knob2", | |
17 35 : "button-knob3", 36 : "button-knob4", | |
18 37 : "button-knob5", 38 : "button-knob6", | |
19 39 : "button-knob7", 40 : "button-knob8", | |
20 | |
21 65 : "button-upper1", 66 : "button-upper2", | |
22 67 : "button-upper3", 68 : "button-upper4", | |
23 69 : "button-upper5", 70 : "button-upper6", | |
24 71 : "button-upper7", 72 : "button-upper8", | |
25 73 : "button-lower1", 74 : "button-lower2", | |
26 75 : "button-lower3", 76 : "button-lower4", | |
27 77 : "button-lower5", 78 : "button-lower6", | |
28 79 : "button-lower7", 80 : "button-lower8", | |
29 89 : "button-corner1", 90 : "button-corner2", | |
30 91 : "button-corner3", 92 : "button-corner4", | |
31 } | |
32 | |
33 def __init__(self, dev="/dev/snd/midiC1D0"): | |
34 self.devPath = dev | |
35 self.dev = None | |
36 self.reopen() | |
37 self.lastValue = {} # control name : value | |
38 self.packet = "" | |
39 loop = LoopingCall(self.poll) | |
40 loop.start(.02) | |
41 | |
42 def poll(self): | |
43 try: | |
44 bytes = self.dev.read(3) | |
45 except IOError, e: | |
46 return | |
47 if len(bytes) == 0: | |
48 print "midi stall, reopen slider device" | |
49 self.reopen() | |
50 return | |
51 self.packet += bytes | |
52 if len(self.packet) == 3: | |
53 p = self.packet | |
54 self.packet = "" | |
55 self.packetReceived(p) | |
56 | |
57 return | |
58 | |
59 while 1: | |
60 packet = self.dev.read(3) | |
61 while len(packet) < 3: | |
62 if len(packet) == 0: | |
63 self.reopen() | |
64 packet += self.dev.read(3 - len(packet)) | |
65 | |
66 def packetReceived(self, packet): | |
67 b0, which, value = [ord(b) for b in packet] | |
68 if b0 != 0xb0: | |
69 return | |
70 if which in self.control: | |
71 name = self.control[which] | |
72 if name.startswith("button-"): | |
73 value = value > 0 | |
74 self.lastValue[name] = value | |
75 self.valueIn(name, value) | |
76 else: | |
77 print "unknown control %s to %s" % (which, value) | |
78 | |
79 def reopen(self): | |
80 if self.dev is not None: | |
81 try: | |
82 self.dev.close() | |
83 except IOError: | |
84 pass | |
85 | |
86 self.dev = open(self.devPath, "r+") | |
87 twisted.internet.fdesc.setNonBlocking(self.dev) | |
88 | |
89 def valueIn(self, name, value): | |
90 """override this with your handler for when events come in | |
91 from the hardware""" | |
92 print "slider %s to %s" % (name, value) | |
93 if name == 'slider1': | |
94 for x in range(2,8+1): | |
95 v2 = int(64 + 64 * math.sin(x / 3 + value / 10)) | |
96 self.valueOut('slider%d' % x, v2) | |
97 for x in range(1,8+1): | |
98 self.valueOut('button-upper%s' % x, value > x*15) | |
99 self.valueOut('button-lower%s' % x, value > (x*15+7)) | |
100 | |
101 def valueOut(self, name, value): | |
102 """call this to send an event to the hardware""" | |
103 value = int(value) | |
104 if self.lastValue.get(name) == value: | |
105 return | |
106 self.lastValue[name] = value | |
107 which = [k for k,v in self.control.items() if v == name] | |
108 assert len(which) == 1, "unknown control name %r" % name | |
109 if isinstance(value, bool): | |
110 value = value * 127 | |
111 self.dev.write(chr(0xb0) + chr(which[0]) + chr(int(value))) | |
112 | |
113 | |
114 if __name__ == '__main__': | |
115 b = BCF2000() | |
116 reactor.run() |