//-----------------------------------------------------------------------------
//-------- Copyright (c)2003-2016. All Rights Reserved. -----------------------
//-----------------------------------------------------------------------------
// file implementing MIDI controller ''
// last revision: 2018-02-27
//Author: Tollen Francisco, 2018-02-27
//
//----------------------------------------------------------------------------- 
function getLanguageVersion()
{
	return 1;// do not modify this, this should be 1 for all scripts
}
//----------------------------------------------------------------------------- 
function getFileVersion()
{
	return 1;// update this as needed
}
//----------------------------------------------------------------------------- 
// return a user friendly name for the controller supported
function getControllerUserFriendlyName()
{
	return "DDJ-SR2";
}
//----------------------------------------------------------------------------- 
// return the communication type that the controller supports 
// this can be either 'midi' or 'hid' (please return only one of them in case the controller supports both)
function getControllerType()
{
	return 'midi';
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// preferred way to identify the controller (using the USB device VID and PID -- vendor and product id)
// return false if the controller does not support this kind of identification
// osId -- 0 Windows; 1 MacOSX; 2 Linux; -1 unknown
function getSupportedHidDeviceVID(osId)
{
	return false;
}
//----------------------------------------------------------------------------- 
function getSupportedHidDevicePID(osId)
{
	return false;
}
//----------------------------------------------------------------------------- 
// this is NOT the preferred way to identify the controller but you should use
// it if the controller does not support standard USB VID and PID identification
// return false if the controller does not support this kind of identification
// osId -- 0 Windows; 1 MacOSX; 2 Linux; -1 unknown
function getSupportedHidDeviceName(osId)
{
	return false;
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// preferred way to identify the controller (using the USB device VID and PID -- vendor and product id)
// return false if the controller does not support this kind of identification
// osId -- 0 Windows; 1 MacOSX; 2 Linux; -1 unknown
function getSupportedMidiDeviceVID(osId)
{	
	return 0x2B73;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDevicePID(osId)
{	
	return 0x001E;	
}
//----------------------------------------------------------------------------- 
// preferred way to identify the controller (if it supports MIDI SysEx)
// return false if the controller does not support this kind of identification
function getSupportedMidiSysExIdString(osId)
{
	// sysex response to 'F0 7E 7F 06 01 F7' (identification request sysex)
	// please note that the response contains 5 bytes in hex format containing
	// the Manufacturer ID (3 bytes) and Model Number (2 bytes)
	// ATTN: the returned value should omit the standard 'F0 7E 00 06 02' message start
	return false; //very long sysex id
	
}
//----------------------------------------------------------------------------- 
// this is NOT the preferred way to identify the controller but you should use
// it if the controller does not support standard MIDI SysEx identification
// return false if the controller does not support this kind of identification
// osId -- 0 Windows; 1 MacOSX; 2 Linux; -1 unknown
function getSupportedMidiDeviceNameForInput(osId)
{
	//return "DDJ-SR2";
	return false;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput(osId)
{
	//return "DDJ-SR2";
	return false;
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// some variables necessary only for this particular script
var shiftButton				=[0,0,0,0];
var samplerBlinkLedStatus   =[0,0,0,0];
var jogWheelsInScratchMode	=[0,0,0,0];
//----------------------------------------------------------------------------- 
// this is called when the controller is initialized and the control is passed to this script
// use this to initialize any variables you might need, the controller' leds, etc
// uniqueId is a unique integer between 0..15 that is guaranteed not to change for 
// a certain opened controller -- please note that there can be many controllers
// of the same type in use at the same time ! Use uniqueId to identify between them
function controllerInit(uniqueId)
{
	callSendAllNotifications(uniqueId, true);// send all notifications to the controller (so that we don't have to manually init all leds/lcd screens)
	//turn on effects buttons
	sendMidi(uniqueId,0x90,4,0x47,0x7F);
	sendMidi(uniqueId,0x90,4,0x48,0x7F);
	sendMidi(uniqueId,0x90,4,0x49,0x7F);
	
	sendMidi(uniqueId,0x90,5,0x47,0x7F);
	sendMidi(uniqueId,0x90,5,0x48,0x7F);
	sendMidi(uniqueId,0x90,5,0x49,0x7F);
	
	//disable scratchmode  led
	sendMidi(uniqueId,0x90,0,0x40,0x00);
	sendMidi(uniqueId,0x90,1,0x40,0x00);
	sendMidi(uniqueId,0x90,2,0x40,0x00);
	sendMidi(uniqueId,0x90,3,0x40,0x00);
	
	call('sleep', 10);// delay for 10ms to allow the MIDI out buffer to flush
	
}
//----------------------------------------------------------------------------- 
// called just before the controller will be deinitialized and the control will go away from the script
// use to power off any powered leds, etc
function controllerDeinit(uniqueId)
{
	callSendAllNotifications(uniqueId, false);// send all notifications to the controller (so that we don't have to manually init all leds/lcd screens)
	//turn off effects buttons
	sendMidi(uniqueId,0x90,4,0x47,0x00);
	sendMidi(uniqueId,0x90,4,0x48,0x00);
	sendMidi(uniqueId,0x90,4,0x49,0x00);
	
	sendMidi(uniqueId,0x90,5,0x47,0x00);
	sendMidi(uniqueId,0x90,5,0x48,0x00);
	sendMidi(uniqueId,0x90,5,0x49,0x00);
	
	//disable scratchmode  led
	sendMidi(uniqueId,0x90,0,0x40,0x00);
	sendMidi(uniqueId,0x90,1,0x40,0x00);
	sendMidi(uniqueId,0x90,2,0x40,0x00);
	sendMidi(uniqueId,0x90,3,0x40,0x00);
	
	call('sleep', 10);// delay for 10ms to allow the MIDI out buffer to flush

}
//----------------------------------------------------------------------------- 
// this is your main target function to implement the controller -- this is called 
// for each and every MIDI message that comes from the controller itself
// return true if the message was processed by the script and false to let it 
// pass thru the software (eg. so it can be assigned by the user using the LEARN function)
function messageReceived(uniqueId,status,channel,data1,data2)
{
	//debug('messageReceived ['+uniqueId+'] - status:'+status+' channel:'+channel+' data1:'+data1+' data2:'+data2);
	var messageNotProcessed=false;
	
    //if(channel==2) channel = 1;else if(channel==1) channel = 2; // use this to switch channel; 2 and 3 instead of multiple if's
	switch(status)
	{
	//-----------------------------------------------
	// controllers: sliders, knobs, jog-wheels, encoders ('moving' things)
	case 0xE0: // call('setDeckPitch', channel, data2); break; //pitch sliders decks 1-4
		break;
	
	case 0xB0:
		switch(data1)
		{
		case 0x00:
			call('setDeckPitch', channel, 0x7F-data2);
		break;
		case 0x01: 
		break;
		case 0x02: //echo
			if(channel >= 4){
				call('deckFxEchoDW', channel-4, data2);
			
			}
			
		break;
		case 0x03: //setDeckPos 
			if(channel == 6){
				call('setSamplerMasterVolume',data2);
			} else {
				call('setDeckPos', channel, data2);
			}
			
		break;
		case 0x04: //flanger
			if(channel >= 4){
				call('deckFxFlangerDW', channel-4, data2);
			} else {
				call('setDeckGain', channel, data2);
			}
			
		break;
		case 0x05:
		break;
		case 0x06: //beatwaw
			
			call('deckFxBeatwawDW', channel-4, data2);
		break;
		case 0x07: 
			call('setDeckEqHigh', channel, data2);
		break;
		case 0x08: 
			call('setMasterGain', data2);
		break;
		case 0x09: 
			call('setMonitorGain', data2);
		break;
		case 0x0A: 
			call('setMicVolume', data2);
		break;
		case 0x0B: 
			call('setDeckEqMid', channel, data2);
		break;
		case 0x0C: 
			call('setCuePgmMix', data2);
		break;
		case 0x0D: 
			call('setMonitorGain', data2);
		break;
		case 0x0E: 
		break;
		case 0x0F: 
		call('setDeckEqLow', channel, data2);
		break;
		case 0x10: 
		break;
		case 0x11: 
		break;
		case 0x12: 
		break;
		case 0x13: 
			call('setDeckVolume', channel, data2);
		break;
		case 0x14: 
		break;
		case 0x15: 
		break;
		case 0x16: 
		break;
		case 0x17: 
			call('setDeckCutoff', 0, data2);
		break;
		case 0x18:
			call('setDeckCutoff', 1, data2);
		break;
		case 0x19: 
			call('setDeckCutoff', 2, data2);
		break;
		case 0x1A: 
			call('setDeckCutoff', 3, data2);
		break;
		case 0x1B: 
		break;
		case 0x1C: 
		break;
		case 0x1D: 
		break;
		case 0x1E: 
		break;
		case 0x1F: 
			call('setCrossfader', data2);
		break;
		case 0x20: 
		break;
		case 0x21: 
			var val1;
			if(data2 <= 0x3F)
				val1 = 0x00 - data2;
			else
				val1 = data2;
			call('moveDeckJogWheel', channel, val1, 2400);
		break;
		case 0x22: 
			//debug(jogWheelsInScratchMode[channel].toString());
			if(jogWheelsInScratchMode[channel] > 0){
				var val1;
				if(data2 <= 0x3F)
					val1 = 0x00 - data2;
				else
					val1 = data2;
				call('scratchDeckJW', channel, val1, 2400);
			} else {
				var val1;
				if(data2 <= 0x3F)
					val1 = 0x00 - data2;
				else
					val1 = data2;
				call('moveDeckJogWheel', channel, val1, 2400);
			}
			
		break;
		case 0x23: 
		break;
		case 0x24: 
		break;
		case 0x25: 
		break;
		case 0x26: 
		break;
		case 0x27: 

		break;
		case 0x28: 
		break;
		case 0x29: 
		break;
		case 0x2A: 
		break;
		case 0x2B: 			
		break;
		case 0x2C: 
		break;
		case 0x2D: 
		break;
		case 0x2E: 
		break;
		case 0x2F: 
		break;
		case 0x30: 
		break;
		case 0x31: 
		break;
		case 0x32: 
		break;
		case 0x33: 
		break;
		case 0x34: 
		break;
		case 0x35: 
		break;
		case 0x36: 
		break;
		case 0x37: 
		break;
		case 0x38: 
		break;
		case 0x39: 
		break;
		case 0x3A: 
		break;
		case 0x3B: 
		break;
		case 0x3C: 
		break;
		case 0x3D: 
		break;
		case 0x3E: 
		break;
		case 0x3F: 
			shiftButton[channel] = data2;
		break;
		case 0x40:
			var val1 = (data2>0x40 ? data2-0x80 : data2);
			call('lbMoveCursor', val1);
		break;
		case 0x43:			
		break;
		default: messageNotProcessed = true;
		}
	break;
	//-----------------------------------------------
	// note on/off: buttons, switches ('pressing' things)
	case 0x80:
	case 0x90:
		//if(data2==0x40) data2 = 0x7F;
		
		switch(data1)
		{
		case 0x00:			
			call('deckCuePos1', channel-7, data2);
		break;
		case 0x01:
			call('deckCuePos2', channel-7, data2);
		break;
		case 0x02: 			
			call('deckCuePos3', channel-7, data2);
		break;
		case 0x03: 			
			call('deckCuePos4', channel-7, data2);
		break;
		case 0x04: 			
			call('deckCuePos5', channel-7, data2);
		break;
		case 0x05: 			
			call('deckCuePos6', channel-7, data2);
		break;
		case 0x06: 			
			call('deckCuePos7', channel-7, data2);
		break;
		case 0x07: 		
			call('deckCuePos8', channel-7, data2);
		break;
		case 0x08: 
		break;
		case 0x09:			
		break;
		case 0x0A:
		break;
		case 0x0B:			
			call('deckPlayPause', channel, data2);
		break;
		case 0x0C:	
			call('deckCue', channel, data2);
		break;
		case 0x0D:			
		break;
		case 0x0E:			
		break;
		case 0x0F: 
		break;
		case 0x10: 
			if(channel < 7){
				if(!getValue('looping', channel)) call('deckLoopInEnd', channel, data2);else call('deckLoopExit', channel, data2);
			} else {
				call('deckLoopPoint1', channel-7, data2);
			}
			
		break;
		case 0x11: 
		if(channel < 7){
				if(!getValue('looping', channel)) call('deckLoopInEnd', channel, data2);else call('deckLoopExit', channel, data2);
			} else {
				call('deckLoopPoint2', channel-7, data2);
			}
		break;
		case 0x12: 
			if(channel < 7){
				call('deckLoopLess', channel, data2);
			} else {
				call('deckLoopPoint3', channel-7, data2);
			}
		break;
		case 0x13: 
			if(channel < 7){
				call('deckLoopMore', channel, data2);
			} else {
				call('deckLoopPoint4', channel-7, data2);
			}
			
		break;
		case 0x14: 
			if(channel < 7){
				call('deckLoop4', channel, data2);
			} else {
				call('deckLoopPoint5', channel-7, data2);
				
			}
			
		break;
		case 0x15: 
			if(channel < 7){
				call('deckReverse', channel, data2);
			} else {
				call('deckLoopPoint6', channel-7, data2);
			}
		break;
		case 0x16: 
			call('deckLoopPoint7', channel-7, data2);
		break;
		case 0x17: 
			call('deckLoopPoint8', channel-7, data2);
		break;
		case 0x18:		
		break;
		case 0x19:		
		break;
		case 0x1A:	
			call('deckKeyLock', channel, data2);
		break;
		case 0x1B: 						
		break;
		case 0x1C: 
		break;
		case 0x1D: 
		break;
		case 0x1E: 
		break;
		case 0x1F: 
		break;
		case 0x20: 
		break;
		case 0x21: 
		break;
		case 0x22: 
		break;
		case 0x23: 
		break;
		case 0x24: 
		break;
		case 0x25: 
		break;
		case 0x26: 
		break;
		case 0x27: 
		break;
		case 0x28: 			
		break;
		case 0x29: 			
		break;
		case 0x2A: 
		break;
		case 0x2B: 			
		break;
		case 0x2C:			
		break;
		case 0x2D: 
		break;
		case 0x2E: 			
		break;
		case 0x2F: 
		break;
		case 0x30: 
			call('samplerPlay', 1);
		break;
		case 0x31: 
			call('samplerPlay', 2);
		break;
		case 0x32: 
			call('samplerPlay', 3);
		break;
		case 0x33: 
			call('samplerPlay', 4);
		break;
		case 0x34: 
			call('samplerPlay', 5);
		break;
		case 0x35: 
			call('samplerPlay', 6);
		break;
		case 0x36: 
			if(channel >= 7){
				call('samplerPlay', 7);
			} else {
				if(jogWheelsInScratchMode[channel]){
					call('holdDeckJogWheel', channel, data2);
				}				
			}
			
		break;
		case 0x37: 
			call('samplerPlay', 8);
		break;
		case 0x38: 			
		break;
		case 0x39: 
		break;
		case 0x3A: 
		break;
		case 0x3B: 
		break;
		case 0x3C: 
		break;
		case 0x3D: 
		break;
		case 0x3E: 
		break;
		case 0x3F: 
		break;
		case 0x40:
			if(data2){
				jogWheelsInScratchMode[channel] = (jogWheelsInScratchMode[channel]+1)%2; 
				sendMidi(uniqueId,0x90,channel,0x40,(jogWheelsInScratchMode[channel] ? 0x7F : 0x00));
			}
				
		break;
		case 0x41:
			if(data2)
				call('lbToggleSelect', data2);
		break;
		case 0x42:
			
		break;
		case 0x43:
			call('deckTapBpm', channel-4, data2);
		break;
		case 0x44:
			
		break;
		case 0x45:
			
		break;
		case 0x46:
			if(data2)
				call('deckLBLoad', 0, data2);
			break;
		case 0x47:
			if(data2 && channel >= 6)
				call('deckLBLoad', 1, data2);
			break;
		case 0x48:
			if(data2 && channel >= 6)
				call('deckLBLoad', 2, data2);
			break;
		case 0x49:
			if(data2 && channel >= 6)
				call('deckLBLoad', 3, data2);
			break;
		case 0x4D:
			if(getValue('looping',channel)){
				call('deckLoopExit', channel, data2);
			} else {
				call('deckLoopReloop', channel, data2);
			}
			
			break;
		case 0x50:
			
			break;
		case 0x51:
			break;
		case 0x52:
			break;
		case 0x54:
			call('deckMonitor', channel, data2);
		break;
		case 0x55:
		break;
		case 0x58:
			call('deckSync', channel, data2);
			break;
		case 0x5F:
			break;
		case 0x60:
			if(data2){
				var currentPitchRange = getValue('pitchRange');
				currentPitchRange = currentPitchRange + 1; if(currentPitchRange>6) currentPitchRange = 1;
				call('setPitchRange', currentPitchRange);
			}
			break;
		case 0x61:
			break;
		case 0x62:
			break;
		case 0x77: 
			break;
		
		default: messageNotProcessed = true;
		}
		break;
	//-----------------------------------------------
	default: messageNotProcessed = true;
	}
	if(messageNotProcessed) debug('messageReceived ['+uniqueId+'] - status:'+status+' channel:'+channel+' data1:'+data1+' data2:'+data2);
	return !messageNotProcessed;
}
//----------------------------------------------------------------------------- 
// this is called by the software whenever something important changes (eg. play status, song changed, etc)
// depending on the notification type it may refer to a global event (deck is -1) or a specific deck (deck >= 0)
// and can contain any/all of the parameters: param 1 is an integer, param 2 is a float, param 3 is a string
function notificationReceived(uniqueId,name,deck,param1,param2,param3)
{
	//debug('notif ['+uniqueId+'] name='+name + ' deck='+deck + ' p1(int)='+param1 + ' p2(float)='+param2 + ' p3(str)='+param3);
	var nameLen = name.length;
	
	if(name=='cuepos1')		sendMidi(uniqueId,0x90,deck + 7,0x00,(param1 ? 0x7F : 0x00));
	if(name=='cuepos2')		sendMidi(uniqueId,0x90,deck + 7,0x01,(param1 ? 0x7F : 0x00));
	if(name=='cuepos3')		sendMidi(uniqueId,0x90,deck + 7,0x02,(param1 ? 0x7F : 0x00));
	if(name=='cuepos4')		sendMidi(uniqueId,0x90,deck + 7,0x03,(param1 ? 0x7F : 0x00));
	if(name=='cuepos5')		sendMidi(uniqueId,0x90,deck + 7,0x04,(param1 ? 0x7F : 0x00));
	if(name=='cuepos6')		sendMidi(uniqueId,0x90,deck + 7,0x05,(param1 ? 0x7F : 0x00));
	if(name=='cuepos7')		sendMidi(uniqueId,0x90,deck + 7,0x06,(param1 ? 0x7F : 0x00));
	if(name=='cuepos8')		sendMidi(uniqueId,0x90,deck + 7,0x07,(param1 ? 0x7F : 0x00));
	
	
	if(name=='looppos1'){
		debug
		sendMidi(uniqueId,0x90,deck+7,0x10,(param1 ? 0x7F : 0x00));
	}
	if(name=='looppos2'){
		sendMidi(uniqueId,0x90,deck+7,0x11,(param1 ? 0x7F : 0x00));
	}
	if(name=='looppos3'){	
		sendMidi(uniqueId,0x90,deck+7,0x12,(param1 ? 0x7F : 0x00));
	}
	if(name=='looppos4'){	
		sendMidi(uniqueId,0x90,deck+7,0x13,(param1 ? 0x7F : 0x00));
	}
	if(name=='looppos5'){	
		sendMidi(uniqueId,0x90,deck+7,0x14,(param1 ? 0x7F : 0x00));
	}
	
	if(nameLen==8)
	{
		var name1 = name.substr(0, nameLen-1);
		if(name1=='sampler')
			{				
				//debug('notif ['+uniqueId+'] name='+name + ' deck='+deck + ' p1(int)='+param1 + ' p2(float)='+param2 + ' p3(str)='+param3);
				
				if(name=='sampler1') {
					sendMidi(uniqueId,0x90,7,0x30,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x30,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x30,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x30,(param1 ? 0x7F : 0x00));
				}
				if(name=='sampler2') {
					sendMidi(uniqueId,0x90,7,0x31,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x31,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x31,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x31,(param1 ? 0x7F : 0x00));
				}
				if(name=='sampler3') {
					sendMidi(uniqueId,0x90,7,0x32,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x32,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x32,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x32,(param1 ? 0x7F : 0x00));
					
				}
					
				if(name=='sampler4') {
					sendMidi(uniqueId,0x90,7,0x33,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x33,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x33,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x33,(param1 ? 0x7F : 0x00));
				}
				
				if(name=='sampler5') {
					sendMidi(uniqueId,0x90,7,0x34,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x34,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x34,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x34,(param1 ? 0x7F : 0x00));
				}
				
				if(name=='sampler6') {
					sendMidi(uniqueId,0x90,7,0x35,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x35,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x35,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x35,(param1 ? 0x7F : 0x00));
					
				}
				
				if(name=='sampler7') {
					sendMidi(uniqueId,0x90,7,0x36,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x36,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x36,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x36,(param1 ? 0x7F : 0x00));
				}
				
				if(name=='sampler8') {
					sendMidi(uniqueId,0x90,7,0x37,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,8,0x37,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,9,0x37,(param1 ? 0x7F : 0x00));
					sendMidi(uniqueId,0x90,10,0x37,(param1 ? 0x7F : 0x00));
				}
				
				
					
					
			}
	}
	
	
	if(name=='play'){
		sendMidi(uniqueId,0x90,deck,0x0B,(param1 ? 0x7F : 0x00)); //play button
		
	}//play
	if(name=='cue') 		sendMidi(uniqueId,0x90,deck,0x0C,(param1 ? 0x7F : 0x00)); //cue
	if(name=='onbeat') 		sendMidi(uniqueId,0x90,deck,0x58,(param1 ? 0x7F : 0x00)); //play
	if(name=='monitor') 	sendMidi(uniqueId, 0x90,deck,0x54,(param1 ? 0x7F : 0x00));//monitor
	if(name=='reverse')		sendMidi(uniqueId,0x90,deck,0x15,(param1 ? 0x7F : 0x00));//reverse
	if(name=='keyLock') 	sendMidi(uniqueId,0x90,deck,0x1A,(param1 ? 0x7F : 0x00));//keylock
	if(name=='loopIn'){
		sendMidi(uniqueId,0x90,deck,0x10,(param1 ? 0x7F : 0x00));
		sendMidi(uniqueId,0x90,deck,0x11,0x00);//loop out led
	}		//loop in
	if(name=='looping') 	 
	{
		sendMidi(uniqueId,0x90,deck,0x10,(param1 ? 0x7F : 0x00));// loop in led
		sendMidi(uniqueId,0x90,deck,0x11,(param1 ? 0x7F : 0x00));//loop out led
		sendMidi(uniqueId,0x90,deck,0x4D,(param1 ? 0x7F : 0x00));//loop out led ???
	}
	if(name == 'deckFxEcho'){
		
		if(deck == 0 || deck == 2){
			sendMidi(uniqueId,0x90, 4,0x47,(param1 ? 0x7F : 0x00));
		} else {
			sendMidi(uniqueId,0x90, 5,0x47,(param1 ? 0x7F : 0x00));
		}
		
	}
	if(name == 'deckFxFlanger'){
		sendMidi(uniqueId,0x90,deck + 4,0x48,(param1 ? 0x7F : 0x00));
	}
	if(name == 'deckFxBeatwaw'){
		sendMidi(uniqueId,0x90,deck + 4,0x49,(param1 ? 0x7F : 0x00));
	}
				
}


//----------------------------------------------------------------------------- 
// this is called from time to time by the software (several times per second)
// (it is guaranteed that 'timerTick' will get executed ALWAYS right after notificationReceived)
function timerTick(uniqueId)
{
	for(var i=0; i<4; i++)
	{	
		var vuDeck = getValue('vumeterDeck', i);// float dB
		sendMidi(uniqueId,0xB0,i,0x02,getMIDIValueForVU(vuDeck));
		
		
	}
}

function getMIDIValueForVU(vu_val)
{
	// translating VU-meter signal from decibels (dB) to 0..127 MIDI range
	var val = 0;
	var step = 17.7;
	if(vu_val>-44) val =  1 * step;
	if(vu_val>-36) val =  2 * step;
	if(vu_val>-28) val =  3 * step;
	if(vu_val>-20) val =  4 * step;
	if(vu_val>-16) val =  5 * step;
	if(vu_val>-12) val =  6 * step;
	if(vu_val> -8) val =  7 * step;
	if(vu_val> -4) val =  8 * step;
	if(vu_val> -2) val =  9 * step;
	if(vu_val> -1) val = 10 * step;
	return Math.floor(val);
}

//----------------------------------------------------------------------------- 
