summaryrefslogtreecommitdiffstats
path: root/res/controllers/DJ-Tech-Kontrol-One-scripts.js
diff options
context:
space:
mode:
authorRJ Ryan <rryan@mixxx.org>2013-06-19 00:46:54 -0400
committerRJ Ryan <rryan@mixxx.org>2013-06-19 00:46:54 -0400
commit25d57b59dff3947212909634864dd82365c9606b (patch)
treef0d0f8a048f8ed2f45c5ff015fc96891662f72f1 /res/controllers/DJ-Tech-Kontrol-One-scripts.js
parente50f9f168fa08f2be6d0f13e8a225bbcc9de09bb (diff)
Moving mixxx/* to the root. A new era begins!
Diffstat (limited to 'res/controllers/DJ-Tech-Kontrol-One-scripts.js')
-rw-r--r--res/controllers/DJ-Tech-Kontrol-One-scripts.js1569
1 files changed, 1569 insertions, 0 deletions
diff --git a/res/controllers/DJ-Tech-Kontrol-One-scripts.js b/res/controllers/DJ-Tech-Kontrol-One-scripts.js
new file mode 100644
index 0000000000..6f2b197ad3
--- /dev/null
+++ b/res/controllers/DJ-Tech-Kontrol-One-scripts.js
@@ -0,0 +1,1569 @@
+function KONTROL1() {}
+KONTROL1.debug=false;//debug levels - 1 to 3 or false
+KONTROL1.disableFlash=false;//disables the bank indicator flashers so you can see debug messages and not get flooded out with timer msgs
+
+//set defaults
+KONTROL1.flashon=0;
+KONTROL1.flashcount=0;
+KONTROL1.LEDtimer=false;//stores reference to led timer - fires once per second
+KONTROL1.flashTimer=false;//reference to flash timer - flashes leds quickly, fired by LEDtimer
+KONTROL1.curChannel=0;//set current channel (deck selector - 0 to 3 = 1 to 4 on knob)
+KONTROL1.loopmove=0.0125;//default loop move distance in seconds
+KONTROL1.wheelloopmove=0.003125;//default loop move distance in seconds when using wheel to move
+KONTROL1.scratching=[];
+KONTROL1.modTimeout=200;//mod button timeout in ms - ie: how long do you have to hold a mod (like a knob button) to disable the bank switch or whatever it would normally do
+
+KONTROL1.bankIndicatorLED={bank1:0x37, bank2:0x36, bank3:0x35, bank4:0x34};//midi address of bank indicator LEDs (knob leds)
+KONTROL1.defaultDeck={0:"[Channel1]", 1:"[Channel2]", 2:"[Channel3]", 3:"[Channel4]"};//default deck for each channel
+KONTROL1.altDeck={0:"[Channel2]", 1:"[Channel1]", 2:"[Channel4]", 3:"[Channel3]"};//alt deck for each channel
+KONTROL1.syncDeck={0:"[Sampler1]", 1:"[Sampler2]", 2:"[Sampler3]", 3:"[Sampler4]"};//sync deck for each channel
+KONTROL1.beatloopLengths=new Array(0,0.03125,0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32);//store loop lengths with presets in Mixxx
+
+KONTROL1.beatlooprollactive={};
+KONTROL1.beatlooprolllen={};
+
+KONTROL1.overwriteHotcues=true;//when saving loop in points as hotcues, will the script overwrite an existing hotcue?
+
+//scratch parameters
+KONTROL1.wheelRes=150;
+KONTROL1.scratchRev=160;
+KONTROL1.scratchAlpha=1/16;
+KONTROL1.scratchBeta=KONTROL1.scratchAlpha/32;
+KONTROL1.scratchInterpolation=1;
+
+
+
+
+
+
+//obj to store info specific to the state of each channel
+KONTROL1.channels={};
+KONTROL1.channels[0]={curShift:"a",curBank:"bank1",cc:0xb0,noteon:0x90};
+KONTROL1.channels[1]={curShift:"a",curBank:"bank1",cc:0xb1,noteon:0x91};
+KONTROL1.channels[2]={curShift:"a",curBank:"bank1",cc:0xb2,noteon:0x92};
+KONTROL1.channels[3]={curShift:"a",curBank:"bank1",cc:0xb3,noteon:0x93};
+//shift state is "a" off or "b" on
+//banks are "bank1", "bank2", "bank3", or "bank4"
+//plug additional state variables into this object - mutes on/off, kills on/off, etc.
+
+
+//obj to store mod values - mods are pitch +-, Knob buttons, and shift when held down.
+KONTROL1.mod={};
+KONTROL1.mod["p1"]={state:"o",timer:false};
+KONTROL1.mod["p2"]={state:"o",timer:false};
+KONTROL1.mod["k1"]={state:"o",timer:false,bank:"bank1",dobankswitch:true};
+KONTROL1.mod["k2"]={state:"o",timer:false,bank:"bank2",dobankswitch:true};
+KONTROL1.mod["k3"]={state:"o",timer:false,bank:"bank3",dobankswitch:true};
+KONTROL1.mod["k4"]={state:"o",timer:false,bank:"bank4",dobankswitch:true};
+KONTROL1.mod["s"]={state:"o",timer:false,doshift:true};
+
+//if (KONTROL1.debug){print("#####WORD#####")};
+
+
+
+//############################################################################
+//INIT AND SHUTDOWN
+//############################################################################
+
+KONTROL1.init = function init(id, debug) { // called when the device is opened & set up
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ KONTROL1.updateLEDs();
+ if(KONTROL1.disableFlash!==true)KONTROL1.ledTimer = engine.beginTimer(1000, "KONTROL1.doLEDs()");//set timer for LED indicator flashes
+ engine.connectControl("[Channel1]", "volume", "KONTROL1.testconnect");
+ };
+
+KONTROL1.shutdown = function shutdown() {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ };
+
+
+
+//############################################################################
+//INPUT PROCESSING
+//############################################################################
+
+KONTROL1.button = function button(channel, control, value, status, group) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //input received - gatekeeper function connected to most buttons
+ //check channel - see if the deck selector has been moved
+ KONTROL1.checkChannel(channel);
+
+ //get the commands for the current control on the current bank
+ var thecontrol=KONTROL1.getControl(control);
+ var command = (value==127)?thecontrol[0]:thecontrol[1];
+ if (command!==false && command !='ReleaseEvalStr' && command!='ButtonFunctionEvalStr')eval(command);
+ };
+
+KONTROL1.knob = function knob(channel, control, value, status, group) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //input received - gatekeeper function connected to most knobs
+ //check channel - see if the deck selector has been moved
+ KONTROL1.checkChannel(channel);
+
+ //get the commands for the current control on the current bank - press function only - release functions are invalid on knobs
+ var thecontrol=KONTROL1.getControl(control);
+ var command = thecontrol[0];
+ if (command!==false && command!='ButtonFunctionEvalStr')eval(command);
+ };
+
+
+//MOD functions
+KONTROL1.knobPress = function knobPress(knobnum){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //{state:"o",timer:false,dobankswitch:true};
+ KONTROL1.modPress(knobnum);//turn mod on
+ engine.stopTimer(KONTROL1.mod[knobnum]["timer"]);//kill any previous timer
+ KONTROL1.mod[knobnum]["timer"]=engine.beginTimer(KONTROL1.modTimeout, "KONTROL1.disableBankSwitch('"+knobnum+"')", true);
+ }
+
+KONTROL1.knobRelease = function knobRelease(knobnum){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //switches banks when one of the four knob buttons is released
+ //knobnum is k1, k2, k3, or k4
+ //unless button has been held down for more than 1/2 second, in which case the knob is used as a modifier
+ if (KONTROL1.mod[knobnum]["dobankswitch"]===true){
+ engine.stopTimer(KONTROL1.mod[knobnum]["timer"]);
+ KONTROL1.switchBank(KONTROL1.mod[knobnum]["bank"]);
+ KONTROL1.mod[knobnum]["dobankswitch"]=true;
+ KONTROL1.modRelease(knobnum);//turn mod off
+ }else{
+ //reset
+ KONTROL1.mod[knobnum]["dobankswitch"]=true;
+ KONTROL1.modRelease(knobnum);//turn mod off
+ }
+
+ //exit knob loop if no loop was active when knob pressed.
+ if (KONTROL1.exitKnobLoop===true && knobnum=="k4"){
+ var group=KONTROL1.getGroup("default");
+ engine.setValue(group, "reloop_exit", 1);
+ KONTROL1.exitKnobLoop=false;
+ }
+ };
+
+KONTROL1.shiftPress = function shiftPress(){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ var knobnum="s";
+ KONTROL1.modPress(knobnum);//turn mod on
+ engine.stopTimer(KONTROL1.mod[knobnum]["timer"]);//kill any previous timer
+ KONTROL1.mod[knobnum]["timer"]=engine.beginTimer(500, "KONTROL1.disableShiftSwitch('"+knobnum+"')", true);
+ }
+
+KONTROL1.shiftRelease = function shiftRelease(){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ var knobnum="s";
+ //switches shift state
+ //unless button has been held down for more than 1/2 second, in which case the knob is used as a modifier
+ if (KONTROL1.mod[knobnum]["doshift"]===true){
+ engine.stopTimer(KONTROL1.mod[knobnum]["timer"]);
+ KONTROL1.switchShift(KONTROL1.mod[knobnum]["bank"]);
+ KONTROL1.mod[knobnum]["doshift"]=true;
+ KONTROL1.modRelease(knobnum);//turn mod off
+ }else{
+ engine.stopTimer(KONTROL1.mod[knobnum]["timer"]);
+ //reset
+ KONTROL1.mod[knobnum]["doshift"]=true;
+ KONTROL1.modRelease(knobnum);//turn mod off
+ }
+ };
+
+KONTROL1.modPress = function modPress(knobnum){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ KONTROL1.mod[knobnum]["state"]="I";//turn mod on
+ if (KONTROL1.mod["p1"]["state"]=="I" && KONTROL1.mod["p2"]["state"]=="I"){//both pitch buttons on, force update of all LEDS
+ KONTROL1.updateLEDs(false, true);
+ } else {KONTROL1.updateLEDs();}
+ }
+
+KONTROL1.modRelease = function modRelease(knobnum){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ if (KONTROL1.mod["p1"]["state"]=="I"){
+ //reset cue move stuff
+ engine.stopTimer(KONTROL1.cueMoveIndicator);
+ KONTROL1.cueMoveToNum=-1;
+ KONTROL1.cuemoveLastIndicator=-1;
+ }
+
+ KONTROL1.mod[knobnum]["state"]="o";//turn mod off
+
+ KONTROL1.updateLEDs();
+ }
+
+
+
+//############################################################################
+//LED FUNCTIONS - indicator functions
+//############################################################################
+
+KONTROL1.doLEDs = function doLEDs() {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ engine.stopTimer(KONTROL1.flashTimer);
+ KONTROL1.flashTimer=engine.beginTimer(30, "KONTROL1.bankIndicators()");
+ return;
+ };
+
+KONTROL1.bankIndicators= function bankIndicators(){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //flash knob LEDs to indicate current bank
+ var cc = KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ var address = KONTROL1.bankIndicatorLED[KONTROL1.channels[KONTROL1.curChannel]['curBank']];
+ if (KONTROL1.flashon==0){
+ if (KONTROL1.flashcount>=2){KONTROL1.stopFlashTimer();return;}
+ midi.sendShortMsg(cc, address, 0);
+ KONTROL1.flashon=1;
+ KONTROL1.flashcount++;
+ }else {
+ if (KONTROL1.flashcount>=2){KONTROL1.stopFlashTimer();return;}
+ midi.sendShortMsg(cc, address, 127);
+ KONTROL1.flashon=0;
+ KONTROL1.flashcount++;
+ }
+ }
+
+KONTROL1.stopFlashTimer = function stopFlashTimer() {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ engine.stopTimer(KONTROL1.flashTimer);
+ KONTROL1.flashcount=0;
+ var cc = KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ var address = KONTROL1.bankIndicatorLED[KONTROL1.channels[KONTROL1.curChannel]['curBank']];
+ KONTROL1.updateLEDs(true);
+ }
+
+KONTROL1.updateLEDs = function updateLEDs(knobsonly, force) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //fires on mod press/release, shift switch, channel switch, bank switch
+ //updates all LEDs
+ var state;
+ var samehook=false;
+ var hookgroup;
+ var midino;
+ var control;
+ var controllist=(knobsonly===true)?KONTROL1.knobLEDs:KONTROL1.allLEDs;
+ var force=(force===true)?force:false;
+
+ //clear hooks
+ for (var key in controllist){
+ midino=controllist[key];
+ control = KONTROL1.getControl(midino);
+ if ((control[2]==false || control[2]=='LEDstateType') && force !== true){continue;}//control has no LED, LED Type is not set, or LED doesn't change on this mod setting. skip to next control
+
+ //clear hooks
+ if (KONTROL1.controls[midino]["hookSet"]===true){
+ hookgroup=KONTROL1.getGroup(control[5]);//get mixxx control group
+ //clear the hook
+ engine.connectControl(KONTROL1.controls[midino]["hookGroup"], KONTROL1.controls[midino]["hookMixxxControl"], KONTROL1.controls[midino]["hookFunction"], true);
+ KONTROL1.controls[midino]["hookSet"]=false;
+ }//end if
+ }
+
+ for (var key in controllist){//set hooks
+ midino=controllist[key];
+ control = KONTROL1.getControl(midino);
+ if ((control[2]==false || control[2]=='LEDstateType') && force !== true){continue;}//control has no LED, LED Type is not set, or LED doesn't change on this mod setting. skip to next control
+
+
+ if (control[2]=="on"){//LED is always on
+ state=127;
+ }
+ else if (control[2]=="off"){//LED is always off
+ state=0;
+ }
+ else if (control[2]=="hook"){//LED is hooked to a mixxx control
+ print("#####-----SETTING HOOK##"+hookgroup+" - "+control[3]+" - "+control[4]);
+ hookgroup=KONTROL1.getGroup(control[5]);//get mixxx control group
+ engine.connectControl(hookgroup, control[3], control[4]);//set hook
+ KONTROL1.controls[midino]["hookGroup"]=hookgroup;
+ KONTROL1.controls[midino]["hookMixxxControl"]=control[3];
+ KONTROL1.controls[midino]["hookFunction"]=control[4];
+ KONTROL1.controls[midino]["hookSet"]=true;
+ engine.trigger(hookgroup, control[3]);
+ continue;
+ }
+ else if (control[2]=="eval"){//LED state determined by evaluating a javascript statement
+ if (KONTROL1.debug>2){print("##updateLEDs Eval: "+control[3])};
+ if (KONTROL1.debug>2){print("##updateLEDs midino: "+midino)};
+ if (KONTROL1.debug>2){print("##evalstate: "+eval(control[3]))};
+ state=eval(control[3]);
+ }//end if
+ //figure out whether we want a CC or noteon message - CC for knobs, noteon otherwise
+ if (midino==0x37 || midino==0x36 || midino==0x35 || midino==0x34){
+ ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ if (KONTROL1.debug>2){print("ch: "+ch)};
+ if (KONTROL1.debug>2){print("midino: "+midino)};
+ }else{
+ ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ }
+ midi.sendShortMsg(ch, midino, 0);
+ midi.sendShortMsg(ch, midino, state);
+ state=0;
+ }//end for
+ }
+
+//connected control functions
+KONTROL1.doLogKnobLEDs = function doLogKnobLEDs(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //show values of mixxx control on knob leds
+ //logarithmic scale (0 min, 4 max) - used for pregain and lo mid hi filters, for example.
+ //K = 4*(V)^2
+ //V = (K/4)^0.5 -- K= value coming from prog (0-4, logarithmic scale), V=value adjusted to linear 0-1
+ if (KONTROL1.debug>2){print("unadjusted value: "+value)};
+ value=(Math.pow((value/4),.5))*127;
+ if (value<70){value+=10;}//add a bit to center 50% mark
+ else if (value<110){value+=5;}
+ else if (value<120){value+=2;}
+ value=(value>127)?127:value;
+ value=(value<0)?0:value;
+ if (KONTROL1.debug>2){print("value: "+value)};
+ var midino;
+ var ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ if (control=="pregain"){midino=0x37;}
+ if (control=="filterHigh"){midino=0x36;}
+ if (control=="filterMid"){midino=0x35;}
+ if (control=="filterLow"){midino=0x34;}
+
+ midi.sendShortMsg(ch, midino, value);
+ }
+
+KONTROL1.doHotcueLEDs = function doHotcueLEDs(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ value=value*127;
+ if (KONTROL1.debug>2){print("value: "+value)};
+ var hotcuenum=control.replace("hotcue_", "");
+ var hotcuenum=hotcuenum.replace("_enabled", "");
+ var ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ var midino=KONTROL1.hotcueLEDs[hotcuenum];
+
+ midi.sendShortMsg(ch, midino, value);
+ }
+
+KONTROL1.doFilterKillLEDs = function doFilterKillLEDs(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ value=value*127;
+ ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ if (control=="filterHighKill"){midino=0x08}
+ if (control=="filterMidKill"){midino=0x07}
+ if (control=="filterLowKill"){midino=0x06}
+ midi.sendShortMsg(ch, midino, value);
+ }
+
+KONTROL1.syncLED = function syncLED(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ value=(value>0)?1:0;
+ ledstate=value*127;
+ midi.sendShortMsg(ch, KONTROL1.getIt['sync'], ledstate);
+ }
+
+KONTROL1.cueLED = function cueLED(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ value=(value>0)?1:0;
+ ledstate=value*127;
+ midi.sendShortMsg(ch, KONTROL1.getIt['cue'], ledstate);
+ }
+
+KONTROL1.playLED = function playLED(value,group,control) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ value=(value>0)?1:0;
+ ledstate=value*127;
+ midi.sendShortMsg(ch, KONTROL1.getIt['play'], ledstate);
+ }
+
+KONTROL1.loopLenLEDs = function loopLenLEDs(deck, num){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //light LEDS for loop length dial
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ if(typeof num === 'undefined'){
+ num=false;
+ for (i=1;i<11;i++){
+ if (engine.getValue(group, "beatloop_"+KONTROL1.beatloopLengths[i]+"_enabled")==1){num=i;break;}
+ }
+ if (num==false){num=8;}//default to 2 beat loop
+ }
+ num=(num*12.8)-1;
+ print("num="+num);
+ ch=KONTROL1.channels[KONTROL1.curChannel]['cc'];
+ midi.sendShortMsg(ch, 0x34, num);
+ }
+
+
+KONTROL1.lightButtonLEDs = function lightButtonLEDs(value,group,control){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //light button leds for simple binary values
+ //set KONTROL1.buttonLEDs object to contain new addresses as required
+ ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ value=value*127;
+ value=(value>127)?127:value;
+ value=(value<0)?0:value;
+ if (typeof(KONTROL1.buttonLEDs[control])!= 'undefined'){
+ var midino=KONTROL1.buttonLEDs[control];
+ midi.sendShortMsg(ch, midino, value);
+ }
+};
+
+KONTROL1.LoopBankLEDs = function LoopBankLEDs(value,group,control){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //light button leds for simple binary values
+ //set KONTROL1.buttonLEDs object to contain new addresses as required
+ ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ value=value*127;
+ value=(value>127)?127:value;
+ value=(value<0)?0:value;
+ if (typeof(KONTROL1.loopbuttonLEDs[control])!= 'undefined'){
+ var midino=KONTROL1.loopbuttonLEDs[control];
+ midi.sendShortMsg(ch, midino, value);
+ }
+};
+
+KONTROL1.resumeLED = function resumeLED() {//lights sync button if a resume position is set
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ var state;
+ if (KONTROL1.channels[KONTROL1.curChannel]["resumepos"]>-1){
+ state=127;
+ }else{
+ state=0;
+ }//end if
+ var ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ midi.sendShortMsg(ch, 0x1d, state);
+ return state;
+ };
+
+KONTROL1.scratchParameterLEDs = function scratchParameterLEDs(midino,thearray,theindex) {//lights knobs for scratch parameter adjustment
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ var state=Math.round((127/thearray.length)*theindex);
+ state=(state>127)?127:state;
+ state=(state<0)?0:state;
+
+ var ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+ midi.sendShortMsg(ch, midino, state);
+ return state;
+ };
+
+
+//############################################################################
+//CHANNEL AND BANK SWITCHING
+//############################################################################
+
+KONTROL1.checkChannel = function checkChannel(channel){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //checks to see whether the channel has changed (deck selector knob sends no midi when changed,
+ //so every time input is received, this function checks its midi channel to see if it's different from the last)
+ if (KONTROL1.curChannel!=channel){
+ //channel has changed.
+ KONTROL1.curChannel=channel;
+ //add in any functions to run here. Eg: update LEDs, etc. [TODO]
+ KONTROL1.updateLEDs();
+ };
+ };
+
+KONTROL1.disableBankSwitch = function disableBankSwitch(knobnum) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //timed function - fires half a second after pressing knob.
+ //Don't do the bank switch if you hold down the button (if knob button is used as modifier)
+ KONTROL1.mod[knobnum]["dobankswitch"]=false;
+ };
+
+KONTROL1.switchBank = function switchBank(bank){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ KONTROL1.channels[KONTROL1.curChannel]["curBank"]=bank;
+ //add in any functions to run here. Eg: update LEDs, etc. [TODO]
+ KONTROL1.updateLEDs();
+ };
+
+KONTROL1.disableShiftSwitch = function disableShiftSwitch(knobnum) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //timed function - fires half a second after pressing knob.
+ //Don't do the bank switch if you hold down the button (if knob button is used as modifier)
+ KONTROL1.mod[knobnum]["doshift"]=false;
+ };
+
+KONTROL1.switchShift = function switchShift(bank){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ KONTROL1.channels[KONTROL1.curChannel]["curShift"]=(KONTROL1.channels[KONTROL1.curChannel]["curShift"]=="a")?"b":"a";
+ //add in any functions to run here. Eg: update LEDs, etc. [TODO]
+ KONTROL1.updateLEDs();
+ };
+
+
+
+//############################################################################
+//MUSIC FUNCTIONALITY - stuff that actually does stuff
+//############################################################################
+
+KONTROL1.toggleBinaryControl = function toggleBinaryControl(control, newstate){//toggles a binary control. If newstate is provided, it will toggle to that state, otherwise it toggles on/off
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group = KONTROL1.getGroup(deck);
+
+ if (newstate!==1 && newstate!==0){var newstate = (engine.getValue(group, control)==0)?1:0;}
+
+ engine.setValue(group, control, newstate);
+ }
+
+
+KONTROL1.logKnobAdjust = function logKnobAdjust(group, control, minRange, maxRange, value){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //use a knob to adjust a mixxx control
+ //on a logarithmic scale (0 min, 4 max)
+ //K = 4*(V)^2
+ //V = (K/4)^0.5 -- K= value coming from prog (0-4, logarithmic scale), V=value adjusted to linear 0-1
+ var curValue=engine.getValue(KONTROL1.getGroup(group), control);
+ var adjustedValue=Math.pow((curValue/4),.5);//adjust range so it's on a scale of 0 to 1 - logarithmic
+
+ var inc=(value==127)?.02:-.02;//increment - how far to move on each knob click
+
+ var newValue=4*Math.pow((adjustedValue+inc),2);
+
+ if (KONTROL1.debug>2){print("group: "+KONTROL1.getGroup(group))};
+ if (KONTROL1.debug>2){print("control: "+control)};
+ if (KONTROL1.debug>2){print("curValue: "+curValue)};
+ if (KONTROL1.debug>2){print("adjustedValue: "+adjustedValue)};
+ if (KONTROL1.debug>2){print("newValue: "+newValue)};
+ if (KONTROL1.debug>2){print("inc: "+inc)};
+ if (newValue>4)newValue=4;
+ if (newValue<0)newValue=0;
+ engine.setValue(KONTROL1.getGroup(group), control, newValue);
+ }
+
+KONTROL1.wheelTouch = function wheelTouch(channel, control, value, status, group) {//activate scratching
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ if (KONTROL1.debug>2){print("channel: "+channel)};
+
+ if (value == 0x7F) {//wheel is being touched
+ engine.scratchEnable(channel+1, KONTROL1.wheelResArray[KONTROL1.wheelResIndex]*KONTROL1.scratchInterpolation, KONTROL1.scratchRevArray[KONTROL1.scratchRevIndex], KONTROL1.scratchAlphaArray[KONTROL1.scratchAlphaIndex], KONTROL1.scratchAlphaArray[KONTROL1.scratchAlphaIndex]/KONTROL1.scratchBetaArray[KONTROL1.scratchBetaIndex]);
+ // Keep track of whether we're scratching on this virtual deck - for v1.10.x or below
+ KONTROL1.scratching[group] = true;
+ } else {//wheel is released
+ engine.scratchDisable(channel+1);
+ KONTROL1.scratching[group] = false; // Only for v1.10.x and below
+ }
+ };
+
+KONTROL1.wheelTurn = function wheelTurn(channel, control, value, status, group) {//do scratching
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ if (KONTROL1.debug>2){print("channel: "+channel)};
+
+ if (value>1){var newValue=1}else{var newValue=-1};
+ if (!KONTROL1.scratching[group]){//do jog or other functions (move loops, hotcues, etc.) if not scratching
+
+ //check if a loop needs to be moved
+ if (KONTROL1.loopbuttonDown === true || KONTROL1.loopinbuttonDown === true || KONTROL1.loopoutbuttonDown === true){
+ if (KONTROL1.wheelMoveLoop(value)===true){return true;}//function returns true if loop moved
+ }
+
+ engine.setValue(group, "jog", newValue);
+ return true;
+ };
+ for (i=0; i<KONTROL1.scratchInterpolation; i++){
+ engine.scratchTick(channel+1,newValue);
+ }
+ };
+
+KONTROL1.hotcueButton = function hotcueButton(hotcuenum, deck) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group = KONTROL1.getGroup(deck);
+ //activate
+ if (KONTROL1.mod["p1"]["state"]=="I"){
+ engine.setValue(group, "hotcue_"+hotcuenum+"_clear", 1);
+ if (KONTROL1.debug>2){print("cleared")};
+ } else {
+ engine.setValue(group, "hotcue_"+hotcuenum+"_activate", 1);
+ engine.setValue(group, "hotcue_"+hotcuenum+"_activate", 0);
+ if (KONTROL1.debug>2){print("activated")};
+ };
+
+ };
+
+KONTROL1.cueClear = function cueClear(cue, control, deck){//clear hotcue - OR move hotcue to new button
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group = KONTROL1.getGroup(deck);
+
+
+ if(engine.getValue(group, "hotcue_"+cue+"_enabled")!=true){//hotcue not set - prepare to move next hotcue pressed to this button
+ KONTROL1.cueMoveToNum=cue;
+ engine.stopTimer(KONTROL1.cueMoveIndicator);
+ KONTROL1.cueMoveIndicator=engine.beginTimer(100, "KONTROL1.cueMoveIndicatorLEDs("+control+")");//start timer for LED indicator flasher showing the button we're moving to
+ return true;
+ }
+
+ if(KONTROL1.cueMoveToNum>0){//hotcue set, but we're moving it, not clearing it.
+ engine.setValue(group, "hotcue_"+KONTROL1.cueMoveToNum+"_set", 1);
+ engine.setValue(group, "hotcue_"+KONTROL1.cueMoveToNum+"_position", engine.getValue(group, "hotcue_"+cue+"_position"));
+ engine.setValue(group, "hotcue_"+cue+"_clear", 1);
+ engine.setValue(group, "hotcue_"+cue+"_clear", 0);
+
+ engine.stopTimer(KONTROL1.cueMoveIndicator);
+ KONTROL1.cueMoveToNum=-1;//reset
+ KONTROL1.cuemoveLastIndicator=-1;
+ return true;
+ }
+
+ engine.setValue(group, "hotcue_"+cue+"_clear", 1);
+ engine.setValue(group, "hotcue_"+cue+"_clear", 0);
+}
+
+KONTROL1.cueMoveIndicatorLEDs = function cueMoveIndicatorLEDs(control){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ ch=KONTROL1.channels[KONTROL1.curChannel]['noteon'];
+
+ KONTROL1.cuemovecontrol=control;
+ if (KONTROL1.cuemoveLastIndicator!=-1){midi.sendShortMsg(ch, KONTROL1.cuemoveLastIndicator, 0);}//turn off last indicator in case timer was interrupted (keeps last led from being left on if you switch "move to" buttons.
+ KONTROL1.cuemoveLastIndicator=control;
+ KONTROL1.cuemoveflashon=(KONTROL1.cuemoveflashon!=0 && KONTROL1.cuemoveflashon!=1)?0:KONTROL1.cuemoveflashon;
+
+ if (KONTROL1.cuemoveflashon==0){
+ midi.sendShortMsg(ch, control, 0);
+ KONTROL1.cuemoveflashon=1;
+ }else {
+ midi.sendShortMsg(ch, control, 127);
+ KONTROL1.cuemoveflashon=0;
+ }
+
+ return true;
+};
+
+KONTROL1.cueLoop = function cueLoop(cue, len){//jump to hotcue and start loop
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group = KONTROL1.getGroup(deck);
+
+ if (engine.getValue(group, "hotcue_"+cue+"_enabled")!==1){//set hotcue and start loop
+ engine.setValue(group, "hotcue_"+cue+"_activate", 1);
+ engine.setValue(group, "hotcue_"+cue+"_activate", 0);
+ engine.setValue(group, "beatloop_"+len+"_activate", 1);
+ }else{//jump to existing cue and loop
+
+ //calculate start and end points
+ var startpos=engine.getValue(group, "hotcue_"+cue+"_position");
+ var loopseconds = len*(1/(engine.getValue(group, "bpm")/60));
+ var loopsamples = loopseconds*engine.getValue(group, "track_samplerate")*2;//*2 to compensate for stereo samples
+ var endpos=startpos+loopsamples;
+
+ //disable loop if currently enabled
+ if (engine.getValue(group, "loop_enabled")==true){engine.setValue(group, "reloop_exit", 1);}
+
+ //set start and endpoints
+ engine.setValue(group, "loop_start_position", startpos);
+ engine.setValue(group, "loop_end_position", endpos);
+ //enable loop
+ engine.setValue(group, "reloop_exit", 1);
+ }
+}
+
+KONTROL1.kill = function kill(freq, value, deck){
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //kills low mid high, or mutes all by recording current track volume level, switching to 0, then restoring previous volume level
+ //if P1 mod is on when button pressed, it toggles on and off. Otherwise it's momentary
+ //args: freq = "all", "low", "mid", or "high"
+ //value: 127=button pressed ; 0=button released
+ var group=KONTROL1.getGroup(deck);
+
+ if (value==127){//button was pressed
+ if (KONTROL1.channels[KONTROL1.curChannel]['kill'+freq]===true){
+ //kill is already on... change setting so it clears on release
+ KONTROL1.channels[KONTROL1.curChannel]['kill'+freq]=false;
+ return true;
+ } else
+ if (KONTROL1.mod["p1"]["state"]=="I"){//mod is on, set toggle
+ KONTROL1.channels[KONTROL1.curChannel]['kill'+freq]=true;
+ }
+ if (freq=="low"){engine.setValue(group, "filterLowKill", 1);}else
+ if (freq=="mid"){engine.setValue(group, "filterMidKill", 1);}else
+ if (freq=="high"){engine.setValue(group, "filterHighKill", 1);}else
+ if (freq=="all"){
+ //mute
+ curvol=engine.getValue(group, "volume");
+ if (curvol==0){return;}//do nothing if volume is already zeroyyz
+ engine.setValue(group, "volume", 0);
+ KONTROL1.channels[KONTROL1.curChannel]['mutestoredvol']=curvol;
+ KONTROL1.channels[KONTROL1.curChannel]["isMuted"]=true;
+ (KONTROL1.channels[KONTROL1.curChannel]["isMuted"]==true)?127:0;
+ midi.sendShortMsg(KONTROL1.channels[KONTROL1.curChannel]['noteon'], 0x09, 127);//light led
+ }
+ }else{//button was released
+ if (KONTROL1.channels[KONTROL1.curChannel]['kill'+freq]===true){
+ //kill is toggled... ignore button release
+ return true;
+ }
+ if (freq=="low"){engine.setValue(group, "filterLowKill", 0);}else
+ if (freq=="mid"){engine.setValue(group, "filterMidKill", 0);}else
+ if (freq=="high"){engine.setValue(group, "filterHighKill", 0);}else
+ if (freq=="all"){
+ //unmute
+ engine.setValue(group, "volume", KONTROL1.channels[KONTROL1.curChannel]['mutestoredvol']);
+ KONTROL1.channels[KONTROL1.curChannel]["isMuted"]=false;
+ midi.sendShortMsg(KONTROL1.channels[KONTROL1.curChannel]['noteon'], 0x09, 0);//light led
+ }
+ }
+ }
+
+KONTROL1.resetKnob = function resetKnob(control, deck){//resets gain, low mid high to 50%
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+ engine.setValue(group, control, 1);
+ }
+
+KONTROL1.play = function play(value, deck) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+ var state=(engine.getValue(group, "play")==1)?0:1;
+ if (value>0){//button was pressed
+ if (KONTROL1.debug){print("play newstate: "+state)};
+ if (KONTROL1.debug){print("play group: "+group)};
+ engine.setValue(group, "play", state);
+ } else {//button was released
+ };
+
+}
+
+KONTROL1.cue = function play(value, deck) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+ if (value>0){//button was pressed
+ engine.setValue(group, "cue_default", 1);
+ } else {//button was released
+ };
+
+}
+
+//LOOPS
+KONTROL1.beatLoop = function beatLoop(looplen, value, deck) {//activate beatloop
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+ //activate beatloop
+ if (value>0){//button was pressed
+ KONTROL1.loopbuttonDown=true;
+ if (engine.getValue(group, "beatloop_"+looplen+"_enabled")!=1){//if it's not already enabled (this is to prevent turning a beatlooproll into a beatloop of the same length
+ engine.setValue(group, "beatloop_"+looplen+"_activate", 1);
+ }
+ } else {//button was released
+ KONTROL1.loopbuttonDown=false;
+ };
+
+ };
+
+KONTROL1.beatLoopRoll = function beatLoopRoll(looplen, value, deck) {//activate beatloop
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+ //activate beatlooproll
+ if (value>0){//button was pressed
+ KONTROL1.loopbuttonDown=true;
+ engine.setValue(group, "beatlooproll_"+looplen+"_activate", 1);
+ KONTROL1.beatlooprollactive[group]=true;
+ KONTROL1.beatlooprolllen[group]=looplen;
+ } else {//button was released
+ KONTROL1.loopbuttonDown=false;
+ };
+
+ };
+
+KONTROL1.beatjump = function (jumplen) {//jumps back jumplen beats
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ var curpos = engine.getValue(group, "playposition")*engine.getValue(group, "track_samples");
+ var numbeats = jumplen;
+ var backseconds = numbeats*(1/(engine.getValue(group, "bpm")/60));
+ var backsamples = backseconds*engine.getValue(group, "track_samplerate")*2;//*2 to compensate for stereo samples
+ var newpos = curpos-(backsamples);
+
+ if (KONTROL1.debug){print("backseconds: "+backseconds);}
+ if (KONTROL1.debug){print("backsamples: "+backsamples);}
+ if (KONTROL1.debug){print("curpos: "+curpos);}
+ if (KONTROL1.debug){print("newpos: "+newpos);}
+ if (KONTROL1.debug){print("numbeats: "+numbeats);}
+
+ engine.setValue(group, "playposition", newpos/engine.getValue(group, "track_samples"));
+ };
+
+KONTROL1.saveLoop = function saveLoop(cue){//save the current loop inpoint as a hotcue
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ if (engine.getValue(group, "hotcue_"+cue+"_enabled")==1 && KONTROL1.overwriteHotcues===false){//hotcue is already set, return false
+ return false;
+ }else if (engine.getValue(group, "loop_enabled")!=true){//no loop currently active, return false
+ return false;
+ }else{//save the loop as a hotcue
+ engine.setValue(group, "hotcue_"+cue+"_set", 1);
+ engine.setValue(group, "hotcue_"+cue+"_position", engine.getValue(group, "loop_start_position"));
+ return true;
+ }
+}
+
+KONTROL1.reloopButton = function reloopButton(value, deck) {//reloop/exit button
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ if (value>0){//button was pressed
+ engine.stopTimer(KONTROL1.reloopTimer);
+ KONTROL1.loopbuttonDown=true;
+ KONTROL1.doreloop=true;
+ KONTROL1.reloopTimer = engine.beginTimer(500, "KONTROL1.disablereloop()", true);
+ } else {//button was released
+ KONTROL1.loopbuttonDown=false;
+ if (KONTROL1.doreloop===true) {
+ if (KONTROL1.beatlooprollactive[group]===true && KONTROL1.beatlooprolllen[group]>0){
+ engine.setValue(group, "beatlooproll_"+KONTROL1.beatlooprolllen[group]+"_activate", 0);
+ KONTROL1.beatlooprollactive[group]=false;
+ KONTROL1.beatlooprolllen[group]=-1;
+ }else{
+ engine.setValue(group, "reloop_exit", 1);
+ }
+
+ };
+ KONTROL1.doreloop=true;
+ engine.stopTimer(KONTROL1.reloopTimer);
+ };
+
+ };
+
+KONTROL1.disablereloop = function disablereloop() {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //timed function - fires half a second after pressing reloop. Don't do the reloop if you hold down the button (so you can move the loop without exiting)
+ KONTROL1.doreloop=false;
+ };
+
+KONTROL1.looplenDial = function looplenDial(value, deck) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+ //activates variable length loop depending on dial position
+
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ //is a loop active? If not, exit loop when knob button is released
+ if (engine.getValue(group, "loop_enabled")!=1){
+ KONTROL1.exitKnobLoop=true;
+ }
+
+ //determine active loop length, default to 2 beats
+ var arraypointer=false;
+ var inc=(value==127)?1:-1;//increment - how far to move on each knob click
+ for (i=1;i<12;i++){
+ if (engine.getValue(group, "beatloop_"+KONTROL1.beatloopLengths[i]+"_enabled")==1){arraypointer=i;break;}
+ }
+ if (arraypointer==false){arraypointer=8;inc=0;}//default to 2 beat loop, don't increment
+ arraypointer+=inc;
+ arraypointer=(arraypointer<1)?1:arraypointer;
+ arraypointer=(arraypointer>11)?11:arraypointer;
+
+ var newLoopLen=KONTROL1.beatloopLengths[arraypointer];
+ engine.setValue(group, "beatloop_"+newLoopLen+"_activate", 1);
+ KONTROL1.loopLenLEDs("default",arraypointer);
+ return true;
+ };
+
+KONTROL1.loopIn = function loopIn(value, deck) {
+ if (KONTROL1.debug>2){print("##function: "+KONTROL1.getFunctionName())};
+
+ //Set or move loop in point
+ deck=(typeof deck !== 'undefined')?deck:"default";
+ var group=KONTROL1.getGroup(deck);
+
+ if (value>0){//button was pressed
+ KONTROL1.loopinbuttonDown=true;