//-----------------------------------------------------------------------------
//-------- Copyright (c)2003-2013 XYLIO INFO SRL. All Rights Reserved. --------
//-----------------------------------------------------------------------------
// file implementing MIDI controller 'Reloop Contour CE/IE' (script v2)
//----------------------------------------------------------------------------- 
function getLanguageVersion()
{
	return 1;// do not modify this, this should be 1 for all scripts
}
//----------------------------------------------------------------------------- 
function getFileVersion()
{
	return 2;// update this as needed
}
//----------------------------------------------------------------------------- 
// return a user friendly name for the controller supported
function getControllerUserFriendlyName()
{
	return "Reloop Contour CE/IE";
}
//----------------------------------------------------------------------------- 
// 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 0x200C;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDevicePID(osId)
{
	return 0x0010;// Contour CE (Controller Edition)
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceVID2(osId)
{
	return 0x200C;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDevicePID2(osId)
{
	return 0x100A;// Contour IE (Interface Edition)
}
//----------------------------------------------------------------------------- 
// 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 "002079200C";
	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 "Reloop Contour CE";
	//return false;
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForInput2(osId)
{
	return "Reloop CONTOUR";// Contour IE (Interface Edition)
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput(osId)
{
	return "Reloop Contour CE";
}
//----------------------------------------------------------------------------- 
function getSupportedMidiDeviceNameForOutput2(osId)
{
	return "Reloop CONTOUR";// Contour IE (Interface Edition)
}
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// some variables necessary only for this particular script
var jogWheelsInScratchMode=[0,0,0,0];
var jwSearchCountLeft=[0,0,0,0];
var jwSearchCountRight=[0,0,0,0];
var timer1=0;
var loopInPulse=0;
var loopInEnabled=[0,0,0,0];
var fxParams=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[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 Reloop Contour CE/IE ['+uniqueId+']');// this outputs a string to DebugView app on Win
		
	for(var deck=0; deck<4; deck++)
	{
		sendMidi(uniqueId,0x90,deck,0x01,0x00);// 1
		sendMidi(uniqueId,0x90,deck,0x02,0x00);// 2
		sendMidi(uniqueId,0x90,deck,0x03,0x00);// 3
		sendMidi(uniqueId,0x90,deck,0x04,0x00);// 4
		sendMidi(uniqueId,0x90,deck,0x0E,0x00);// FX on
		sendMidi(uniqueId,0x90,deck,0x0F,0x00);// RST
		sendMidi(uniqueId,0x90,deck,0x10,0x00);// FX B1
		sendMidi(uniqueId,0x90,deck,0x11,0x00);// FX B2
		sendMidi(uniqueId,0x90,deck,0x12,0x00);// Loop IN
		sendMidi(uniqueId,0x90,deck,0x52,0x00);// Loop More
		sendMidi(uniqueId,0x90,deck,0x13,0x00);// Loop Exit
		sendMidi(uniqueId,0x90,deck,0x53,0x00);// Reloop
		sendMidi(uniqueId,0x90,deck,0x14,0x00);// Previous Loop
		sendMidi(uniqueId,0x90,deck,0x15,0x00);// Next Loop
		sendMidi(uniqueId,0x90,deck,0x54,0x00);// Loop 1/4
		sendMidi(uniqueId,0x90,deck,0x55,0x00);// Loop 1/2
		sendMidi(uniqueId,0x90,deck,0x1A,(getValue('cuepos1', deck) ? 0x7F : 0x00));// Cuepoint 1
		sendMidi(uniqueId,0x90,deck,0x1B,(getValue('cuepos2', deck) ? 0x7F : 0x00));// Cuepoint 2
		sendMidi(uniqueId,0x90,deck,0x1C,(getValue('cuepos3', deck) ? 0x7F : 0x00));// Cuepoint 3
		sendMidi(uniqueId,0x90,deck,0x1D,(getValue('cuepos4', deck) ? 0x7F : 0x00));// Cuepoint 4
		sendMidi(uniqueId,0x90,deck,0x34,(getValue('cuepos5', deck) ? 0x7F : 0x00));// Cuepoint 5
		sendMidi(uniqueId,0x90,deck,0x35,(getValue('cuepos6', deck) ? 0x7F : 0x00));// Cuepoint 6
		sendMidi(uniqueId,0x90,deck,0x36,(getValue('cuepos7', deck) ? 0x7F : 0x00));// Cuepoint 7
		sendMidi(uniqueId,0x90,deck,0x37,(getValue('cuepos8', deck) ? 0x7F : 0x00));// Cuepoint 8
		sendMidi(uniqueId,0x90,deck,0x25,0x00);// Cueplay
		sendMidi(uniqueId,0x90,deck,0x26,(getValue('cue', deck) ? 0x7F : 0x00));// Cue
		sendMidi(uniqueId,0x90,deck,0x27,(getValue('play', deck) ? 0x7F : 0x00));// Play-pause
		sendMidi(uniqueId,0x90,deck,0x28,0x00);// Sync
		sendMidi(uniqueId,0x90,deck,0x0A,0x00);// FX Sel
		sendMidi(uniqueId,0x90,deck,0x0B,0x00);// FX 1 Sel
		sendMidi(uniqueId,0x90,deck,0x0C,0x00);// FX 2 Sel
		sendMidi(uniqueId,0x90,deck,0x0D,0x00);// Fx 3 Sel
	}
}
//----------------------------------------------------------------------------- 
// 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 Reloop Mixage CE/IE ['+uniqueId+']');
	
	for(var deck=0; deck<4; deck++)
	{
		sendMidi(uniqueId,0x90,deck,0x01,0x00);// 1
		sendMidi(uniqueId,0x90,deck,0x02,0x00);// 2
		sendMidi(uniqueId,0x90,deck,0x03,0x00);// 3
		sendMidi(uniqueId,0x90,deck,0x04,0x00);// 4
		sendMidi(uniqueId,0x90,deck,0x0E,0x00);// FX on
		sendMidi(uniqueId,0x90,deck,0x0F,0x00);// RST
		sendMidi(uniqueId,0x90,deck,0x10,0x00);// FX B1
		sendMidi(uniqueId,0x90,deck,0x11,0x00);// FX B2
		sendMidi(uniqueId,0x90,deck,0x12,0x00);// Loop IN
		sendMidi(uniqueId,0x90,deck,0x52,0x00);// Loop More
		sendMidi(uniqueId,0x90,deck,0x13,0x00);// Loop Exit
		sendMidi(uniqueId,0x90,deck,0x53,0x00);// Reloop
		sendMidi(uniqueId,0x90,deck,0x14,0x00);// Previous Loop
		sendMidi(uniqueId,0x90,deck,0x15,0x00);// Next Loop
		sendMidi(uniqueId,0x90,deck,0x54,0x00);// Loop 1/4
		sendMidi(uniqueId,0x90,deck,0x55,0x00);// Loop 1/2
		sendMidi(uniqueId,0x90,deck,0x1A,0x00);// Cuepoint 1
		sendMidi(uniqueId,0x90,deck,0x34,0x00);// Cuepoint 5
		sendMidi(uniqueId,0x90,deck,0x1B,0x00);// Cuepoint 2
		sendMidi(uniqueId,0x90,deck,0x35,0x00);// Cuepoint 6
		sendMidi(uniqueId,0x90,deck,0x1C,0x00);// Cuepoint 3
		sendMidi(uniqueId,0x90,deck,0x36,0x00);// Cuepoint 7
		sendMidi(uniqueId,0x90,deck,0x1D,0x00);// Cuepoint 4
		sendMidi(uniqueId,0x90,deck,0x37,0x00);// Cuepoint 8
		sendMidi(uniqueId,0x90,deck,0x25,0x00);// Cueplay
		sendMidi(uniqueId,0x90,deck,0x26,0x00);// Cue
		sendMidi(uniqueId,0x90,deck,0x27,0x00);// Play-pause
		sendMidi(uniqueId,0x90,deck,0x28,0x00);// Sync
		sendMidi(uniqueId,0x90,deck,0x0A,0x00);// FX Sel
		sendMidi(uniqueId,0x90,deck,0x0B,0x00);// FX 1 Sel
		sendMidi(uniqueId,0x90,deck,0x0C,0x00);// FX 2 Sel
		sendMidi(uniqueId,0x90,deck,0x0D,0x00);// Fx 3 Sel
	}
}
//----------------------------------------------------------------------------- 
// 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: pitch sliders ('moving' things)
	case 0xE0:
		// attn: we're only using 7bit	
		call('setDeckPitch', channel, data2);
		break;
	//-----------------------------------------------
	// controllers: sliders, knobs, jog-wheels, encoders ('moving' things)
	case 0xB0:
		switch(data1)
		{
		//global		
		case 0x09: call('lbMoveCursor', data2-0x40); break;
		case 0x6D: call('setMonitorGain', data2); break;
		case 0x6E: call('setMasterGain', data2); break;

		//per deck
		case 0x2D: call('setDeckCutoff', channel, data2); break;
		case 0x2E: call('setDeckPitchKey', channel, data2); break;
		
		case 0x16: if(data2==0x3F) call('deckLoopLess', channel, data2); else call('deckLoopMore', channel, data2); break; //loop knob x2 or /2
		case 0x17: if(data2==0x3F) call('deckLoopPrev', channel, data2); else call('deckLoopNext', channel, data2); break; //loop knob prev/next
		// jog-wheel has a lot of different modes (add 0x40 if SHIFT is also pressed)
		// --------------------------------------------------------------------------------
		// mode					code -> | side move   toL   toR | middle move   toL   toR |
		// --------------------------------------------------------------------------------
		// normal						|				0x2F	| 0x2F on press		0x2F  |
		// scratch button on			|  0x90|0x7F  0x39 0x38	| 0x30 on press		0x30  |
		// pitch bend button on			|				0x31	| 0x31 on press		0x31  |
		// search button on				|				0x32	| 0x32 on press		0x32  |
		// trax button on				|				0x33	| 0x33 on press		0x33  |
		// --------------------------------------------------------------------------------
		// params: (deck, increment, total positions per complete revolution) 
		case 0x2F: // normal (all buttons disabled)
			var val1 = data2-0x40;
			if(jogWheelsInScratchMode[channel]) call('scratchDeckJW', channel, val1, 150);else call('moveDeckJogWheel', channel, val1, 150);
			break;
		case 0x30: // scratch on
			var val1 = data2-0x40;
			call('scratchDeckJW', channel, val1, 150);
			break;
		case 0x31: // pitch bend on
			var val1 = data2-0x40;
			call('moveDeckJogWheel', channel, val1, 150);
			break;
		case 0x32: // search on
		case 0x33: // trax on (also search but with bigger fwd/rev)
			var skipCnt = 8;
			if(data1==0x33) skipCnt = 3;
			var val1 = data2-0x40;
			if(val1<0)
			{
				jwSearchCountLeft[channel]++;
				jwSearchCountRight[channel]=0;
				if(jwSearchCountLeft[channel]>skipCnt)
				{
					call('deckSkipBarPrev', channel, 0x7F);
					call('deckSkipBarPrev', channel, 0x00);
					jwSearchCountLeft[channel]=0;
				}
			}else
			{
				jwSearchCountRight[channel]++;
				jwSearchCountLeft[channel]=0;
				if(jwSearchCountRight[channel]>skipCnt)
				{
					call('deckSkipBarNext', channel, 0x7F);
					call('deckSkipBarNext', channel, 0x00);
					jwSearchCountRight[channel]=0;
				}
			}
			break;
			
		// fx faders
		case 0x29: call('deckFxFlangerDW', channel, data2); break;
		case 0x2A: call('deckFxBeatwawDW', channel, data2); break;
		case 0x2B: call('deckFxEchoDW', channel, data2); break;
		case 0x2C: call('deckFxPanDW', channel, data2); break;
		
		// fx controllers (a/b/c/d + led strips)
		case 0x0A:
		case 0x0B:
		case 0x0C:
		case 0x0D:
			var val1 = data2-0x40;
			var fxId = data1 - 0x0A;
			var oldVal = fxParams[channel][fxId];
			fxParams[channel][fxId] += val1*8;
			if(fxParams[channel][fxId]<0)   fxParams[channel][fxId] = 0; 
			if(fxParams[channel][fxId]>127) fxParams[channel][fxId] = 127;
			// set the param
			if(fxParams[channel][fxId] != oldVal)
			{
				if(data1==0x0A) call('deckFxFlangerP1', channel, fxParams[channel][fxId]);
				if(data1==0x0B) call('deckFxBeatwawP1', channel, fxParams[channel][fxId]);
				if(data1==0x0C) call('deckFxEchoP1', channel, fxParams[channel][fxId]);
				if(data1==0x0D) call('deckFxPanP1', channel, fxParams[channel][fxId]);
				// set the FX led strip
				sendMidi(uniqueId,0x90,channel,data1,fxParams[channel][fxId]);
				//debug('fx p1 '+fxParams[channel][fxId]);
			}
			break;
		
		default: messageNotProcessed = true;
		}
		break;
	//-----------------------------------------------
	// note on/off: buttons, switches ('pressing' things)
	case 0x80:
	case 0x90:
		switch(data1)
		{
		//global
		case 0x09: if(data2>0x3F) call('deckLBLoad', channel, data2); break;//if(data2>0x3F) call('lbToggleSelect', data2); break;
		
		//per deck
		//decks
		case 0x28: call('deckSync', channel,data2); break;
		case 0x26: call('deckCue', channel, data2); break;
		case 0x25: call('deckCuePlay', channel, data2); break;
		case 0x27: call('deckPlayPause', channel, data2); break;// ok
		case 0x1A: call('deckCuePos1', channel, data2); break;
		case 0x1B: call('deckCuePos2', channel, data2); break;
		case 0x1C: call('deckCuePos3', channel, data2); break;
		case 0x1D: call('deckCuePos4', channel, data2); break;
		case 0x34: call('deckCuePos5', channel, data2); break;
		case 0x35: call('deckCuePos6', channel, data2); break;
		case 0x36: call('deckCuePos7', channel, data2); break;
		case 0x37: call('deckCuePos8', channel, data2); break;
		case 0x15: call('deckLoopNext', channel, data2); break;
		case 0x14: call('deckLoopPrev', channel, data2); break;
		case 0x54: call('deckLoop1_4', channel, data2); break;
		case 0x55: call('deckLoop1_2', channel, data2); break;
		case 0x12: call('deckLoopInEnd', channel, data2); break;
		case 0x52: call('deckLoopMore', channel, data2); break;
		case 0x13: call('deckLoopExit', channel, data2); break;
		case 0x53: call('deckLoopReloop', channel, data2); break;
		case 0x08: call('deckKeyLock', channel, data2); break;
		case 0x07: call('deckFxSel', channel, data2); break;
		//case 0x04: call('deckScratch', channel, data2); break;
		case 0x16: // loop in/out/exit
		case 0x17: if(!getValue('looping', channel)) call('deckLoopInEnd', channel, data2);else call('deckLoopExit', channel, data2); break; //Loop
		// jog-wheel hold
		case 0x2F: // normal
		case 0x30: // scratch on
		//case 0x31: // pitch bend on
			jogWheelsInScratchMode[channel] = (jogWheelsInScratchMode[channel]+1) % 2; // keep the remainder to toggle between scratch mode "0" or jog bend mode "1"
			call('holdDeckJogWheel', channel, jogWheelsInScratchMode[channel]);
			break;
		// the jog-wheel sends NoteOn values when the scratch button is on (sends 0x39 for left, 0x38 for right; value 0x7F)
		case 0x39: // scratch on (move jw to left)
		case 0x38: // scratch on (move jw to right)
			var val1 = -1;
			if(data2==0x7F)
			{
				if(data1==0x38) val1 = 1;
				call('scratchDeckJW', channel, val1, 150);
			}
			break;
		// fx buttons (e/f/10/11 + leds)
		case 0x0A: call('deckEqLowKill', channel, data2); break;// fx 1
		case 0x0B: call('deckEqMidKill', channel, data2); break;// fx 2
		case 0x0C: call('deckEqHighKill', channel, data2); break;// fx 3
		case 0x0D: call('deckBrake', channel, data2); break;// fx 4
		
		/*
		case 0x4A: if(getValue('looping', 0) || getValue('loopIn', 0)) call('deckLoopExit', 0, data2);else call('deckLoopReloop', 0, data2); 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);
	if(name=='cue') 		 sendMidi(uniqueId,0x90,deck,0x26,(param1 ? 0x7F : 0x00));	
	if(name=='play') 		 sendMidi(uniqueId,0x90,deck,0x27,(param1 ? 0x7F : 0x00));	
	if(name=='onbeat') 		 sendMidi(uniqueId,0x90,deck,0x28,(param1 ? 0x7F : 0x00));	
	if(name=='cuepos1')		 sendMidi(uniqueId,0x90,deck,0x1A,(param1 ? 0x7F : 0x00));
	if(name=='cuepos2')		 sendMidi(uniqueId,0x90,deck,0x1B,(param1 ? 0x7F : 0x00));
	if(name=='cuepos3')		 sendMidi(uniqueId,0x90,deck,0x1C,(param1 ? 0x7F : 0x00));
	if(name=='cuepos4')		 sendMidi(uniqueId,0x90,deck,0x1D,(param1 ? 0x7F : 0x00));
	if(name=='cuepos5')		 sendMidi(uniqueId,0x90,deck,0x34,(param1 ? 0x7F : 0x00));
	if(name=='cuepos6')		 sendMidi(uniqueId,0x90,deck,0x35,(param1 ? 0x7F : 0x00));
	if(name=='cuepos7')		 sendMidi(uniqueId,0x90,deck,0x36,(param1 ? 0x7F : 0x00));
	if(name=='cuepos8')		 sendMidi(uniqueId,0x90,deck,0x37,(param1 ? 0x7F : 0x00));

/*
	if(name=='fxFlanger')  { sendMidi(uniqueId,0x90,0,(deck==0)?0x31:0x45,(param1 ? 0x7F : 0x00)); fxParams[4*deck + 1] = 127*param1;}
	if(name=='fxBeatwaw')  { sendMidi(uniqueId,0x90,0,(deck==0)?0x33:0x44,(param1 ? 0x7F : 0x00)); fxParams[4*deck + 0] = 127*param1;}
	if(name=='fxEcho') 	   { sendMidi(uniqueId,0x90,0,(deck==0)?0x30:0x47,(param1 ? 0x7F : 0x00)); fxParams[4*deck + 3] = 127*param1;}
	if(name=='fxPan') 	   { sendMidi(uniqueId,0x90,0,(deck==0)?0x32:0x46,(param1 ? 0x7F : 0x00)); fxParams[4*deck + 2] = 127*param1;}
	if(name=='monitor') 	 sendMidi(uniqueId,0x90,0,(deck==0)?0x35:0x40,(param1 ? 0x7F : 0x00));
	if(name=='keyLock') 	 sendMidi(uniqueId,0x90,0,(deck==0)?0x36:0x41,(param1 ? 0x7F : 0x00));	
*/
	
	if(name=='loopIn')
	{
		// buttons leds
		sendMidi(uniqueId,0x90,deck,0x12,(param1 ? 0x7F : 0x00));// loop in
		loopInEnabled[deck] = param1;
	}
	if(name=='looping')
	{
		// buttons leds
		sendMidi(uniqueId,0x90,deck,0x12,(param1 ? 0x7F : 0x00));// loop in
		sendMidi(uniqueId,0x90,deck,0x13,(param1 ? 0x7F : 0x00));// loop exit(out)
		sendMidi(uniqueId,0x90,deck,0x14,(param1 ? 0x7F : 0x00));// loop <
		sendMidi(uniqueId,0x90,deck,0x15,(param1 ? 0x7F : 0x00));// loop >
	}	
}
//----------------------------------------------------------------------------- 
// 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+']');
	// limit the amount of time this gets executed
	timer1++; if(timer1<4) return;else timer1 = 0;
	//
	for(var deck=0; deck<2; deck++)
	{
		if(loopInEnabled[deck]) sendMidi(uniqueId,0x90,deck,0x12,(loopInPulse ? 0x7F : 0x00));// loop in
	}
	if(loopInPulse==0) loopInPulse = 1;else loopInPulse = 0;
}
//----------------------------------------------------------------------------- 
