//-----------------------------------------------------------------------------
//-------- Copyright (c)2003-2011. All Rights Reserved. -----------------------
//-----------------------------------------------------------------------------
// file implementing MIDI controller ' Akiyama Quark SC
// Version: 1.0 11/11/12
//Author: Brandon James
//----------------------------------------------------------------------------- 
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 "Akiyama Quark SC";
}
//----------------------------------------------------------------------------- 
// 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 (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 "002079200C10";
	
	// full string:
	// 00  F0 7E 7F 06 02 00 20 79  20 0C 10 12 00 00 00 01 10  F7
	
	//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 "Midi port name ";// !!! 
	return false;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput(osId)
{
	//return " midi port name ";// !!! MAKE SURE THIS IS INDEED OK !!!
	return false;
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// some variables necessary only for this particular script
var shiftButton=[0,0,0,0];
var delCue=[0,0,0,0];
var loopingInBlinkLed=[-1,-1,-1,-1];// -1 means disabled
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)
{
	debug('controllerInit QuarkSc ['+uniqueId+']');// this outputs a string to DebugView app on Win
	callSendAllNotifications(uniqueId, true)
	for(var i=0; i<4; i++)
	{
	
			sendMidi(uniqueId,0x90,i,0x37,0x00); //scratch off
			sendMidi(uniqueId,0xB0,i,0x3D,0x00); //Lvl LED off
			
		
		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)
{
	debug('controllerDeinit QuarkSc ['+uniqueId+']');
	callSendAllNotifications(uniqueId, false);
	for(var i=0; i<4; i++)
	{
		
		sendMidi(uniqueId,0x90,i,0x37,0x00); //scratch off
		sendMidi(uniqueId,0xB0,i,0x3D,0x00); //Lvl LED off
		
		

		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)
{
	var messageNotProcessed=false;
	switch(status)
	{
	//-----------------------------------------------
	// controllers: sliders, knobs, jog-wheels, encoders ('moving' things)
	case 0xB0:
		switch(data1)
		{
		// global





		// decks
		case 0x3B: call('setDeckVolume', channel, data2); break; //volume slider
		case 0x38: call('setDeckPitch', channel, data2); break; //pitch slider
		case 0x09: call('setDeckGain', channel, data2); break; // gain
		case 0x0A: call('setDeckEqHigh', channel, data2); break; // eq high
		case 0x0B: call('setDeckEqMid', channel, data2); break; // eq mid
		case 0x0C: call('setDeckEqLow', channel, data2); break; // eq low deckLoopMore  deckLoopLess
		
		//deck selector knob changes note on loop mode simulate fast press
		case 0x2C:
   					if(data2==0x3F){ call('deckLoopLess', channel, 0x7F); call('deckLoopLess', channel, 0x00);}
   					if(data2==0x41){ call('deckLoopMore', channel, 0x7F); call('deckLoopMore', channel, 0x00);}
  					break;
		case 0x2D:
   					if(data2==0x3F){ call('deckLoopLess', channel, 0x7F); call('deckLoopLess', channel, 0x00);}
   					if(data2==0x41){ call('deckLoopMore', channel, 0x7F); call('deckLoopMore', channel, 0x00);}
  					break;
		case 0x2E:
   					if(data2==0x3F){ call('deckLoopLess', channel, 0x7F); call('deckLoopLess', channel, 0x00);}
   					if(data2==0x41){ call('deckLoopMore', channel, 0x7F); call('deckLoopMore', channel, 0x00);}
  					break;

		
		//deck selector + shift changes note on each loop mode simulate fast press and release
	
		/*
		case 0x6C:
		case 0x6D:
		case 0x6E: 
		*/
		
		// sp/fx section left channels 6/7  sp/fx right channels 8/9
		
		case 0x01:  if(channel==4) call('setMasterGain', data2);
					if(channel==5) call('deckFxFlangerP1', 0, data2);
					if(channel==6) call('samplerVolume', 1, data2);	 
					if(channel==7) call('deckFxFlangerP1', 1, data2);
					if(channel==8) call('samplerVolume', 5, data2);
					break; //P1 knob
							
		case 0x02:  if(channel==4) call('lbMoveCursor', data2==0x41 ? 1:-1);
					if(channel==5) call('deckFxBeatwawP1', 0, data2);
					if(channel==6) call('samplerVolume', 2, data2);	 
					if(channel==7) call('deckFxBeatwawP1', 1, data2);
					if(channel==8) call('samplerVolume', 6, data2);
					break; //P2 knob			
		
		case 0x03:  if(channel==5) call('setDeckPitchKey', 0, data2);
					if(channel==6) call('samplerVolume', 3, data2);	 
					if(channel==7) call('setDeckPitchKey', 1, data2);
					if(channel==8) call('samplerVolume', 7, data2);
					break; //P3 knob	
		
		
		case 0x04:  if(channel==4) call('setCrossfader', data2);
					if(channel==5) call('setDeckCutoff', 0, data2);
					if(channel==6) call('samplerVolume', 4, data2);	 
					if(channel==7) call('setDeckCutoff', 1, data2);
					if(channel==8) call('samplerVolume', 8, data2);
					break; //P4 knob
		
		
		
		case 0x05: call('setDeckCutoff', channel, data2); break; // Hp filter
				
		case 0x39: 
				var val1 = data2-0x40;
				if(jogWheelsInScratchMode[channel]) call('scratchDeckJW', channel, val1, 75);else call('moveDeckJogWheel', channel, val1, 75);
				break;	
				
		default: messageNotProcessed = true;
		}
		break;
	//-----------------------------------------------
	// note on/off: buttons, switches ('pressing' things)
	case 0x80:
	case 0x90:
		//if(status==0x90) data2 = 0x7F;
		//if(status==0x80) data2 = 0;
		switch(data1)
		{
		// global
		
		
		//decks alt functions
		case 0x3F: shiftButton[channel] = data2; sendMidi(uniqueId,0x90,channel,0x3F,data2); break; //shift button
		case 0x16: delCue[channel] = data2; sendMidi(uniqueId,0x90,channel,0x16,data2); break;
		
		// decks
		case 0x3B: call('deckLBLoad', channel, data2); break; //load deck	
		case 0x34: call('deckPlayPause', channel, data2); break; //play pause 
		case 0x35: call('deckCue', channel, data2); break; //cue
		case 0x36: call('deckSync', channel, data2); break; //sync
		case 0x76: call('deckMatch', channel, data2); break; //sync +shift = match
		case 0x3C: call('deckMonitor', channel, data2); break; //pfl
		
		case 0x0A: if(data2>0x3F) call('deckEqHighKill', channel, data2); break; // eq high Kill
		case 0x0B: if(data2>0x3F) call('deckEqMidKill', channel, data2); break; // eq mid kill
		case 0x0C: if(data2>0x3F) call('deckEqLowKill', channel, data2); break; // eq low kill
		
	
		case 0x17: if(delCue[channel]<0x7F) call('deckCuePos1', channel, data2);else call('deckCuePos1Clear', channel, data2); break; //cue1 
		case 0x1A: if(delCue[channel]<0x7F) call('deckCuePos2', channel, data2);else call('deckCuePos2Clear', channel, data2); break; //cue2
		case 0x1D: if(delCue[channel]<0x7F) call('deckCuePos3', channel, data2);else call('deckCuePos3Clear', channel, data2); break; //cue3
		case 0x20: if(delCue[channel]<0x7F) call('deckCuePos4', channel, data2);else call('deckCuePos4Clear', channel, data2); break; //cue4
		case 0x23: if(delCue[channel]<0x7F) call('deckCuePos5', channel, data2);else call('deckCuePos5Clear', channel, data2); break; //cue5
		case 0x26: if(delCue[channel]<0x7F) call('deckCuePos6', channel, data2);else call('deckCuePos6Clear', channel, data2); break; //cue6
		
		case 0x18: call('deckLoop1', channel, data2); break; //loop 1
		case 0x1B: call('deckLoop2', channel, data2); break; //loop 2
		case 0x1E: call('deckLoop4', channel, data2); break; //loop 4
		case 0x21: call('deckLoop8', channel, data2); break; //loop 8
		case 0x24: call('deckLoop16', channel, data2); break; //loop 16
		case 0x27: call('deckLoop32', channel, data2); break; //loop 32
		
		case 0x19: call('deckLoop1_32', channel, data2); break; //loop 1/32
		case 0x1C: call('deckLoop1_16', channel, data2); break; //loop 1/16
		case 0x1F: call('deckLoop1_8', channel, data2); break; //loop 1/8
		case 0x22: call('deckLoop1_4', channel, data2); break; //loop 1/4
		case 0x25: call('deckLoop1_2', channel, data2); break; //loop 1/2
		case 0x28: call('deckLoop1', channel, data2); break; //loop 1	
		
		case 0x32: call('deckBendDown', channel, data2); break; //bend down
		
		case 0x72:	if(data2>0x3F)
					{ 
					var currentPitchRange = getValue('pitchRange');
					currentPitchRange = currentPitchRange + 1; if(currentPitchRange>6) currentPitchRange = 1;
					call('setPitchRange', currentPitchRange);
					} break; //bend -  + Shift = pitch range
		
		case 0x33: call('deckBendUp', channel, data2); break; //bend +
		case 0x73: call('deckResetPitch', channel, data2); break; //bend+ / +shift = reset pitch
		
		case 0x2F: call('deckLoopInEnd', channel, data2); break; //Loop In / end
		case 0x30: call('deckLoopExit', channel, data2); break; //Loop out
		case 0x31: call('deckLoopReloop', channel, data2); sendMidi(uniqueId,0x90,channel,0x31,data2); break; //reloop	
		
		//sp/fx knob press
		case 0x01: 	if(channel==5) call('deckFxFlanger', 0, data2); 
				   	if(channel==6) call('samplerPlay', 1);
				   	if(channel==7) call('deckFxFlanger', 1, data2); 
				   	if(channel==8) call('samplerPlay', 5);
					break; //deck FX flanger / sampler 1 /5 play
					
		case 0x02: 	if(channel==4) if(data2>0x3F) call('lbToggleSelect', data2); //slection knob press
					if(channel==5) call('deckFxBeatwaw', 0, data2); 
				   	if(channel==6) call('samplerPlay', 2);
				   	if(channel==7) call('deckFxBeatwaw', 1, data2); 
				   	if(channel==8) call('samplerPlay', 6);
					break; //deck FX beatwaw / sampler 1 play
					
		case 0x03: 	if(channel==4) call('mixNext', data2); 
					if(channel==5) call('deckKeyLock', 0, data2); //key effect no on or off so key lock is substituted
				   	if(channel==6) call('samplerPlay', 3);
				   	if(channel==7) call('deckKeyLock', 1, data2); //key effect no on or off so key lock is substituted
				   	if(channel==8) call('samplerPlay', 7);
					break; //deck  key lock / sampler 1 play
					
		case 0x04: 	if(channel==5) call('deckFxPhaser', 0, data2); //filter effect no on or off so phaser is substituted
				   	if(channel==6) call('samplerPlay', 4);
				   	if(channel==7) call('deckFxPhaser', 1, data2); //filter effect no on or off so phaser is substituted
				   	if(channel==8) call('samplerPlay', 8);
					break; //deck FX flanger / sampler 1 play

		
		case 0x37: if(data2>0x3F) jogWheelsInScratchMode[channel] = (jogWheelsInScratchMode[channel]+1)%2; sendMidi(uniqueId,0x90,channel,0x37,(jogWheelsInScratchMode[channel] ? 0x7F : 0x00)); break; 
		case 0x39: if(jogWheelsInScratchMode[channel]) call('holdDeckJogWheel', channel, data2); break;
		
		
		
		
		
		default: messageNotProcessed = true;
		}
	//-----------------------------------------------
	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);
	if(deck<4)
	{
		if(name=='cue') 		 sendMidi(uniqueId,0x90,deck,0x35,(param1 ? 0x7F : 0x00)); // cue
		if(name=='play') 		 sendMidi(uniqueId,0x90,deck,0x34,(param1 ? 0x7F : 0x00)); //play
		if(name=='onbeat') 		 sendMidi(uniqueId,0x90,deck,0x36,(param1 ? 0x7F : 0x00)); //sync
		if(name=='monitor') 	 sendMidi(uniqueId,0x90,deck,0x3C,(param1 ? 0x7F : 0x00)); //pfl
		
		if(name=='cuepos1') 	 sendMidi(uniqueId,0x90,deck,0x17,(param1 ? 0x7F : 0x00)); //cue 1
		if(name=='cuepos2') 	 sendMidi(uniqueId,0x90,deck,0x1A,(param1 ? 0x7F : 0x00)); //cue 2
		if(name=='cuepos3') 	 sendMidi(uniqueId,0x90,deck,0x1D,(param1 ? 0x7F : 0x00)); //cue 3
		if(name=='cuepos4') 	 sendMidi(uniqueId,0x90,deck,0x20,(param1 ? 0x7F : 0x00)); //cue 4
		if(name=='cuepos5') 	 sendMidi(uniqueId,0x90,deck,0x23,(param1 ? 0x7F : 0x00)); //cue 5
		if(name=='cuepos6') 	 sendMidi(uniqueId,0x90,deck,0x26,(param1 ? 0x7F : 0x00)); //cue 6
		
		if(name=='killHigh') 	 sendMidi(uniqueId,0x90,deck,0x0A,(param1 ? 0x7F : 0x00)); //kill hi led
		if(name=='killMid') 	 sendMidi(uniqueId,0x90,deck,0x0B,(param1 ? 0x7F : 0x00)); //kill mid led
		if(name=='killLow') 	 sendMidi(uniqueId,0x90,deck,0x0C,(param1 ? 0x7F : 0x00)); //kill low led
		
		if(name=='sampler1') 	 sendMidi(uniqueId,0x90,6,0x01,(param1 ? 0x7F : 0x00)); //sampler 1
		if(name=='sampler2') 	 sendMidi(uniqueId,0x90,6,0x02,(param1 ? 0x7F : 0x00)); //sampler 2
		if(name=='sampler3') 	 sendMidi(uniqueId,0x90,6,0x03,(param1 ? 0x7F : 0x00)); //sampler 3
		if(name=='sampler4') 	 sendMidi(uniqueId,0x90,6,0x04,(param1 ? 0x7F : 0x00)); //sampler 4
		if(name=='sampler5') 	 sendMidi(uniqueId,0x90,8,0x01,(param1 ? 0x7F : 0x00)); //sampler 5
		if(name=='sampler6') 	 sendMidi(uniqueId,0x90,8,0x02,(param1 ? 0x7F : 0x00)); //sampler 6
		if(name=='sampler7') 	 sendMidi(uniqueId,0x90,8,0x03,(param1 ? 0x7F : 0x00)); //sampler 7
		if(name=='sampler8') 	 sendMidi(uniqueId,0x90,8,0x04,(param1 ? 0x7F : 0x00)); //sampler 8
		
		if(name=='keyLock') 	{
								if(deck==0) sendMidi(uniqueId,0x90,5,0x03,(param1 ? 0x7F : 0x00));
								if(deck==1) sendMidi(uniqueId,0x90,7,0x03,(param1 ? 0x7F : 0x00));
								}
		if(name=='fxFlanger') 	{
								if(deck==0) sendMidi(uniqueId,0x90,5,0x01,(param1 ? 0x7F : 0x00));
								if(deck==1) sendMidi(uniqueId,0x90,7,0x01,(param1 ? 0x7F : 0x00));
								}
		if(name=='fxBeatwaw') 	{
								if(deck==0) sendMidi(uniqueId,0x90,5,0x02,(param1 ? 0x7F : 0x00));
								if(deck==1) sendMidi(uniqueId,0x90,7,0x02,(param1 ? 0x7F : 0x00));
								}
		if(name=='fxPhaser') 	{
								if(deck==0) sendMidi(uniqueId,0x90,5,0x04,(param1 ? 0x7F : 0x00));
								if(deck==1) sendMidi(uniqueId,0x90,7,0x04,(param1 ? 0x7F : 0x00));
								}
		if(name=='loopIn')
			{
			sendMidi(uniqueId,0x90,deck,0x2F,(param1 ? 0x7F : 0x00));// Loop In (on)
			// activate blinking for the LoopIn led (so the user knows to press it again)
			if(param1) loopingInBlinkLed[deck] = 0;else loopingInBlinkLed[deck] = -1;
			}
		
			
		if(name=='looping')
			{
			sendMidi(uniqueId,0x90,deck,0x2F,(param1 ? 0x7F : 0x00));// Loop In (off)		
			sendMidi(uniqueId,0x90,deck,0x30,(param1 ? 0x7F : 0x00));// Loop Out (on / off)
			}	
			

		 if(name=='loopSize')
			{
			
			// calculate the new led to power on
				var l132, l116, l18, l14, l12, l1, l2, l4, l8, l16, l32;
				l132 = l116 = l18 = l14 = l12 = l1 = l2 = l4 = l8 = l16 = l32 = 0;
				switch(param1)
				{
				case  2: l132 = 0x7F; break; //loop 1/32
				case  4: l116 = 0x7F; break; //loop 1/16
				case  8: l18 = 0x7F; break; //loop 1/8
				case  16: l14 = 0x7F; break; //loop 1/4
				case  32: l12 = 0x7F; break; //loop 1/2
				case  64: l1 = 0x7F; break; //loop 1
				case  128: l2 = 0x7F; break; //loop 2
				case  256: l4 = 0x7F; break; //loop 4
				case  512: l8 = 0x7F; break; //loop 8
				case  1024: l16 = 0x7F; break; //loop 16
				case  2048: l32 = 0x7F; break; //loop 32		
				}
				if(deck<4)
				{
					sendMidi(uniqueId,0x90,deck,0x19,l132); //loop 1/32
					sendMidi(uniqueId,0x90,deck,0x1C,l116); //loop 1/16	
					sendMidi(uniqueId,0x90,deck,0x1F,l18); //loop 1/8
					sendMidi(uniqueId,0x90,deck,0x22,l14); //loop 1/4
					sendMidi(uniqueId,0x90,deck,0x25,l12); //loop 1/2
					sendMidi(uniqueId,0x90,deck,0x18,l1); //loop 1 / loop mode
					sendMidi(uniqueId,0x90,deck,0x28,l1); //loop 1 /loop roll mode	
					sendMidi(uniqueId,0x90,deck,0x1B,l2); //loop 2
					sendMidi(uniqueId,0x90,deck,0x1E,l4); //loop 4 
					sendMidi(uniqueId,0x90,deck,0x21,l8); //loop 8
					sendMidi(uniqueId,0x90,deck,0x24,l16); //loop 16
					sendMidi(uniqueId,0x90,deck,0x27,l32); //loop 32
				}
			}	
				
			if((name=='looping')&&(!param1))
				{
				sendMidi(uniqueId,0x90,deck,0x19,0); //loop 1/32
				sendMidi(uniqueId,0x90,deck,0x1C,0); //loop 1/16
				sendMidi(uniqueId,0x90,deck,0x1F,0); //loop 1/8
				sendMidi(uniqueId,0x90,deck,0x22,0); //loop 1/4
				sendMidi(uniqueId,0x90,deck,0x25,0); //loop 1/2
				sendMidi(uniqueId,0x90,deck,0x18,0); //loop 1 / loop mode
				sendMidi(uniqueId,0x90,deck,0x28,0); //loop 1 / loop roll mode
				sendMidi(uniqueId,0x90,deck,0x1B,0); //loop 2
				sendMidi(uniqueId,0x90,deck,0x1E,0); //loop 4 
				sendMidi(uniqueId,0x90,deck,0x21,0); //loop 8
				sendMidi(uniqueId,0x90,deck,0x24,0); //loop 16
				sendMidi(uniqueId,0x90,deck,0x27,0); //loop 32

				}
	}
}
//----------------------------------------------------------------------------- 
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)
{
	//debug('timerTick ['+uniqueId+']');


	for(var i=0; i<4; i++)
	{
	
		var vuDeck = getValue('vumeterDeck', i);// float dB
		sendMidi(uniqueId,0xB0,i,0x3D,getMIDIValueForVU(vuDeck));
			
		if(loopingInBlinkLed[i]!=-1)
		{
			// actually set the led
			sendMidi(uniqueId,0x90,i,0x2F,((loopingInBlinkLed[i]<2) ? 0x7F : 0x00));// Loop In (on or off)
			loopingInBlinkLed[i]++;
			if(loopingInBlinkLed[i]>=4) loopingInBlinkLed[i] = 0;
		}
		
			
	
	
	}
}
//----------------------------------------------------------------------------- 
