//-----------------------------------------------------------------------------
//-------- Copyright (c)2003-2016. All Rights Reserved. -----------------------
//-----------------------------------------------------------------------------
// file implementing MIDI controller 'Numark Party Mix'
// last revision: 2017-06-07
//Author: Tollen Francisco, 2017-06-07
//
//----------------------------------------------------------------------------- 
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 "Numark DJ2GO2";
}
//----------------------------------------------------------------------------- 
// 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 0x15E4;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDevicePID(osId)
{	
	return 0x004E;	
}
//----------------------------------------------------------------------------- 
// 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 "013F4E001900010102000000000000000000000000000000000000000000F7"; //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 false;
	
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput(osId)
{
	return false;
	
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// some variables necessary only for this particular script

//----------------------------------------------------------------------------- 
// 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)
{
	debug('controllerInit Numark DJ2GO2 ['+uniqueId+']');// this outputs a string to DebugView app on Win
	callSendAllNotifications(uniqueId, true);// send all notifications to the controller (so that we don't have to manually init all leds/lcd screens)
	
	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)
	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:
			if(data2==1) call('lbMoveCursor', 1);else call('lbMoveCursor', -1);
			break;
		case 0x06:
			var val1 = 0x7F - data2 - 0x40;
			call('scratchDeckJW', channel, val1, 10000);
			break;
		case 0x0A:
			call('setMasterGain', data2);
			break;
		case 0x0C:
			call('setMonitorGain', data2);
			break;
		case 0x16:
			call('setDeckVolume', channel, data2);
			break;
		case 0x08:
			call('setCrossfader', data2);
			break;
		case 0x09:
			call('setDeckPitch', channel, 0x7F - data2);
			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('deckPlayPause', channel, data2); //play pause
			break;
		case 0x01:
			if(channel == 4 || channel == 5){
				//cue point 1
				call('deckCuePos1', channel - 4, data2);
			} else {
				call('deckCue', channel, data2); //cue
			}
			
			break;
		case 0x02:
			if(channel == 0x0F){
				if(data2) call('deckLBLoad', 0, data2);
			} else if (channel == 4 || channel == 5) {
				//cuepoint 2
				call('deckCuePos2', channel - 4, data2);
				
			} else {
				call('deckSync' ,channel, data2);
			}
			
			break;
		case 0x03:
			if(channel == 0x0F){
				if(data2) call('deckLBLoad', 1, data2);
			} else if (channel == 4 || channel == 5) {
				//cuepoint 3
				call('deckCuePos3', channel - 4, data2);
			} else {
				
			}
			break;
		case 0x04:
			if (channel == 4 || channel == 5) {
				//cuepoint 4
				call('deckCuePos4', channel - 4, data2);
			}
			break;
		case 0x06:
			if(data2) call('lbToggleSelect', data2);
			break;
		case 0x11:
			call('deckLoop1_8', channel-4, data2);
			break;
		case 0x12:
			call('deckLoop1_2', channel-4, data2);
			break;
		case 0x13:
			call('deckLoop2', channel-4, data2);
			break;
		case 0x14:
			call('deckLoop4', channel-4, data2);
			break;
		case 0x1B:
			
			call('deckMonitor', channel, 0x7F);
			call('deckMonitor', channel, 0x00);
			
			break;
		case 0x21://loop in.
			call('deckLoopInEnd', channel - 4, data2);
			break;
		case 0x22://loop out.
			call('deckLoopInEnd', channel - 4, data2);
			break;
		case 0x23:
			call('deckLoopMore', channel - 4, data2);
			break;
		case 0x24:
			call('deckLoopExit', channel - 4, data2);
			break;
		
		case 0x31:
			 call('samplerPlay', 1);
			break;
		case 0x32:
			 call('samplerPlay', 2);
			break;
		case 0x33:
			 call('samplerPlay', 3);
			break;
		case 0x34:
			 call('samplerPlay', 4);
			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=='play') 		sendMidi(uniqueId,0x90,deck,0x00, (param1 ? 0x7F : 0x01)); //play
	if(name=='cue') 		sendMidi(uniqueId,0x90,deck,0x01,(param1 ? 0x7F : 0X01)); //cue
	if(name=='onbeat') 		sendMidi(uniqueId,0x90,deck,0x02,(param1 ? 0x7F : 0X01)); //play
	if(name=='monitor') 	sendMidi(uniqueId,(param1 > 0 ? 0x90 : 0x80),deck,0x1B,(param1 > 0 ? 0x7F : 0x00));//monitor
	//debug((currentPadMode[deck]).toString());
	
	
	//if(name=='keyLock') 	sendMidi(uniqueId,0x90,deck,0x0D,(param1 ? 0x3F : 0x01));//keylock
	//if(name=='monitor') 	sendMidi(uniqueId,0x90,deck,0x1B,(param1 ? 0x3F : 0x01));//monitor
	//if(name=='reverse')		sendMidi(uniqueId,0x90,deck,0x10,(param1 ? 0x3F : 0x01));//reverse

	if(name=='cuepos1') {	 
	sendMidi(uniqueId,0x90,deck+4,0x01,(param1 ? 0x7F : 0x00)); 		
	
	}//cue 1
	if(name=='cuepos2'){ 	 
		sendMidi(uniqueId,0x90,deck+4,0x02,(param1 ? 0x7F : 0x00)); //cue 2
		
	}
	if(name=='cuepos3'){ 	
		sendMidi(uniqueId,0x90,deck+4,0x03,(param1 ? 0x7F : 0x00)); //cue 3
		
	}
	if(name=='cuepos4'){ 	 
		sendMidi(uniqueId,0x90,deck+4,0x04,(param1 ? 0x7F : 0x00)); //cue 4
		
	}
	
	if(name=='loopSize'){
		sendMidi(uniqueId,0x90,deck+4,0x11, 0x00); //cue 4
		sendMidi(uniqueId,0x90,deck+4,0x12, 0x00); //cue 4
		sendMidi(uniqueId,0x90,deck+4,0x13, 0x00); //cue 4
		sendMidi(uniqueId,0x90,deck+4,0x14, 0x00); //cue 4
		
		switch(param1){
			case 8:
				sendMidi(uniqueId,0x90,deck+4,0x11, 0x7F); //cue 4
				break;
			case 32:
				sendMidi(uniqueId,0x90,deck+4,0x12, 0x7F); //cue 4
				break;
			case 128:
				sendMidi(uniqueId,0x90,deck+4,0x13, 0x7F); //cue 4
				break;
			case 256:
				sendMidi(uniqueId,0x90,deck+4,0x14, 0x7F); //cue 4
				break;
		}
	}
	if(name=='sampler1'){ 
		
		sendMidi(uniqueId,0x90,4,0x31, (param2 ? 0x7F : 0x00)); //sample
	}
	if(name=='sampler2'){ 
		sendMidi(uniqueId,0x90,4,0x32, (param2 ? 0x7F : 0x00)); //sample
	}
	if(name=='sampler3'){ 
		sendMidi(uniqueId,0x90,4,0x33, (param2 ? 0x7F : 0x00)); //sample
	}
	if(name=='sampler4'){ 
		sendMidi(uniqueId,0x90,4,0x34, (param2 ? 0x7F : 0x00)); //sample
	}
	
	if(name=='loopIn') {
		//debug('notif ['+uniqueId+'] name='+name + ' deck='+deck + ' p1(int)='+param1 + ' p2(float)='+param2 + ' p3(str)='+param3);
		sendMidi(uniqueId,0x90,deck + 4, 0x21, (param1 ? 0x7F : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x22, (param1 ? 0x00 : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x23, (param1 ? 0x00 : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x24, (param1 ? 0x00 : 0x00)); //loop in
	}
	if(name=='looping'){
		sendMidi(uniqueId,0x90,deck + 4, 0x21, (param1 ? 0x7F : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x22, (param1 ? 0x7F : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x23, (param1 ? 0x00 : 0x00)); //loop in
		sendMidi(uniqueId,0x90,deck + 4, 0x24, (param1 ? 0x00 : 0x00)); //loop in
	}
	

}


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

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