miredis/libs/midix.py

1043 lines
26 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Midi3 light version for soundt/Jamidi/clapt
v0.7.0
Midi Handler :
- Hook to the MIDI host
- Enumerate connected midi devices and spawn a process/device to handle incoming events
by Sam Neurohack
from /team/laser
Midi conversions from https://github.com/craffel/pretty-midi
"""
import time
from threading import Thread
import rtmidi
from rtmidi.midiutil import open_midiinput
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE, TIMING_CLOCK, SONG_CONTINUE, SONG_START, SONG_STOP)
import mido
from mido import MidiFile
import traceback
import weakref
import sys
from sys import platform
import os
import re
from collections import deque
from libs import log
import json
oscIP = "127.0.0.1"
oscPORT = 8000
is_py2 = sys.version[0] == '2'
if is_py2:
from queue import Queue
from OSC import OSCServer, OSCClient, OSCMessage
else:
from queue import Queue
from OSC3 import OSCServer, OSCClient, OSCMessage
print("")
midiname = ["Name"] * 16
midiport = [rtmidi.MidiOut() for i in range(16) ]
OutDevice = []
InDevice = []
midisync = True
debug = True
# max 16 midi port array
midinputsname = ["Name"] * 16
midinputsqueue = [Queue() for i in range(16) ]
midinputs = []
# False = server / True = Client
clientmode = False
#Mser = False
MidInsNumber = 0
clock = mido.Message(type="clock")
start = mido.Message(type ="start")
stop = mido.Message(type ="stop")
ccontinue = mido.Message(type ="continue")
reset = mido.Message(type ="reset")
songpos = mido.Message(type ="songpos")
nocolor = 64
green = 16
yellow = 127
red = 3
#mode = "maxwell"
'''
print "clock",clock)
print "start",start)
print "continue", ccontinue)
print "reset",reset)
print "sonpos",songpos)
'''
try:
input = raw_input
except NameError:
# Python 3
Exception = Exception
STATUS_MAP = {
'noteon': NOTE_ON,
'noteoff': NOTE_OFF,
'programchange': PROGRAM_CHANGE,
'controllerchange': CONTROLLER_CHANGE,
'pitchbend': PITCH_BEND,
'polypressure': POLY_PRESSURE,
'channelpressure': CHANNEL_PRESSURE
}
PadLeds = [0] * 64
PadTops= [0] * 8
PadRights= [0] * 8
LaunchLedMatrix = [(0,1,2,3,4,5,6,7),(16,17,18,19,20,21,22,23),(32,33,34,35,36,37,38,39),(48,49,50,51,52,53,54,55),(64,65,66,67,68,69,70,71),(80,81,82,83,84,85,86,87),(96,97,98,99,100,101,102,103),(112,113,114,115,116,117,118,119)]
LaunchRight = (8,24,40,56,72,88,104,120)
# CC
LaunchTop = (104,105,106,107,108,109,110,111)
PadTop = [0,0,0,0,0,0,0,0]
PadRight = [0,0,0,0,0,0,0,0]
PadMatrix = [0] * 64
matrix1 = [1,1]
matrix2 = [1,1]
matrix3 = [1,1]
TopSelection = [0] *8
def SendOSC(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
osclientlj = OSCClient()
osclientlj.connect((oscIP, oscPORT))
try:
osclientlj.sendto(oscmsg, (oscIP, oscPORT ))
oscmsg.clearData()
except:
log.err('Connection to OSC server refused : died ?')
pass
#time.sleep(0.001
def SendUI(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
osclientlj = OSCClient()
osclientlj.connect((TouchOSCIP, TouchOSCPort))
#print("MIDI Aurora sending UI :", oscmsg, "to",TouchOSCIP,":",TouchOSCPort)
try:
osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort))
oscmsg.clearData()
except:
log.err('Connection to Aurora UI refused : died ?')
pass
#time.sleep(0.001
# Ask redis for a given key
def fromKey(keyname):
return r.get(keyname)
#
# Write to redis key
def toKey(keyname,keyvalue):
#print(keyname,keyvalue)
# Store encoded data in Redis
return r.set(keyname,keyvalue)
def toKeyevent(eventname):
print("redis midi event key :", eventname)
r.publish("/midi/last_event", eventname)
def GetTime():
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
notes = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
def midi2note(midinote):
print("midinote",midinote, "note", notes[midinote%12]+str(round(midinote/12)))
return notes[midinote%12]+str(round(midinote/12))
def note2midi(note_name):
"""Converts a note name in the format
``'(note)(accidental)(octave number)'`` (e.g. ``'C#4'``) to MIDI note
number.
``'(note)'`` is required, and is case-insensitive.
``'(accidental)'`` should be ``''`` for natural, ``'#'`` for sharp and
``'!'`` or ``'b'`` for flat.
If ``'(octave)'`` is ``''``, octave 0 is assumed.
Parameters
----------
note_name : str
A note name, as described above.
Returns
-------
note_number : int
MIDI note number corresponding to the provided note name.
Notes
-----
Thanks to Brian McFee.
"""
# Map note name to the semitone
pitch_map = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
# Relative change in semitone denoted by each accidental
acc_map = {'#': 1, '': 0, 'b': -1, '!': -1}
# Reg exp will raise an error when the note name is not valid
try:
# Extract pitch, octave, and accidental from the supplied note name
match = re.match(r'^(?P<n>[A-Ga-g])(?P<off>[#b!]?)(?P<oct>[+-]?\d+)$',
note_name)
pitch = match.group('n').upper()
offset = acc_map[match.group('off')]
octave = int(match.group('oct'))
except:
raise ValueError('Improper note format: {}'.format(note_name))
# Convert from the extrated ints to a full note number
return 12*(octave + 1) + pitch_map[pitch] + offset
def hz2midi(frequency):
"""Convert a frequency in Hz to a (fractional) note number.
Parameters
----------
frequency : float
Frequency of the note in Hz.
Returns
-------
note_number : float
MIDI note number, can be fractional.
"""
# MIDI note numbers are defined as the number of semitones relative to C0
# in a 440 Hz tuning
return 12*(np.log2(frequency) - np.log2(440.0)) + 69
def midi2hz(note_number):
"""Convert a (fractional) MIDI note number to its frequency in Hz.
Parameters
----------
note_number : float
MIDI note number, can be fractional.
Returns
-------
note_frequency : float
Frequency of the note in Hz.
"""
# MIDI note numbers are defined as the number of semitones relative to C0
# in a 440 Hz tuning
return 440.0*(2.0**((note_number - 69)/12.0))
# /cc cc number value
def cc(midichannel, ccnumber, value, mididest):
if debug == True:
print("Midix sending Midi channel", midichannel, "cc", ccnumber, "value", value, "to", mididest)
MidiMsg([CONTROLLER_CHANGE+midichannel-1, ccnumber, value], mididest)
#
# MIDI Startup and handling
#
mqueue = Queue()
inqueue = Queue()
bpm = 0
running = True
samples = deque()
last_clock = None
#
# Events from Generic MIDI Handling
#
def MidinProcess(inqueue, portname):
inqueue_get = inqueue.get
bpm = 0
samples = deque()
last_clock = None
while True:
time.sleep(0.001)
msg = inqueue_get()
#print("")
#print("Generic from", portname,"msg : ", msg)
# NOTE ON message on all midi channels
if NOTE_ON -1 < msg[0] < 160 and msg[2] !=0 :
MidiChannel = msg[0]-144
MidiNote = msg[1]
MidiVel = msg[2]
print()
print("NOTE ON :", "Channel", MidiChannel, "note :", MidiNote, 'velocity :', MidiVel )
# redis key : "/midi/noteon/midichannel" value : "note/velocity"
if r.set("/midi/noteon/"+str(MidiChannel), str(MidiNote)+"/"+str(MidiVel))==True:
print("redis :", "/midi/noteon/"+str(MidiChannel)+" : "+ str(MidiNote)+"/"+str(MidiVel))
NoteOn(MidiNote, MidiVel, "pads" , midichannel=MidiChannel)
# OSC : /midi/noteon midichannel note velocity
SendOSC("/midi/noteon",[MidiChannel, msg[1], msg[2]])
print("osc :","/midi/noteon/",[MidiChannel, msg[1], msg[2]])
toKeyevent("/midi/noteon/"+str(MidiChannel)+"/"+str(MidiNote)+"/"+str(MidiVel))
'''
# Sampler mode : note <63 launch snare.wav / note > 62 kick.wav
if MidiNote < 63 and MidiVel >0:
if platform == 'darwin':
os.system("afplay snare.wav")
else:
os.system("aplay snare.wav")
if MidiNote > 62 and MidiVel >0:
if platform == 'darwin':
os.system("afplay kick.wav")
else:
os.system("aplay kick.wav")
'''
# NOTE OFF or Note with 0 velocity on all midi channels
if NOTE_OFF -1 < msg[0] < 145 or (NOTE_OFF -1 < msg[0] < 160 and msg[2] == 0):
if msg[0] > 143:
MidiChannel = msg[0]-144
else:
MidiChannel = msg[0]-128
MidiNote = msg[1]
print("NOTE_off channel :", MidiChannel, "note :", MidiNote)
NoteOff(MidiNote, "pads" , midichannel=MidiChannel)
# redis key : "/midi/noteon/midichannel" value : "note"
if r.set("/midi/noteoff/"+str(MidiChannel), str(MidiNote)) ==True:
print("redis :", "/midi/noteoff/"+str(MidiChannel)+" : "+ str(MidiNote))
# OSC : /midi/noteoff midichannel note
SendOSC("/midi/noteoff",[MidiChannel, msg[1]])
print('osc :', "/midi/noteoff",[MidiChannel, msg[1]])
# # CC on all Midi Channels
if CONTROLLER_CHANGE -1 < msg[0] < 192:
MidiChannel = msg[0]-175
cc(MidiChannel, msg[1], msg[2], "pads" )
#print("channel", MidiChannel, "CC :", msg[1], msg[2])
print("CC channel : "+str(msg[0]-175-1)+" CC :"+str(msg[1])+" value : "+str(msg[2]))
toKeyevent("/midi/cc/"+str(MidiChannel)+"/"+str(msg[1])+"/"+str(msg[2]))
# redis key : "/midi/cc/midichannel/ccnumber" value : "ccvalue"
if r.set("/midi/cc/"+str(MidiChannel)+"/"+str(msg[1]),str(msg[2]))==True:
print("redis :", "/midi/cc/"+str(MidiChannel)+"/"+str(msg[1]), ":", str(msg[2]))
# OSC : /midi/cc midichannel ccnumber value
SendOSC("/midi/cc",[msg[0]-175-1, msg[1], msg[2]])
#print("osc :","/midi/cc",[msg[0]-175-1, msg[1], msg[2]] )
for param in conf['params']:
if MidiChannel == param["chanIN"] and param["CC"] == msg[1]:
#print(param["name"]+"/"+ str(msg[1])+"/"+str(msg[2]))
SendOSC(param["name"],[msg[0]-175-1, msg[1], msg[2]])
toKeyevent(param["name"]+"/"+ str(MidiChannel)+"/"+str(msg[1])+"/"+str(msg[2]))
if msg[0] == TIMING_CLOCK:
now = time.time()
if last_clock is not None:
samples.append(now - last_clock)
last_clock = now
if len(samples) > 24:
samples.popleft()
if len(samples) >= 2:
#bpm = 2.5 / (sum(samples) / len(samples))
#print("%.2f bpm" % bpm)
bpm = round(2.5 / (sum(samples) / len(samples))) # Against BPM lot very tiny change :
sync = True
# print("MIDI BPM", bpm)
#print("Midi clock : BPM", bpm)
# OSC : "/midi/clock"
SendOSC("/midi/clock",[])
print("osc : /midi/clock")
# SendAU("/aurora/bpm",[bpm])
if msg[0] in (SONG_CONTINUE, SONG_START):
running = True
#print("START/CONTINUE received.")
#print("Midi in process send /aurora/start")
# OSC : /midi/start
SendOSC("/midi/start",[])
print("osc : /midi/start")
if msg[0] == SONG_STOP:
running = False
#print("STOP received.")
#print("Midi in process send /aurora/stop")
# OSC : /midi/start
SendOSC("/midi/stop",[])
print("osc : /midi/stop")
print()
'''
# other midi message
if msg[0] != NOTE_OFF and msg[0] != NOTE_ON and msg[0] != CONTROLLER_CHANGE:
pass
print("from", portname,"other midi message")
MidiMsg(msg[0],msg[1],msg[2],mididest)
'''
#def NoteOn(note, color, mididest):
#https://pypi.org/project/python-rtmidi/0.3a/
# NOTE_ON=#90 et NOTE_OFF=#80 on ajoute le channel (0 le premier) pour envoyer effectivement sur le channel
def NoteOn(note, color, mididest, midichannel=0):
global MidInsNumber
if debug == True:
print("Sending", note, color, "to", mididest, "on channel", midichannel)
for port in range(MidInsNumber):
# To mididest
if midiname[port].find(mididest) == 0:
midiport[port].send_message([NOTE_ON+midichannel, note, color])
# To All
elif mididest == "all" and midiname[port].find(mididest) != 0:
midiport[port].send_message([NOTE_ON+midichannel, note, color])
elif mididest == "pads" and midiname[port].find("Launchpad") > -1:
midiport[port].send_message([NOTE_ON+midichannel, note, color])
if mode == "clitools":
x,y = PadIndex(note)
print("Y :",y)
if 0< y < 3:
ClsCli1()
if 2< y < 5:
ClsCli2()
if 4< y < 7:
ClsCli3()
if 6< y < 9:
ClsCli4()
PadNoteOnXY(x,y,red)
def NoteOff(note, mididest, midichannel=0):
global MidInsNumber
for port in range(MidInsNumber):
# To mididest
if midiname[port].find(mididest) != -1:
midiport[port].send_message([NOTE_OFF, note, 0])
# To All
elif mididest == "all" and midiname[port].find(mididest) == -1:
midiport[port].send_message([NOTE_OFF, note, 0])
#elif mididest == "pads" and midiname[port].find("Launchpad") > -1:
# midiport[port].send_message([NOTE_OFF, note, 0])
# Generic call back : new msg forwarded to queue
class AddQueue(object):
def __init__(self, portname, port):
self.portname = portname
self.port = port
#print "AddQueue", port)
self._wallclock = time.time()
def __call__(self, event, data=None):
message, deltatime = event
self._wallclock += deltatime
#print "inqueue : [%s] @%0.6f %r" % ( self.portname, self._wallclock, message))
message.append(deltatime)
midinputsqueue[self.port].put(message)
#
# MIDI OUT Handling
#
class OutObject():
_instances = set()
counter = 0
def __init__(self, name, kind, port):
self.name = name
self.kind = kind
self.port = port
self._instances.add(weakref.ref(self))
OutObject.counter += 1
print("Adding OutDevice name", self.name, "kind", self.kind, "port", self.port)
@classmethod
def getinstances(cls):
dead = set()
for ref in cls._instances:
obj = ref()
if obj is not None:
yield obj
else:
dead.add(ref)
cls._instances -= dead
def __del__(self):
OutObject.counter -= 1
def OutConfig():
global midiout, MidInsNumber
#
if len(OutDevice) == 0:
print("")
log.info("MIDIout...")
print("List and attach to available devices on host with IN port :")
# Display list of available midi IN devices on the host, create and start an OUT instance to talk to each of these Midi IN devices
midiout = rtmidi.MidiOut()
available_ports = midiout.get_ports()
for port, name in enumerate(available_ports):
midiname[port]=name
midiport[port].open_port(port)
#print )
#print "New OutDevice [%i] %s" % (port, name))
OutDevice.append(OutObject(name, "generic", port))
# Search for a LaunchPad
if name.find("Launchpad") == 0:
OutDevice.append(OutObject(name, "launchpad", port))
print("Launchpad mini start animation")
Start()
time.sleep(0.2)
#print "")
print(len(OutDevice), "Out devices")
#ListOutDevice()
MidInsNumber = len(OutDevice)+1
def ListOutDevice():
for item in OutObject.getinstances():
print(item.name)
def FindOutDevice(name):
port = -1
for item in OutObject.getinstances():
#print "searching", name, "in", item.name)
if name == item.name:
#print 'found port',item.port)
port = item.port
return port
def DelOutDevice(name):
Outnumber = Findest(name)
print('deleting OutDevice', name)
if Outnumber != -1:
print('found OutDevice', Outnumber)
delattr(OutObject, str(name))
print("OutDevice", Outnumber,"was removed")
else:
print("OutDevice was not found")
#
# MIDI IN Handling
# Create processing thread and queue for each device
#
class InObject():
_instances = set()
counter = 0
def __init__(self, name, kind, port, rtmidi):
self.name = name
self.kind = kind
self.port = port
self.rtmidi = rtmidi
self.queue = Queue()
self._instances.add(weakref.ref(self))
InObject.counter += 1
print("Adding InDevice name", self.name, "kind", self.kind, "port", self.port)
@classmethod
def getinstances(cls):
dead = set()
for ref in cls._instances:
obj = ref()
if obj is not None:
yield obj
else:
dead.add(ref)
cls._instances -= dead
def __del__(self):
InObject.counter -= 1
def InConfig():
print("")
log.info("MIDIin...")
# client mode
if debug == True:
if clientmode == True:
print("midix in client mode")
else:
print("midix in server mode")
print("List and attach to available devices on host with OUT port :")
if platform == 'darwin':
mido.set_backend('mido.backends.rtmidi/MACOSX_CORE')
genericnumber = 0
for port, name in enumerate(mido.get_input_names()):
outport = FindOutDevice(name)
midinputsname[port]=name
#print "name",name, "Port",port, "Outport", outport)
# print "midinames", midiname)
#ListInDevice()
try:
#print name, name.find("RtMidi output"))
if name.find("RtMidi output") > -1:
print("No thread started for device", name)
else:
portin = object
port_name = ""
portin, port_name = open_midiinput(outport)
if midisync == True:
portin.ignore_types(timing=False)
#midinputs.append(portin)
InDevice.append(InObject(name, "generic", outport, portin))
thread = Thread(target=MidinProcess, args=(midinputsqueue[port],port_name))
thread.setDaemon(True)
thread.start()
#print "Thread launched for midi port", port, "portname", port_name, "Inname", midiname.index(port_name)
#print "counter", InObject.counter
#midinputs[port].set_callback(AddQueue(name),midinputsqueue[port])
#midinputs[port].set_callback(AddQueue(name))
#genericnumber += 1
InDevice[InObject.counter-1].rtmidi.set_callback(AddQueue(name,port))
#if name.find("Launch") > -1:
# Cls()
except Exception:
traceback.print_exc()
#print "")
print(InObject.counter, "In devices")
#ListInDevice()
def ListInDevice():
#print "known IN devices :"
for item in InObject.getinstances():
print(item.name)
print("")
def FindInDevice(name):
port = -1
for item in InObject.getinstances():
#print "searching", name, "in", item.name)
if name in item.name:
#print 'found port',item.port)
port = item.port
return port
def DelInDevice(name):
Innumber = Findest(name)
print('deleting InDevice', name)
if Innumber != -1:
print('found InDevice', Innumber)
delattr(InObject, str(name))
print("InDevice", Innumber,"was removed")
else:
print("InDevice was not found")
def End():
global midiout
#midiin.close_port()
midiout.close_port()
#del virtual
if launchpad.Here != -1:
del launchpad.Here
if bhoreal.Here != -1:
del bhoreal.Here
if LPD8.Here != -1:
del LPD8.Here
# mididest : all or specifiname, won't be sent to launchpad or Bhoreal.
def MidiMsg(midimsg, mididest):
desterror = -1
print("miredis got midimsg", midimsg, "for", mididest)
for port in range(len(OutDevice)):
# To mididest
if midiname[port].find(mididest) != -1:
if debug == True:
print("miredis sending to name", midiname[port], "port", port, ":", midimsg)
midiport[port].send_message(midimsg)
desterror = 0
elif mididest == "pads" and midiname[port].find("Launchpad") > -1:
midiport[port].send_message(midimsg)
desterror = 0
if desterror == -1:
print("mididest",mididest, ": ** This midi destination doesn't exists **")
# send midi msg over ws.
#if clientmode == True:
# ws.send("/ocs2/cc/1 2")
'''
def NoteOn(note, velocity, mididest):
global MidInsNumber
for port in range(MidInsNumber):
# To mididest
if midiname[port].find(mididest) == 0:
midiport[port].send_message([NOTE_ON, note, velocity])
'''
#
# launchpad
#
def PadNoteOn(note,color):
(x,y) = BhorIndex(note)
#print('PadNoteon', note, x, y, color)
PadNoteOnXY(x,y,color)
def PadNoteOff(note):
(x,y) = BhorIndex(note)
#print('PadNoteOFF', note, x, y)
PadNoteOffXY(x,y)
def PadNoteOnXY(x,y,color):
msg= [NOTE_ON, PadNoteXY(x,y), color]
#print(msg)
MidiMsg(msg,"Launchpad")
PadLeds[BhorNoteXY(x,y)]=color
def PadNoteOffXY(x,y):
msg= [NOTE_OFF, PadNoteXY(x,y), 0]
#print(msg)
MidiMsg(msg,"Launchpad")
PadLeds[BhorNoteXY(x,y)]=0
def PadNoteXY(x,y):
note = LaunchLedMatrix[int(y-1)][int(x-1)]
return note
def PadIndex(note):
y=note/16
x=note%16
return int(x+1),int(y+1)
def BhorIndex(note):
y=note/8
x=note%8
#print "Note : ",note
#print "BhorIndex : ", x+1,y+1
return int(x+1),int(y+1)
def BhorNoteXY(x,y):
note = (x -1)+ (y-1) * 8
return note
# top raw and right column leds are numbered humanly 1-8. So -1 is for pythonic arrays position 0-7
def PadTopOn(number, color):
msg= [CONTROLLER_CHANGE, LaunchTop[number-1], color]
MidiMsg(msg,"Launchpad")
PadTops[number-1]=color
def PadTopOff(number):
msg= [CONTROLLER_CHANGE, LaunchTop[number-1], 0]
MidiMsg(msg,"Launchpad")
PadTops[number-1]=0
def PadRightOn(number, color):
msg= [NOTE_ON, LaunchRight[number-1], color]
MidiMsg(msg,"Launchpad")
PadRights[number-1] = color
#UpdateAllCCs(number-1)
def PadRightOff(number):
msg= [NOTE_OFF, LaunchRight[number-1], 0]
MidiMsg(msg,"Launchpad")
PadRights[number-1] = 0
def TopUpdate(button, color):
#print(PadTop)
PadTop = [0,0,0,0,0,0,0,0]
PadTop[button] = color
for pad in range(7):
PadTopOn(pad+1, PadTop[pad])
def RightUpdate():
for pad in range(8):
print(pad,PadRight[pad])
PadRightOn(pad, PadRight[pad])
if PadRight[pad] == 0:
SendOSCUI('/pad/r'+ str(pad) +'/button', [0])
else:
SendOSCUI('/pad/r'+ str(pad) +'/button', [1])
def MatrixUpdate():
for pad in range(64):
PadNoteOn(pad, PadMatrix[pad])
def MatrixSelect():
MatrixUpdate()
return
# AllColor for launchpad on given port
def AllColorPad(color):
print('AllColorPad')
for led in range(0,64,1):
PadNoteOn(led,color)
'''
for line in LaunchLedMatrix:
for led in line:
midiport[port].send_message([NOTE_ON, led, color])
'''
for rightled in range(8):
PadRightOn(rightled+1, color)
for topled in range(8):
PadTopOn(topled+1,color)
#midiport[port].send_message([CONTROLLER_CHANGE, topled, color])
# Led line 1,2 color 58
def ClsCli1():
for x in range(8):
PadNoteOnXY(x,1,58)
PadNoteOnXY(x,2,58)
# Led line 3,4 color yellow
def ClsCli2():
for x in range(8):
PadNoteOnXY(x,3,yellow)
PadNoteOnXY(x,4,yellow)
# Led line 5,6 color 58
def ClsCli3():
for x in range(8):
PadNoteOnXY(x,5,58)
PadNoteOnXY(x,6,58)
# Led line 7,8 color yellow
def ClsCli4():
for x in range(8):
PadNoteOnXY(x,7,yellow)
PadNoteOnXY(x,8,yellow)
def ClsCli():
ClsCli1()
ClsCli2()
ClsCli3()
ClsCli4()
def ClsMatrix():
for led in range(0,64,1):
PadNoteOff(led)
def ClsTop():
for topled in range(8):
PadTopOff(topled+1)
def ClsRight():
for rightled in range(8):
PadRightOff(rightled+1)
def Cls():
ClsMatrix()
ClsTop()
ClsRight()
def Start():
#ClsPad(port)
#time.sleep(0.3)
ClsTop()
ClsRight()
#AllColorPad(20)
time.sleep(1)
for color in range(64,128,1):
#AllColorPad(color)
PadNoteOn(color-64, color)
#print("color", color)
time.sleep(0.5)
Cls()
if mode == "clitools":
ClsCli()
for y in range(0,8,2):
PadNoteOnXY(1,y-1,red)
def listdevice(number):
return midiname[number]
def loadConf():
global conf, nbparam
try:
ConFile = 'miredis.json'
f = open(ConFile,"r")
s = f.read()
conf = json.loads(s)
print("params", len(conf['params']))
nbparam = len(conf['params'])
print(conf)
return True
except Exception as e:
print("_loadPlaylist error when loading '{}':{}".format(ConFile,e))
def check():
OutConfig()
InConfig()