#!/usr/bin/python # Type of LED Functions. # 0=off, # 1=green, # 2=green blink, # 3=red, # 4=red blink, # 5=yellow, # 6=yellow blink, # 7-127=green, # Type of LED Ring Functions # 0=off, # 1=Single, # 2=Volume Style, # 3=Pan Style, # 4-127=Single import logging import sys import time import rtmidi import random from rtmidi.midiutil import open_midioutput from rtmidi.midiconstants import NOTE_OFF, NOTE_ON from simplemidi.midiio import MidiInputPort, MidiOutputPort from simplemidi.midimessage import MidiType from simplemidi.alsaconnector import AlsaConnector from simplemidi.options import * """ Classe qui represente un bouton """ class Button: def __init__(self, port, index, channel=1): self.channel=channel # canal midi : int self.oport=port # port de sortie : MidiOut self.index=index # index (=note) du bouton : int Button.LED_UNKNOWN=-1 # etat du bouton (couleur de la led) incoonu Button.OFF=0 self.state=Button.LED_UNKNOWN # etat de la led : int self.mindata=0 #valeur minimal que le bouton peut predre : int self.maxdata=0 #valeur max que le bouton peut predre : int self.values=[] # liste des valeurs que le bouton peut predre : int self.lastState=0 # etat précédent (pour la fonction toggle()) : int def onNoteOn(self, channel, idx, val): pass def onNoteOff(self, channel, idx, val): pass """ Envoi un note on pour changer de couleur dat: int: couleur a mettre """ def send(self, data): if data<=self.maxdata and data>=self.mindata: self.state=data if data!=Button.OFF and (data in self.values): self.lastState=data self.oport.noteOn(1, self.index, data) time.sleep(0.00001) """ Demande au bouton de passe à la couleur suivante """ def next(self): if self.state==Button.LED_UNKNOWN: return x=self.state+1 if x>self.maxdata: x=self.mindata self.send(x) """ Demande au bouton de passe à la couleur précédente """ def prev(self): if self.state==Button.LED_UNKNOWN: return x=self.state-1 if x0: if (isinstance(data[0], list) or isinstance(data[0], tuple)): end=(start[0]+len(data[0]), start[1]+len(data[1])) data=Pad.matrixToArray(data) if end==None: end=(self.ledbuttonsWidth, self.ledbuttonsHeight) w=end[0]-start[0] realw= w if start[0]+w= realw: continue n=(j-start[1])*w+(i-start[0]) self[i,j]=data[n] def fill(self, value, matrixOnly=True): if matrixOnly: x=[] for i in range(self.ledbuttonsWidth*self.ledbuttonsHeight): x.append(value) self.map(x) else: for k in self.keys(): self[k]=value def blink(self, value, n=2): self.fill(value) time.sleep(n/2.0) def loadingScreen(self, tt): t=tt/9.0 for i in range(64,64+8): self[i].on() time.sleep(t) self[i].off() for k in range(2): for i in range(64,64+8): self[i].on() time.sleep(t/3) for i in range(64,64+8): self[i].off() if k<2: time.sleep(t/3) def showText(self, text): mat=text.getDataToShow() self.mapSubRect(mat, text.pos, (text.dim[0]+text.pos[0],text.dim[1]+text.pos[1])) text.step() """ Mappe un vecteur ou une matrice tous les boutons de notes """ def map(self, data): first=self.ledbuttons[0].index self.mapSubRect(data, (int(first/self.ledbuttonsWidth),first%self.ledbuttonsWidth)) #liste des id des boutons def keys(self): return self.ledbuttons.keys() # transforeme une coordonnée d'uune matrice ou d'un vecteur en une coordonée d'un vecteur def getIndex(self, x, y=-1): return x if y<0 else x+y*self.ledbuttonsWidth # renvoie le bouton a l'adresse x, y def getButton(self, x, y=-1): return self.ledbuttons[self.getIndex(x,y)] def __getitem__(self,key): if isinstance(key, tuple): return self.getButton(key[0], key[1]) else: return self.getButton(key) def __setitem__(self,key,value): if isinstance(key, tuple): x=self.getButton(key[0], key[1]) if x: x.send(value) else: x=self.getButton(key).send(value) if x: x.send(value) def connectOut(self, port): port=AlsaConnector.portAuto(port) self.oport.connect(port) INFO("Connected to input port: "+str(port)+"\n") def connectIn(self, port): port=AlsaConnector.portAuto(port) self.iport.connect(port) INFO("Connected to output port: "+str(port)+"\n") def close(self): self.oport.close() self.iport.close() TEXT_DATA={ 'A': [[1,1,1,0], [1,0,1,0], [1,1,1,0], [1,0,1,0]], 'R': [[1,1,1,0], [1,1,0,0], [1,0,1,0], [1,0,1,0]], 'T': [[1,1,1,0], [0,1,0,0], [0,1,0,0], [0,1,0,0]], 'Y': [[1,0,1,0], [1,0,1,0], [0,1,0,0], [0,1,0,0]], 'G': [[1,1,1,0], [1,0,0,0], [1,0,1,0], [1,1,1,0]], 'I': [[0,1,0,0], [0,1,0,0], [0,1,0,0], [0,1,0,0]], 'L': [[0,1,0,0], [0,1,0,0], [0,1,0,0], [0,1,1,0]], 'N': [[1,0,1,0], [1,1,1,0], [1,1,1,0], [1,0,1,0]], 'O': [[1,1,1,0], [1,0,1,0], [1,0,1,0], [1,1,1,0]], 'C': [[1,1,1,0], [1,0,0,0], [1,0,0,0], [1,1,1,0]], 'S': [[1,1,1,0], [1,1,1,0], [0,0,1,0], [1,1,1,0]], ' ': [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]], ':': [[0,0,0,0], [0,1,0,0], [0,0,0,0], [0,1,0,0]], '0': [[1,1,1,0], [1,0,1,0], [1,0,1,0], [1,1,1,0]], '1': [[0,1,0,0], [1,1,0,0], [0,1,0,0], [0,1,0,0]], '2': [[1,1,1,0], [0,0,1,0], [0,1,0,0], [1,1,1,0]], '3': [[0,1,1,0], [0,0,1,0], [0,1,1,0], [0,1,1,0]], '4': [[0,0,1,0], [0,1,1,0], [1,1,1,1], [0,0,1,0]], '5': [[1,1,1,0], [1,0,0,0], [1,1,1,0], [1,1,1,0]], '6': [[0,1,1,0], [0,1,0,0], [0,1,1,0], [0,1,1,0]], '7': [[1,1,0,0], [0,1,0,0], [1,1,1,0], [0,1,0,0]], '8': [[1,1,1,0], [1,1,1,0], [1,0,1,0], [1,1,1,0]], '9': [[0,1,1,0], [0,1,1,0], [0,0,1,0], [0,1,1,0]], 'M': [[1,0,1,0], [1,1,1,0], [1,1,1,0], [1,1,1,0]], 'E': [[0,1,1,0], [0,1,1,0], [0,1,0,0], [0,1,1,0]], 'V': [[1,0,1,0], [1,0,1,0], [1,0,1,0], [0,1,0,0]], '!': [[0,1,0,0], [0,1,0,0], [0,0,0,0], [0,1,0,0]], '?': [[1,1,1,0], [0,1,1,0], [0,0,0,0], [0,1,0,0]] } """ Classe qui gère les donnes a afficher pour afficher du texte défilant """ class Text: def __init__(self, txt, dim, pos=(0,0)): self.pos=pos # position : (x, y) self.dim=dim # dimension : (w,h) self.txt=txt.upper() # texte a afficher : str self.len=len(txt)*4 # longueur en cases (pas en caracteres) : int self.matrix=[] # toutes les données : Matrix [ [..] .. [..] ] for y in range(4): for x in range(self.len): self.matrix.append(0) self.offset=-1 # décalage de la partie a afficher actuellement : in self.color=1 # couleur du text : int self.backgroundcolor=0 #couleur du fond : int for i in range(len(self.txt)): self.map(self.txt[i], i*4) """ Récupère un vecteur de bit a afficher pour une lettre color: int : Couleur du texte backcolor: int : couleur du fond """ @staticmethod def letterVector(char, color=1, backcolor=0): x=[] c=TEXT_DATA[char] for j in reversed(range(4)): for i in range(4): x.append(color if c[j][i]>0 else backcolor) return x """ Map un vecteur ou une matrix dans les données a afficher """ def map(self, char, off): c=TEXT_DATA[char] for j in reversed(range(4)): for i in range(off, off+4): self.matrix[i+(3-j)*self.len]=c[j][i-off] """ Change la couleur du text c: int : Couleur du texte """ def setColor(self, c): self.color=c """ Change la couleur du fond c: int : Couleur du fond """ def setBackgroundColor(self, c): self.backgroundcolor=c """ Recupere le vecteur a mapper sur le pad """ def getDataToShow(self): out=[] for j in range(4): for i in range(self.offset, self.offset+self.dim[0]): i=i%self.len xx=self.matrix[i+j*self.len] x= self.color if xx>0 else self.backgroundcolor out.append(x) return out """ Donne le nombre d'étape pour afficher completement le text n fois n: (int = 1) : Nombre de fois a afficher """ def stepCount(self, n=1): return (self.len-self.dim[0]+1)*n """ Décale d'une position (case) le texte """ def step(self): self.offset=(self.offset+1)%self.len import os def setRealtime(rt=os.SCHED_FIFO): try: os.sched_setscheduler(0, rt, os.sched_param(0)) return True except Exception as err: ERR("Impossible de passer en temps-réel: "+str(err)) return False