#!/usr/bin/python import copy from .midimessage import MidiType from .utils import * class MidiEventTrigger: NOTE=1 CONTROL=2 PROGRAM=4 FILTER_ALL_KEY=-1 def __init__(self, param): if param==None: self._initNone() elif isinstance(param, (tuple, list)): self._initTuple(param) elif isinstance(param, int): self._initTuple([param]) elif isinstance(param, MidiEventTrigger): self._initCopy(param) def _initNone(self): self._init() """ () -> déclenchement pour toutes les evenemnts parmis NOTE, CONTROL et PROGRAM (TYPE) (TYPE, CHANNEL, NOTE) (TYPE, CHANNEL, NOTE, FORWARD) (TYPE, CHANNEL, NOTE, FORWARD, CALLBACK [, DATA]) TYPE: flags parmis NOTE, CONTROL, PROGRAM (qui sera une condition necessaire au déclenchement) CHANNEL: le canal pour le déclenchement none ou vide: declenchement pour toutes les valeurs int: declenchement pour une valeur array: declenchement pour toutes les valeurs de la liste tuple: declenchement pour l'interval (x,y) avec x ET y inclus NOTE: la clé de la Note du Program ou Control pour le déclenchement none ou vide: declenchement pour toutes les valeurs int: declenchement pour une valeur array: declenchement pour toutes les valeurs de la liste tuple: declenchement pour l'interval (x,y) avec x ET y inclus FORWARD: Uen fois l'élément traité doit il etre réinjecter en canal de sortie ? True ou vide: Oui None ou False: Non CALLBACK et DATA: callback appelé en cas de céclenchement de la forem fct(msg, data) """ def _initTuple(self, t): self._init(*t) def _initCopy(self, t): _init(t.type, copy.copy(t.channel), copy.copy(t.key), t.forward) def _init(self, t=NOTE|CONTROL|PROGRAM, ch=None, k=None, f=True, cb=None, data=None ): self.channel=self.FILTER_ALL_KEY self.key=self.FILTER_ALL_KEY self.forward=True self.type=t if isinstance(ch, list): self.channel=ch elif isinstance(ch, tuple): self.channel=[] for i in range(ch[0], ch[1]+1): self.channel.append(i) if isinstance(k, list): self.key=k elif isinstance(k, tuple): self.key=[] for i in range(k[0], k[1]+1): self.key.append(i) self.forward=f self.callback=cb self.callbackData=data def trigger(self, msg): if self.callback: self.callback(msg, self.callbackData) def filter(self, _msg, out): msg=_msg[1] delta=_msg[0] t=msg.getType() if t!=MidiType.NOTE_ON and t!=MidiType.NOTE_OFF and \ t!=MidiType.PROGRAM_CHANGE and t!=MidiType.CONTROL_CHANGE: return False #test du type lt=[] if self.type & self.NOTE: lt+=[MidiType.NOTE_ON, MidiType.NOTE_OFF] if self.type & self.CONTROL: lt+=[MidiType.CONTROL_CHANGE] if self.type & self.PROGRAM: lt+=[MidiType.PROGRAM_CHANGE] ok=False for tt in lt: if tt==t: ok=True break if not ok: return False if self.key!=None and self.key!=-1 and not (msg.key in self.key): return False if self.channel!=None and self.channel!=-1 and not (msg.key in self.channel): return False if out!=None and self.forward: out.send(msg) print(msg) self.trigger(msg) return True class MidiMultiTrigger: """ param={ id_1 : PARAM_TO_MIDI_EVENT_TRIGGER, id_2 : PARAM_TO_MIDI_EVENT_TRIGGER, ... id_n : PARAM_TO_MIDI_EVENT_TRIGGER, } """ def __init__(self, param={}): if not isinstance(param, dict): raise Exception("MidiMultiTrigger expects an dict argument") self.data={} for i in param.keys(): self.addTrigger(i, param[i]) def addTrigger(self, name, param): self.data[name]=MidiEventTrigger(param) """ names: None ou une liste des id a tester renvoie une liste des declenchements """ def filter(self, msg, out, names=None): ret=[] toTest=self.data.keys() if names!=None: toTest=names for i in toTest: if self.data[i].filter(msg, out): ret.append(i) return ret