Mercurial > code > home > repos > light9
view bcf2000.py @ 2405:69ca2b2fc133
overcomplicated attempt at persisting the pane layout in the rdf graph
this was hard because we have to somehow wait for the graph to load before config'ing the panes
author | drewp@bigasterisk.com |
---|---|
date | Fri, 17 May 2024 16:58:26 -0700 |
parents | 02eb0e99bba5 |
children |
line wrap: on
line source
#!/usr/bin/python import math import twisted.internet.fdesc from twisted.internet import reactor from twisted.internet.task import LoopingCall from typing import Dict 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/midiC2D0"): """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: Dict[str, int] = {} # control name : value self.reopen() self.packet = b"" loop = LoopingCall(self.poll) loop.start(.01) def poll(self): try: newData = self.dev.read(3) except (IOError, AttributeError): return if newData is None: return self.packet += newData if len(self.packet) == 3: p = self.packet self.packet = b"" self.packetReceived(p) def packetReceived(self, packet): b0, which, value = 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, "rb+", buffering=0) 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 list(self.control.items()) if v == name] assert len(which) == 1, "unknown control name %r" % name if name.startswith('button-'): value = value * 127 #print "bcf: write %s %s" % (name, value) self.dev.write(bytes([0xb0, which[0], int(value)])) def close(self): self.dev.close() self.dev = None if __name__ == '__main__': b = BCF2000() reactor.run()