
#!/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]))
                    toKeyevent(param["name"]+"/"+ 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()
    

	
