123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- import math
- import json
- from padmanager import PadManager
- class InputAction(list):
- def __init__(self, js):
- super().__init__(js)
- def json(self):
- return self
- class InputActionList():
- def __init__(self, js):
- self.actions=[]
- if len(js)>0:
- if isinstance(js[0], str):
- self.actions.append(InputAction(js))
- else:
- for k in js:
- self.actions.append(k)
- def json(self):
- x=[]
- for k in self.actions:
- x.append(k)
- return x
- class InputDefinition:
- def __init__(self, js):
- self.type=js["type"]
- self.actions={}
- for k in js["actions"]:
- self.actions[k]=InputActionList(js["actions"][k])
- self.shape=js["shape"] if "shape" in js else ""
- def json(self):
- actions={}
- for k in self.actions:
- actions[k]=self.actions[k].json()
- return {
- "type" : self.type,
- "actions" : self.actions,
- "shape" : self.shape
- }
- class Pad:
- def __init__(self, js):
- self.name=js["name"]
- self.width=js["width"]
- self.height=js["height"]
- self.ports=js["ports"]
- self.inputs={}
- for k in js["inputs"]:
- self.inputs[k]=InputDefinition(js["inputs"][k])
- self.matrix=[]
- for i in range(self.width*self.height): self.matrix.append(None)
- for i in range(self.width*self.height):
- obj=js["matrix"][i]
- if obj:
- self.matrix[i]=self.inputs[obj["type"]]
- class Operation:
- def __init__(self, type, js=None):
- pass
- def json(self): raise NotImplementedError
- @staticmethod
- def parse(js):
- cl = CLASSES[js["type"]]
- return cl(js)
- class DropOperation(Operation):
- TYPE="DROP"
- def __init__(self, js):
- super().__init__(js)
- self.type=DropOperation.TYPE
- def json(self): return {"type" : DropOperation.TYPE}
- @staticmethod
- def new(): return DropOperation(None)
- def __str__(self):
- return "Drop()"
- class ReorderOperation(Operation):
- TYPE="REORDER"
- def __init__(self, js):
- super().__init__(js)
- self.type=ReorderOperation.TYPE
- if js:
- self.offset=js["offset"]
- def json(self):
- return {
- "type" : ReorderOperation.TYPE,
- "offset" : self.offset
- }
- @staticmethod
- def new(offset):
- tmp = ReorderOperation(None)
- tmp.offset=offset
- return tmp
- def __str__(self):
- return "Reorder(offset %d)" % self.offset
- class TranslateOperation(Operation):
- RELATIVE="RELATIVE"
- FIXED="FIXED"
- UNCHANGED="UNCHANGED"
- TYPE="TRANSLATE"
- def __init__(self, js):
- super().__init__(js)
- self.type=TranslateOperation.TYPE
- self.channelmode=TranslateOperation.RELATIVE
- self.keymode=TranslateOperation.RELATIVE
- self.velocitymode=TranslateOperation.RELATIVE
- self.channel=0
- self.key=0
- self.velocity=0
- if js:
- self.channelmode=js["modes"][0]
- self.keymode=js["modes"][1]
- self.velocitymode=js["modes"][2]
- self.channel=js["values"][0]
- self.key=js["values"][1]
- self.velocity=js["values"][2]
- def __str__(self):
- ch = ("=" if self.channelmode=="FIXED" else ("+" if self.channel>=0 else "")) + str(self.channel)
- key = ("=" if self.keymode=="FIXED" else ("+" if self.key>=0 else "")) + str(self.key)
- vel = ("=" if self.velocitymode=="FIXED" else ("+" if self.velocity>=0 else "")) + str(self.velocity)
- return "Translate(channel %s, key %s, velocity %s)" % (ch, key, vel)
- def json(self):
- return {
- "type" : TranslateOperation.TYPE,
- "values" : [self.channel, self.key, self.velocity],
- "modes" : [self.channelmode, self.keymode, self.velocitymode]
- }
- @staticmethod
- def new(values=[0,0,0], modes=[False,False,False]):
- _modes=["FIXED" if modes[0] else "RELATIVE","FIXED" if modes[1] else "RELATIVE",
- "FIXED" if modes[2] else "RELATIVE"]
- return TranslateOperation({ "values" : values, "modes": _modes})
- class RangeOperation(Operation):
- TYPE="RANGE"
- def __init__(self, js):
- super().__init__(js)
- self.type=RangeOperation.TYPE
- self.range=[]
- self.key=0
- self.length=12
- if js:
- self.range=js["range"]
- self.key=js["key"]
- self.length=js["length"]
- def json(self):
- return {
- "type" : RangeOperation.TYPE,
- "range" : self.range,
- "key" : self.key,
- "length" : self.length
- }
- def __str__(self):
- return "RANGE(range %s, key %d, len %d)" % (self.range, self.key, self.length)
- @staticmethod
- def new(range, key, length=12):
- tmp = RangeOperation(None)
- tmp.length=length
- tmp.range=range
- tmp.key=key
- return tmp
- CLASSES={
- TranslateOperation.TYPE : TranslateOperation,
- DropOperation.TYPE : DropOperation,
- ReorderOperation.TYPE : ReorderOperation,
- RangeOperation.TYPE : RangeOperation
- }
- class Selection:
- def __init__(self, pad, js=None):
- self.pad=pad
- self.operations=[]
- self.locked=[]
- self.init=InputActionList([])
- self.inputs=[]
- if js:
- for op in js["operations"]:
- self.operations.append(Operation.parse(op))
- self.init=InputActionList(js["init"])
- self.locked=[]
- for k in js["locked"]:
- self.locked.append(k[0]+k[1]*pad.width)
- def add_to_sel(self, i, j=0):
- if j>=0: i+=j*self.pad.width
- if not i in self.inputs:
- self.inputs.append(i)
- def remove_from_sel(self, i,j=-1):
- if j>=0: i+=j*self.pad.width
- if not i in self.inputs: return
- out=[]
- for k in self.inputs:
- if i!=k:
- out.append(k)
- self.inputs=out
- def json(self):
- ops = []
- for op in self.operations:
- ops.append(op.json())
- lock=[]
- for i in self.locked:
- lock.append([i%self.pad.width, math.floor(i/self.pad.width)])
- return {
- "operations" : ops,
- "init" : self.init.json(),
- "locked" : lock
- }
- class PadConfiguration(Pad):
- def __init__(self, js, pad=None):
- self.pad=(js["pad"] if js else pad)
- super().__init__(PadManager.read_pad(self.pad))
- self.conf_name=""
- self.description=""
- self.selections={}
- if js:
- self.conf_name = js["name"]
- self.description=js["description"]
- for k in js["selections"]:
- self.selections[k]=Selection(self, js["selections"][k])
- for i in range(len(js["matrix"])):
- sel = self.selections[js["matrix"][i]] if js["matrix"][i] else None
- if sel: sel.inputs.append(i)
- def find_selection_of(self, x, y=-1):
- if y>=0: x+=y*self.width
- for sel in self.selections:
- if x in self.selections[sel].inputs: return sel
- return None
- def new_sel(self, name):
- sel = Selection(self)
- self.selections[name]=sel
- return sel
- def sel(self, name):
- return self.selections[name]
- def add_button_to(self, selname, i, j=-1):
- if j>=0: i+=j*self.pad.width
- for k in self.selections:
- self.selections[k].remove_from_sel(i)
- self.selections[selname].add_to_sel(i)
- def remove_button_selection(self, i, j=-1):
- if j>=0: i+=j*self.pad.width
- for k in self.selections:
- self.selections[k].remove_from_sel(i)
- def rename_selection(self, old, new):
- self.selections[new]=self.selections[old]
- del self.selections[old]
- def json(self):
- mat = []
- for i in range(self.width*self.height):
- mat.append(self.find_selection_of(i))
- sels = {
- }
- for k in self.selections:
- sels[k]=self.selections[k].json()
- return {
- "name" : self.conf_name,
- "description" : self.description,
- "pad" : self.pad,
- "selections" : sels,
- "matrix" : mat
- }
- @staticmethod
- def parse(file):
- with open(file) as f:
- return PadConfiguration(json.loads(f.read()))
- @staticmethod
- def new(pad):
- return PadConfiguration(None, pad)
|