//-----------------------------------------------------------------------------
//-------- Copyright (c)2003-2011. All Rights Reserved. -----------------------
//-----------------------------------------------------------------------------
// file implementing MIDI controller ' Pioneer DDJ SX
// Date: 2015 9	 11
// Author: Tollen Francisco
//----------------------------------------------------------------------------- 
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 "PIONEER DDJ-WeGO3";
}
//----------------------------------------------------------------------------- 
// 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 0x08E4;
	//return false;
}
//----------------------------------------------------------------------------- 
function getSupportedHidDevicePID(osId)
{
	//return 0x01A0;
	//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 (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
	//if(osId==1) return false;
	
	//return "";
	// full string: 00  F0 7E 7F 06 02 00 20 79  08 same as SR :(
	return false;
}
//----------------------------------------------------------------------------- 
// 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 "PIONEER DDJ-WeGO3";// !!! 
	return false;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput(osId)
{
	//return "PIONEER DDJ-WeGO3";// !!! MAKE SURE THIS IS INDEED OK !!!
	return false;
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// some variables necessary only for this particular script
var jogWheelsInScratchMode=[0,0,0,0];
var jogWheelsWasDeckPlaying=[0,0,0,0];
var shiftButton = 0;
var deckMode=[0,0,0,0]; //0=hot cue 1=roll 2=slicer 3=sampler

var samplerBlinkLedStatus		=[0,0,0,0,0,0,0,0];// 2 decks leds, each with 4 samplers // 0 means off; 1 means on; 2 means blink on; 3 means blink off;
var samplerBlinkState = [0,0,0,0,0,0,0,0];

var jwSearchCountLeft=[0,0,0,0];
var jwSearchCountRight=[0,0,0,0];

var fxdeckSetting = [0,0]

//----------------------------------------------------------------------------- 
var fxLast=[-1,-1,-1,-1,-1];
//----------------------------------------------------------------------------- 

// 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)
{

	
}
//----------------------------------------------------------------------------- 
// 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)
{

	sendMidi(uniqueId, 0x90, 1, 0x58, 0x7F);
	sendMidi(uniqueId, 0x91, 2, 0x58, 0x7F);
	//deck 1
	sendMidi(uniqueId,0x90,4,0x43,0x00);//fx1
	sendMidi(uniqueId,0x90,4,0x44,0x00);//fx2
	sendMidi(uniqueId,0x90,4,0x45,0x00);//fx3
	call('sleep', 5);
	//deck 2
	sendMidi(uniqueId,0x90,5,0x43,0x00);//fx1
	sendMidi(uniqueId,0x90,5,0x44,0x00);//fx2
	sendMidi(uniqueId,0x90,5,0x45,0x00);//fx3
	
	
	
	sendMidi(uniqueId, 0x90, 2, 0x72, 0x00);
	sendMidi(uniqueId, 0x90, 3, 0x72, 0x00);
	
	for(var i=0; i<2; i++)
	{
		sendMidi(uniqueId,0x90,4+i,0x42,0x00);// Ctrl+A
		sendMidi(uniqueId,0x90,4+i,0x43,0x00);// FX1
		sendMidi(uniqueId,0x90,4+i,0x44,0x00);// FX2
		sendMidi(uniqueId,0x90,4+i,0x45,0x00);// FX3
		sendMidi(uniqueId,0x90,4+i,0x46,0x00);// Ctrl+B
	}
	
	for(var i=2; i<4; i++)
	{
		sendMidi(uniqueId,0x90,4+i-2,0x47,0x00);// Ctrl+A
		sendMidi(uniqueId,0x90,4+i-2,0x48,0x00);// FX1
		sendMidi(uniqueId,0x90,4+i-2,0x49,0x00);// FX2
		sendMidi(uniqueId,0x90,4+i-2,0x4A,0x00);// FX3
		sendMidi(uniqueId,0x90,4+i-2,0x4B,0x00);// Ctrl+B
	}
	
	for(var i=0; i<4; i++)
	{
		sendMidi(uniqueId,0x90,i,0x0B,0x00);
		sendMidi(uniqueId,0x90,i,0x0C,0x00);		
		sendMidi(uniqueId,0x90,i,0x14,0x00);		
		call('sleep', 5);
		sendMidi(uniqueId,0x90,i,88, 0x00);// sync (off by default)
		sendMidi(uniqueId,0x90,i,0x2E,0x00);//cue1
		sendMidi(uniqueId,0x90,i,0x2F,0x00);//cue2
		sendMidi(uniqueId,0x90,i,0x30,0x00);//cue3
		sendMidi(uniqueId,0x90,i,0x31,0x00);//cue4
		call('sleep', 5);		
		if(i==0)
		{
			sendMidi(uniqueId,0x90,i,0x3C,0x00);// sampler 1
			sendMidi(uniqueId,0x90,i,0x3E,0x00);// sampler 2
			sendMidi(uniqueId,0x90,i,0x40,0x00);// sampler 3
			sendMidi(uniqueId,0x90,i,0x42,0x00);// sampler 4
		}
		if(i==1)
		{
			sendMidi(uniqueId,0x90,i,0x3C,0x00);// sampler 5
			sendMidi(uniqueId,0x90,i,0x3E,0x00);// sampler 6
			sendMidi(uniqueId,0x90,i,0x40,0x00);// sampler 7
			sendMidi(uniqueId,0x90,i,0x42,0x00);// sampler 8
		}
		call('sleep', 5);// delay for 5ms to allow the MIDI out buffer to flush
	}
	// monitor (headphones
	sendMidi(uniqueId,0x90,6,84,0x00);
	sendMidi(uniqueId,0x90,6,85,0x00);	
	call('sleep', 5);// delay for 5ms 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;
	switch(status){
		// controllers: sliders, knobs, jog-wheels, encoders ('moving' things)
		case 0xB0:
		case 0xB4:
		case 0xB6:
			switch(data1){
				case 0x00: //deck pitch
					call('setDeckPitch', channel, 0x7F - data2);
					break;
				case 0x02:
						debug((fxLast[0]).toString());
						if(channel==4){
							fxdeckSetting[0] = data2;
							if((fxLast[0]).toString() == '1') call('deckFxFlangerDW', 0, data2);// jog-fx FX1
						}
						
						if(channel==5) {
							fxdeckSetting[1] = data2;
							if((fxLast[1]).toString() == '1') call('deckFxFlangerDW', 1, data2);// jog-fx FX1					
						}
					break;
				case 0x04:
					if(channel==4) {
						fxdeckSetting[0] = data2;
						if((fxLast[0]).toString() == '2') call('deckFxBeatwawDW', 0, data2);// jog-fx FX2
					}
					if(channel==5) {
						fxdeckSetting[1] = data2;
						if((fxLast[1]).toString() == '2') call('deckFxBeatwawDW', 1, data2);// jog-fx FX2
					}
					
					break;
				case 0x06:							
						if(channel==4) {
							fxdeckSetting[0] = data2;
							if((fxLast[0]).toString() == '3') call('deckFxEchoDW', 0, data2);// jog-fx FX3
						}
						if(channel==5) {
							fxdeckSetting[1] = data2;
							if((fxLast[1]).toString() == '3') call('deckFxEchoDW', 1, data2);// jog-fx FX3
						}
					break;
				case 0x07: //deck 0 hi
					call('setDeckEqHigh', 0, data2);
					break;
				case 0x08: //deck 1 hi
					call('setDeckEqHigh', 1, data2);
					break;
				case 0x0B: //deck 0 mid
					call('setDeckEqMid', 0, data2);
					break;
				case 0x0C: //deck 1 mid
					call('setDeckEqMid', 1, data2);
					break;
				case 0x0F: //deck 0 low
					call('setDeckEqLow', 0, data2);
					break;
				case 0x10: //deck 1 low
					call('setDeckEqLow', 1, data2);
					break;
				case 0x13:
					call('setDeckVolume', 0, data2);
					break;
				case 0x15:
					call('setDeckVolume', 1, data2);
					break;
				case 0x1F:
					call('setCrossfader', data2);
					break;
				case 0x21:
					var val1 = data2-0x40;
					call('moveDeckJogWheel', channel, val1, 470);					
					break;
				case 0x22:
					var val1 = data2-0x40;
					call('scratchDeckJW', channel, val1, 470);
					break;
				case 0x26: // also gain D extra byte
				case 0x27: // pressed (also eq high A extra byte)
					
						var val1 = data2-0x40;
						if(val1<0)
						{
							jwSearchCountLeft[channel]++;
							jwSearchCountRight[channel]=0;
							if(jwSearchCountLeft[channel]>8)
							{
								call('deckSkipBarPrev', channel, 0x7F);
								call('deckSkipBarPrev', channel, 0x00);
								jwSearchCountLeft[channel]=0;
							}
						}else
						{
							jwSearchCountRight[channel]++;
							jwSearchCountLeft[channel]=0;
							if(jwSearchCountRight[channel]>8)
							{
								call('deckSkipBarNext', channel, 0x7F);
								call('deckSkipBarNext', channel, 0x00);
								jwSearchCountRight[channel]=0;
							}
						}
					
					break;
				case 0x40:
					var val1 = (data2>0x40 ? data2-0x80 : data2);
					call('lbMoveCursor', val1);
					break;
			}
			break;
		// note on/off: buttons, switches ('pressing' things)
		case 0x80:
		case 0x90:
		case 0x94:
		case 0x96:
			switch(data1){
				case 0x0B: //playpause
					call('deckPlayPause', channel, data2);							
					break;
				case 0x0C: //cue
					call('deckCue', channel, data2);
					break;
				case 0x12:
					call('deckLoopLess', channel, data2);
					break;
				case 0x13:
					call('deckLoopMore', channel, data2);
					break;
				case 0x14: //loop button
					if(data2){
						if(!getValue('looping', channel)){						
							call('deckLoopInEnd', channel, data2);
						} else {
							debug('loopexit');
							call('deckLoopExit', channel, data2);
						}
					}
										
					break;	
				case 0x2E: //cuepoint1
					if(!shiftButton) call('deckCuePos1', channel, data2); 
					break;
				case 0x2F: //cuepoint2
					if(!shiftButton) call('deckCuePos2', channel, data2); 
					break;
				case 0x30: //cuepoint3
					if(!shiftButton) call('deckCuePos3', channel, data2); 
					break;
				case 0x31: //cuepoint4
					if(!shiftButton) call('deckCuePos4', channel, data2);
					break;
				case 0x36://jogwheel pressed
				//case 0x37:
					call('holdDeckJogWheel', channel, data2);
					break;
				case 0x3C: //Sampler 1				
					if(data2>0x3F) if(channel == 0) call('samplerPlay', 1); else call('samplerPlay',5);
					break;
				case 0x3E: //Sampler 2				
					if(data2>0x3F) if(channel == 0) call('samplerPlay', 2); else call('samplerPlay',6);
					break;
				case 0x40: //Sampler 3				
					if(data2>0x3F) if(channel == 0) call('samplerPlay', 3); else call('samplerPlay',7);
					break;
				case 0x41:
					if(data2>0x3F) call('lbToggleSelect', data2);
					break;
				case 0x42: //Sampler 4				
					if(data2>0x3F) if(channel == 0) call('samplerPlay', 4); else call('samplerPlay',8);
					break;
					
				case 0x43: 											
					if(channel==4) if(data2>0x3F) toggleJogFX(uniqueId, 0,'fx1');//call('deckFxFlanger', 2, data2);
					if(channel==5) if(data2>0x3F) toggleJogFX(uniqueId, 1,'fx1');//call('deckFxFlanger', 3, data2);					
					break;
				case 0x44: 
					if(channel==4) if(data2>0x3F) toggleJogFX(uniqueId, 0,'fx2');//call('deckFxBeatwaw', 2, data2);
					if(channel==5) if(data2>0x3F) toggleJogFX(uniqueId, 1,'fx2');//call('deckFxBeatwaw', 3, data2);					
					break;
				case 0x45: 
					if(channel==4) if(data2>0x3F) toggleJogFX(uniqueId, 0,'fx3');//call('deckFxEcho', 2, data2);
					if(channel==5) if(data2>0x3F) toggleJogFX(uniqueId, 1,'fx3');//call('deckFxEcho', 3, data2);	
					break;
				case 0x46:
					if(data2>0x3F) call('deckLBLoad', 0, data2);
					break;
				case 0x47:
					if(data2>0x3F) call('deckLBLoad', 1, data2);	
					break;
				case 0x4F:
					shiftButton = data2;
					break;	
				case 0x50:					
					call('deckLoop1', channel, data2);//1/2x (manual)
					break;
				case 0x51:					
					call('deckLoop1_4', channel, data2);//loopbutton (manual)
					break;
				case 0x52:					
					call('deckLoop4', channel, data2); //2x (manual)
					break;
				case 0x54: 
					call('deckMonitor', 0, data2); //monitor deck 1
				break;
				case 0x55: 
					call('deckMonitor', 1, data2); //monitor deck 2
				break;
				case 0x58:
					call('deckSync', channel, data2);
					break;
				case 0x5F: //delcuepoint1
					call('deckCuePos1Clear', channel, data2);
					break;
				case 0x60: //delcuepoint2
					call('deckCuePos2Clear', channel, data2);
					break;
				case 0x61: //delcuepoint3
					call('deckCuePos3Clear', channel, data2);
					break;
				case 0x62: //delcuepoint3
					call('deckCuePos4Clear', channel, data2);
					break;
				
			}
		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)
{
	var nameLen = name.length;
	
	if(name=='monitor')		 
	{
		if(deck==0)	sendMidi(uniqueId,0x90,6,0x54,(param1 ? 0x7F : 0x00));
		if(deck==1)	sendMidi(uniqueId,0x90,6,0x55,(param1 ? 0x7F : 0x00));		
	}
	//sync
	if(name=='onbeat'){
		sendMidi(uniqueId,0x90,deck,0x58,(param1 ? 0x7F : 0x00));	
	}	
	if(name=='cuepos1')		sendMidi(uniqueId,0x90,deck,0x2E,(param1 ? 0x7F : 0x00));
	if(name=='cuepos2')		sendMidi(uniqueId,0x90,deck,0x2F,(param1 ? 0x7F : 0x00));
	if(name=='cuepos3')		sendMidi(uniqueId,0x90,deck,0x30,(param1 ? 0x7F : 0x00));
	if(name=='cuepos4')		sendMidi(uniqueId,0x90,deck,0x31,(param1 ? 0x7F : 0x00));
	
	if(nameLen==8)
	{
		var name1 = name.substr(0, nameLen-1);
		if(name1=='sampler')
			{				
				var samplerIdx = parseInt(name.charAt(nameLen-1))-1;		
				if(!param1) 
				{
					samplerBlinkLedStatus[samplerIdx] = 0;
					if(name=='sampler1') sendMidi(uniqueId,0x90,0,0x3C,0x00);
					if(name=='sampler2') sendMidi(uniqueId,0x90,0,0x3E,0x00);
					if(name=='sampler3') sendMidi(uniqueId,0x90,0,0x40,0x00);
					if(name=='sampler4') sendMidi(uniqueId,0x90,0,0x42,0x00);
					if(name=='sampler5') sendMidi(uniqueId,0x90,1,0x3C,0x00);
					if(name=='sampler6') sendMidi(uniqueId,0x90,1,0x3E,0x00);
					if(name=='sampler7') sendMidi(uniqueId,0x90,1,0x40,0x00);
					if(name=='sampler8') sendMidi(uniqueId,0x90,1,0x42,0x00);
					// instead of Math.floor(19/4), parseInt(19/4) = 4 can also be used
				}else
				{
					if(name=='sampler1') sendMidi(uniqueId,0x90,0,0x3C,0x7F);
					if(name=='sampler2') sendMidi(uniqueId,0x90,0,0x3E,0x7F);
					if(name=='sampler3') sendMidi(uniqueId,0x90,0,0x40,0x7F);
					if(name=='sampler4') sendMidi(uniqueId,0x90,0,0x42,0x7F);
					if(name=='sampler5') sendMidi(uniqueId,0x90,1,0x3C,0x7F);
					if(name=='sampler6') sendMidi(uniqueId,0x90,1,0x3E,0x7F);
					if(name=='sampler7') sendMidi(uniqueId,0x90,1,0x40,0x7F);
					if(name=='sampler8') sendMidi(uniqueId,0x90,1,0x42,0x7F);
					if(param2>0) samplerBlinkLedStatus[samplerIdx] = 2;else samplerBlinkLedStatus[samplerIdx] = 1;
				}				
			}
	}
		
	
	
}
//----------------------------------------------------------------------------- 
function getMIDIValueForVU(vu_val)
{
	// translating VU-meter signal from decibels (dB) to 0..127 MIDI range
	var val = 0;
	var step = 12.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);
}
//----------------------------------------------------------------------------- 
// 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)
{
	//samplerBlinkState
	//samplerBlinkLedStatus
	//debug('timerTick ['+uniqueId+']');
	for(var i = 0; i<8; i++){
		switch(i){
			case 0:
			if(samplerBlinkLedStatus[i] == 2){				
				sendMidi(uniqueId,0x90,0,0x3C,(samplerBlinkState[i] ? 0x00:0x7F));
				samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;				
			} else {
				sendMidi(uniqueId,0x90,0,0x3C,0x7F);
			}
			break;
			case 1:
				if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,0,0x3E,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,0,0x3E,0x7F);
				}
			break;
			case 2:
				if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,0,0x40,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,0,0x40,0x7F);
				}
			break;
			case 3:
			if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,0,0x42,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,0,0x42,0x7F);
				}
			break;
			case 4:
			if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,1,0x3C,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,1,0x3C,0x7F);
				}
			break;
			case 5:
			if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,1,0x3E,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,1,0x3E,0x7F);
				}
			break;
			case 6:
			if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,1,0x40,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,1,0x40,0x7F);
				}
			break;
			case 7:
			if(samplerBlinkLedStatus[i] == 2){				
					sendMidi(uniqueId,0x90,1,0x42,(samplerBlinkState[i] ? 0x00:0x7F));
					samplerBlinkState[i] ? samplerBlinkState[i]=0:samplerBlinkState[i]=1;					
				} else {
					sendMidi(uniqueId,0x90,1,0x42,0x7F);
				}
			break;
		}
	}
	//samplerBlinkLedStatus

}
//----------------------------------------------------------------------------- 
function toggleJogFX(uniqueId,ch,mode) // ch:0..3; mode:0 (CtrlA), 1 (FX1), 2 (FX2), 3 (FX3), 4 (CtrlB)
{
	debug('0 toggleJogFX ch='+ch+', mode='+mode);
	var mode2 = -1;
	if(mode=='none')  mode2 = -1;
	if(mode=='ctrla') mode2 = 0;
	if(mode=='fx1')   mode2 = 1;
	if(mode=='fx2')   mode2 = 2;
	if(mode=='fx3')   mode2 = 3;
	if(mode=='ctrlb') mode2 = 4;
	// see if we want to disable the current one
	if(fxLast[ch] == mode2) mode2 = -1;
	// clear the previous one
	if(ch<2)
	{
		switch(fxLast[ch])
		{		
		case 1:	sendMidi(uniqueId,0x90,4+ch,0x43,0); call('deckFxFlangerDW',ch,0x00); break;// FX1
		case 2:	sendMidi(uniqueId,0x90,4+ch,0x44,0); call('deckFxBeatwawDW',ch,0x00); break;// FX2
		case 3:	sendMidi(uniqueId,0x90,4+ch,0x45,0); call('deckFxEchoDW',ch,0x00); break;// FX3		
		}
	}else
	{
		switch(fxLast[ch])
		{
		//case 0:	sendMidi(uniqueId,0x90,4+ch-2,0x47,0); break;// Ctrl+A
		case 1:	sendMidi(uniqueId,0x90,4+ch-2,0x48,0); call('deckFxFlangerDW',ch,0x00); break;// FX1
		case 2:	sendMidi(uniqueId,0x90,4+ch-2,0x49,0); call('deckFxBeatwawDW',ch,0x00); break;// FX2
		case 3:	sendMidi(uniqueId,0x90,4+ch-2,0x4A,0); call('deckFxEchoDW',ch,0x00); break;// FX3
		//case 4:	sendMidi(uniqueId,0x90,4+ch-2,0x4B,0); break;// Ctrl+B
		}
	}
	// set the new one
	fxLast[ch] = mode2;
	if(ch<2)
	{
		switch(fxLast[ch])
		{
		//case 0:	sendMidi(uniqueId,0x90,4+ch,0x42,0x7F); break;// Ctrl+A
		case 1:	sendMidi(uniqueId,0x90,4+ch,0x43,0x7F); call('deckFxFlangerDW',ch,fxdeckSetting[ch]); break;// FX1
		case 2:	sendMidi(uniqueId,0x90,4+ch,0x44,0x7F); call('deckFxBeatwawDW',ch,fxdeckSetting[ch]); break;// FX2
		case 3:	sendMidi(uniqueId,0x90,4+ch,0x45,0x7F); call('deckFxEchoDW',ch,fxdeckSetting[ch]); break;// FX3
		//case 4:	sendMidi(uniqueId,0x90,4+ch,0x46,0x7F); break;// Ctrl+B
		}
	}else
	{
		switch(fxLast[ch])
		{
		//case 0:	sendMidi(uniqueId,0x90,4+ch-2,0x47,0x7F); break;// Ctrl+A
		case 1:	sendMidi(uniqueId,0x90,4+ch-2,0x48,0x7F); break;// FX1
		case 2:	sendMidi(uniqueId,0x90,4+ch-2,0x49,0x7F); break;// FX2
		case 3:	sendMidi(uniqueId,0x90,4+ch-2,0x4A,0x7F); break;// FX3
		//case 4:	sendMidi(uniqueId,0x90,4+ch-2,0x4B,0x7F); break;// Ctrl+B
		}
	}
	//debug('1 toggleJogFX ch='+ch+', mode2='+mode2);
}
