home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Aplikacje_64-bitowe / Mixxx / mixxx-1.9.0-win64.exe / midi / Stanton-SCS3m-scripts.js < prev    next >
Text File  |  2011-02-04  |  36KB  |  871 lines

  1. /****************************************************************/
  2. /*      Stanton SCS.3m MIDI controller script v1.04             */
  3. /*          Copyright (C) 2010, Sean M. Pappalardo              */
  4. /*      but feel free to tweak this to your heart's content!    */
  5. /*      For Mixxx version 1.8.x                                 */
  6. /****************************************************************/
  7.  
  8. function StantonSCS3m() {}
  9.  
  10. //      See http://mixxx.org/wiki/doku.php/stanton_scs.3m_mixxx_user_guide  for details
  11.  
  12. // ----------   Other global variables    ----------
  13. StantonSCS3m.debug = false;  // Enable/disable debugging messages to the console
  14. StantonSCS3m.id = "";   // The ID for the particular device being controlled for use in debugging, set at init time
  15. StantonSCS3m.channel = 0;   // MIDI channel the device is on
  16. StantonSCS3m.sysex = [0xF0, 0x00, 0x01, 0x60];    // Preamble for all SysEx messages for this device
  17. StantonSCS3m.modifier = { };    // Modifier buttons (allowing alternate controls) defined on-the-fly if needed
  18. StantonSCS3m.mode_store = { "[Channel1]":"fx", "[Channel2]":"fx", "Master":"alt" };   // Set to opposite default on both
  19.  
  20. // Signals to (dis)connect by mode: Group, Key, Function name
  21. StantonSCS3m.modeSignals = {"fx":[ ["[Flanger]", "lfoDepth", "StantonSCS3m.FXDepthLEDs"],
  22.                                    ["[Flanger]", "lfoDelay", "StantonSCS3m.FXDelayLEDs"],
  23.                                    ["[Flanger]", "lfoPeriod", "StantonSCS3m.FXPeriodLEDs"] ],
  24.                             "eq":[ ["CurrentChannel", "filterLow", "StantonSCS3m.EQLowLEDs"],
  25.                                    ["CurrentChannel", "filterMid", "StantonSCS3m.EQMidLEDs"],
  26.                                    ["CurrentChannel", "filterHigh", "StantonSCS3m.EQHighLEDs"] ],
  27.                             "none":[]  // To avoid an error on forced mode changes
  28.                             };
  29. StantonSCS3m.masterSignals = {  "main":[ ["CurrentChannel", "rate", "StantonSCS3m.pitchLEDs"],
  30.                                          ["CurrentChannel", "volume", "StantonSCS3m.volumeLEDs"],
  31.                                          ["CurrentChannel", "VuMeter", "StantonSCS3m.Vu"] ],
  32.                                 "alt":[  ["[Master]","VuMeterL","StantonSCS3m.VuL"],
  33.                                          ["[Master]","VuMeterR","StantonSCS3m.VuR"],
  34.                                          ["[Master]","headMix","StantonSCS3m.pitchLEDsL"],
  35.                                          ["[Master]","headVolume","StantonSCS3m.masterVolumeLEDsL"],
  36.                                          ["[Master]","balance","StantonSCS3m.pitchLEDsR"],
  37.                                          ["[Master]","volume","StantonSCS3m.masterVolumeLEDsR"] ]
  38.                             };
  39.  
  40. StantonSCS3m.masterSliders = {  "slider":[ 0x00, 0x01, 0x02, 0x04, 0x06, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0A ],
  41.                                 "main":  [ 0x71, 0x71, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70 ],
  42.                                 "alt":   [ 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x70 ]
  43. };  // 0x70 = absolute, 0x71 = relative
  44.  
  45. // ----------   Functions   ----------
  46.  
  47. StantonSCS3m.init = function (id) {
  48.     
  49.     StantonSCS3m.id = id;   // Store the ID of this device for later use
  50.     
  51.     // Set the device to flat mode
  52.     midi.sendSysexMsg(StantonSCS3m.sysex.concat([0x15, 0x01, 0xF7]),7);
  53.     
  54.     var CC = 0xB0 + StantonSCS3m.channel;
  55.     var No = 0x90 + StantonSCS3m.channel;
  56. //     midi.sendShortMsg(CC,0x7B,0x00);  // Extinguish all LEDs
  57.  
  58.     // Connect cross-fader LEDs & light them
  59.     StantonSCS3m.doConnectSignal("[Master]","crossfader","StantonSCS3m.crossfaderLEDs");
  60.  
  61.     // Connect master signals
  62.     // Hack: Have to register a down press first to get LEDs to light correctly
  63.     StantonSCS3m.Master(StantonSCS3m.channel, 0x0E, 0, 0x90+StantonSCS3m.channel);
  64.     StantonSCS3m.Master(StantonSCS3m.channel, 0x0E, 0, 0x80+StantonSCS3m.channel);
  65.  
  66.     // Force change to EQ mode on both sides
  67.     // Hack: Have to force FX mode first to get LEDs to light correctly
  68.     StantonSCS3m.FXL(StantonSCS3m.channel, 0x0C, 0, 0x80+StantonSCS3m.channel);
  69.     StantonSCS3m.FXR(StantonSCS3m.channel, 0x0D, 0, 0x80+StantonSCS3m.channel);
  70.     // ----
  71.     StantonSCS3m.EQL(StantonSCS3m.channel, 0x0C, 0, 0x80+StantonSCS3m.channel);
  72.     StantonSCS3m.EQR(StantonSCS3m.channel, 0x0D, 0, 0x80+StantonSCS3m.channel);
  73.  
  74.     print ("Stanton SCS.3m: \""+StantonSCS3m.id+"\" on MIDI channel "+(StantonSCS3m.channel+1)+" initialized.");
  75. }
  76.  
  77. StantonSCS3m.shutdown = function () {
  78.     var CC = 0xB0 + StantonSCS3m.channel;
  79.     var No = 0x90 + StantonSCS3m.channel;
  80.  
  81.     midi.sendShortMsg(CC,0x7B,0x00);  // Extinguish all LEDs
  82.     midi.sendShortMsg(No,0x69,0x01);  // Light the Stanton LED so you know it's still on
  83.     
  84.     print ("Stanton SCS.3m: \""+StantonSCS3m.id+"\" on MIDI channel "+(StantonSCS3m.channel+1)+" shut down.");
  85. }
  86.  
  87. // (Dis)connects the appropriate Mixxx control signals to/from functions based on what mode the controller section is in
  88. StantonSCS3m.connectModeSignals = function (midiChannel, side, disconnect) {
  89.     var deck = StantonSCS3m.SideToDeck(side);
  90.     var signalList = StantonSCS3m.modeSignals[StantonSCS3m.mode_store["[Channel"+deck+"]"]];
  91.     for (i=0; i<signalList.length; i++) {
  92.         var group = signalList[i][0];
  93.         var calledFunction = signalList[i][2]+side;
  94.         if (group=="CurrentChannel") group = "[Channel"+deck+"]";
  95.         StantonSCS3m.doConnectSignal(group,signalList[i][1],calledFunction,disconnect);
  96.     }
  97.     // If disconnecting signals, darken the LEDs on the controls
  98.     if (disconnect) {
  99.         var CC = 0xB0 + midiChannel;
  100.         switch (side) {
  101.             case "L":
  102.                 midi.sendShortMsg(CC,0x02,0x00);  // S3 LEDs off
  103.                 midi.sendShortMsg(CC,0x04,0x00);  // S4 LEDs off
  104.                 midi.sendShortMsg(CC,0x06,0x00);  // S5 LEDs off
  105.                 break;
  106.             case "R":
  107.                 midi.sendShortMsg(CC,0x03,0x00);  // S6 LEDs off
  108.                 midi.sendShortMsg(CC,0x05,0x00);  // S7 LEDs off
  109.                 midi.sendShortMsg(CC,0x07,0x00);  // S8 LEDs off
  110.                 break;
  111.         }
  112.     }
  113. }
  114.  
  115. // (Dis)connects the appropriate Mixxx Master control signals to/from functions
  116. StantonSCS3m.connectMasterSignals = function (midiChannel, disconnect) {
  117.     
  118.     var signalList = StantonSCS3m.masterSignals[StantonSCS3m.mode_store["Master"]];
  119.     for (i=0; i<signalList.length; i++) {
  120.         var group = signalList[i][0];
  121.         var calledFunction = signalList[i][2];
  122.         if (group=="CurrentChannel") {
  123.             var sides = ["L","R"];
  124.             var side, deck;
  125.             for (j=0; j<2; j++) {
  126.                 side=sides[j];
  127.                 switch (side) {
  128.                     case "L":
  129.                         deck=1; break;
  130.                     case "R":
  131.                         deck=2; break;
  132.                 }
  133.                 group = "[Channel"+deck+"]";
  134.                 calledFunction = signalList[i][2]+side;
  135.                 StantonSCS3m.doConnectSignal(group,signalList[i][1],calledFunction,disconnect);
  136.             }
  137.         }
  138.         else StantonSCS3m.doConnectSignal(group,signalList[i][1],calledFunction,disconnect);
  139.     }
  140.     // If disconnecting signals, darken the LEDs on the controls
  141.     if (disconnect) {
  142.         var CC = 0xB0 + midiChannel;
  143.         midi.sendShortMsg(CC,0x00,0x00);  // S1 LEDs off
  144.         midi.sendShortMsg(CC,0x08,0x00);  // S9 LEDs off
  145.         midi.sendShortMsg(CC,0x0C,0x00);  // V1 LEDs off
  146.         midi.sendShortMsg(CC,0x01,0x00);  // S2 LEDs off
  147.         midi.sendShortMsg(CC,0x09,0x00);  // S10 LEDs off
  148.         midi.sendShortMsg(CC,0x0D,0x00);  // V2 LEDs off
  149.     }
  150. }
  151.  
  152. StantonSCS3m.doConnectSignal = function (group, key, calledFunction, disconnect) {
  153.     engine.connectControl(group,key,calledFunction,disconnect);
  154.  
  155.     // If connecting a signal, cause it to fire (by setting it to the same value) to update the LEDs
  156. //     if (!disconnect) engine.trigger(group,key);  // Commented because there's no sense in wasting queue length
  157.     // Alternate method:
  158.     if (!disconnect) {
  159.         var command = calledFunction+"("+engine.getValue(group,key)+")";
  160. //         if (StantonSCS3m.debug) print("Stanton SCS.3m: command="+command);
  161.         eval(command);
  162.     }
  163.     if (StantonSCS3m.debug) {
  164.         if (disconnect) print("Stanton SCS.3m: "+group+","+key+" disconnected from "+calledFunction);
  165.         else print("Stanton SCS.3m: "+group+","+key+" connected to "+calledFunction);
  166.     }
  167. }
  168.  
  169. StantonSCS3m.SideToDeck = function (side) { // For future n-deck support
  170.     var deck;
  171.     switch (side) {
  172.         case "L":
  173.             deck=1; break;
  174.         case "R":
  175.             deck=2; break;
  176.     }
  177.     return deck;
  178. }
  179.  
  180. StantonSCS3m.sliderMode = function (control,value) {
  181.     // FIXME: This is a hack, present due to the fact that the SCS.3m
  182.     // wasn't designed to have its slider modes changed quickly on-the-fly
  183.     // It needs about 10ms between slider change commands
  184.     midi.sendShortMsg(0xBF,control,value);
  185.     
  186.     // 10ms pause - TODO: This needs a timer in 1.8
  187.     var date = new Date();
  188.     var curDate = null;
  189.     
  190.     do { curDate = new Date(); }
  191.     while(curDate-date < 10);
  192. }
  193.  
  194. // ------------------- Surface Controls -----------------------
  195.  
  196. StantonSCS3m.Deck = function (channel, control, value, status) {
  197.     if (StantonSCS3m.modifier["Master"]) return;    // Ignore if MASTER is held down
  198.     var decks = { 0x10:1, 0x0F:2 };
  199.     var deck = decks[control];
  200.     
  201.     var sides = { 0x10:"L", 0x0F:"R" };
  202.     var side = sides[control];
  203.     
  204.     var volsliders = { 0x10:0x08, 0x0F:0x09 };
  205.     var volslider = volsliders[control];
  206.     
  207.     var byte1 = 0x90 + channel;
  208.     if ((status & 0xF0) == 0x90) {   // If button down
  209.         midi.sendShortMsg(byte1,control,3); // Light up C/D too
  210.         StantonSCS3m.modifier["Deck"+side] = true;
  211.         // Use the sliders for other functions, so disconnect previous ones
  212.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "volume", "StantonSCS3m.volumeLEDs"+side, true);
  213.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "volume", "StantonSCS3m.volumeLEDs"+side, true);
  214.         StantonSCS3m.doConnectSignal("[Master]","crossfader","StantonSCS3m.crossfaderLEDs",true);
  215.         // Connect new ones
  216.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "pregain", "StantonSCS3m.gainLEDs"+side);
  217.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "playposition", "StantonSCS3m.needleDropLEDs");
  218.         // Change the slider mode - 0x70 = absolute, 0x71 = relative
  219.         StantonSCS3m.sliderMode(volslider,0x71);  // Relative gain control
  220.         StantonSCS3m.sliderMode(0,0x7F);    // End of sequence
  221.         // Use the mode buttons for other functions
  222.         //  so connect applicable signals
  223.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]","beatsync","StantonSCS3m.EQ"+side+"ButtonLED");
  224.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]","flanger","StantonSCS3m.FX"+side+"ButtonLED");
  225.     }
  226.     else {
  227.         // Disconnect special signals
  228.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]","beatsync","StantonSCS3m.EQ"+side+"ButtonLED",true);
  229.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]","flanger","StantonSCS3m.FX"+side+"ButtonLED",true);
  230.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "pregain", "StantonSCS3m.gainLEDs"+side, true);
  231.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "playposition", "StantonSCS3m.needleDropLEDs", true);
  232.         // Reconnect original ones & trigger
  233.         StantonSCS3m.doConnectSignal("[Channel"+deck+"]", "volume", "StantonSCS3m.volumeLEDs"+side);
  234.         StantonSCS3m.doConnectSignal("[Master]","crossfader","StantonSCS3m.crossfaderLEDs");
  235.         // Change the slider mode - 0x70 = absolute, 0x71 = relative
  236.         StantonSCS3m.sliderMode(volslider,0x70);  // Absolute volume control
  237.         StantonSCS3m.sliderMode(0,0x7F);    // End of sequence
  238.         // Restore the button LEDs
  239.         var fx = { "L":0x0A, "R":0x0B };
  240.         var eq = { "L":0x0C, "R":0x0D };
  241.         var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  242.         StantonSCS3m.modifier["Deck"+side] = false;
  243.         switch (currentMode) {
  244.             case "fx": StantonSCS3m.modeButton(channel, fx[side], 0x80+channel, "fx", side); break;
  245.             case "eq": StantonSCS3m.modeButton(channel, eq[side], 0x80+channel, "eq", side); break;
  246.         }
  247.         midi.sendShortMsg(byte1,control,1); // Light just A/B
  248.     }
  249. }
  250.  
  251. StantonSCS3m.Master = function (channel, control, value, status) {
  252.     var byte1 = 0x90 + channel;
  253.     if ((status & 0xF0) == 0x90) {   // If button down
  254.         midi.sendShortMsg(byte1,control,2); // Make it red
  255.         StantonSCS3m.modifier["Master"] = true;
  256.         StantonSCS3m.connectMasterSignals(channel,true);    // Disconnect previous signals
  257.         StantonSCS3m.mode_store["Master"]="alt";
  258.         StantonSCS3m.connectMasterSignals(channel); // Connect new ones
  259.     }
  260.     else {
  261.         StantonSCS3m.connectMasterSignals(channel,true);    // Disconnect previous signals
  262.         StantonSCS3m.mode_store["Master"]="main";
  263.         StantonSCS3m.connectMasterSignals(channel); // Connect new ones
  264.         StantonSCS3m.modifier["Master"] = false;
  265.         midi.sendShortMsg(byte1,control,1); // Make it blue
  266.     }
  267.     // Set the sliders to abs/rel mode as needed
  268.     var sliderList = StantonSCS3m.masterSliders["slider"];
  269.     var sliderValues = StantonSCS3m.masterSliders[StantonSCS3m.mode_store["Master"]];
  270.     for (i=0; i<sliderList.length; i++) {
  271. //         print("Stanton SCS.3m: slider number="+sliderList[i]+", value="+sliderValues[i]);
  272.         StantonSCS3m.sliderMode(sliderList[i],sliderValues[i]);
  273.     }
  274.     StantonSCS3m.sliderMode(0,0x7F);    // End of sequence
  275. }
  276.  
  277. StantonSCS3m.PitchL = function (channel, control, value, status) {
  278.     var deck = StantonSCS3m.SideToDeck("L");
  279.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  280.     // If the current mode button is held down, reset the control to center
  281.     if (StantonSCS3m.modifier[currentMode+"L"]) {
  282.         switch (StantonSCS3m.mode_store["Master"]) {
  283.             case "main": engine.setValue("[Channel"+deck+"]","rate",0); break;
  284.             case "alt": engine.setValue("[Master]","headMix",0); break;
  285.         }
  286.     }
  287.     else switch (StantonSCS3m.mode_store["Master"]) {
  288.         case "main": StantonSCS3m.PitchRel(1,value,"L"); break;
  289.         case "alt": engine.setValue("[Master]","headMix",(value-64)/64); break;
  290.     }
  291. }
  292.  
  293. StantonSCS3m.PitchR = function (channel, control, value, status) {
  294.     var deck = StantonSCS3m.SideToDeck("R");
  295.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  296.     // If the current mode button is held down, reset the control to center
  297.     if (StantonSCS3m.modifier[currentMode+"R"]) {
  298.         switch (StantonSCS3m.mode_store["Master"]) {
  299.             case "main": engine.setValue("[Channel"+deck+"]","rate",0); break;
  300.             case "alt": engine.setValue("[Master]","balance",0); break;
  301.         }
  302.     }
  303.     else switch (StantonSCS3m.mode_store["Master"]) {
  304.         case "main": StantonSCS3m.PitchRel(2,value,"R"); break;
  305.         case "alt": engine.setValue("[Master]","balance",(value-64)/64); break;
  306.     }
  307. }
  308.  
  309. StantonSCS3m.PitchRel = function (deck, value, side) {
  310.     var currentValue = engine.getValue("[Channel"+deck+"]","rate");
  311.     var newValue;
  312.     if (StantonSCS3m.modifier["Deck"+side])
  313.         newValue = currentValue+(value-64)/1024;    // Fine pitch adjust
  314.     else newValue = currentValue+(value-64)/256;
  315.     if (newValue<-1) newValue=-1.0;
  316.     if (newValue>1) newValue=1.0;
  317.     engine.setValue("[Channel"+deck+"]","rate",newValue);
  318. }
  319.  
  320. StantonSCS3m.PitchLbL = function (channel, control, value, status) {
  321.     StantonSCS3m.PitchBendButton(status,"L",-1);
  322. }
  323.  
  324. StantonSCS3m.PitchLbR = function (channel, control, value, status) {
  325.     StantonSCS3m.PitchBendButton(status,"L",1);
  326. }
  327.  
  328. StantonSCS3m.PitchRbL = function (channel, control, value, status) {
  329.     StantonSCS3m.PitchBendButton(status,"R",-1);
  330. }
  331.  
  332. StantonSCS3m.PitchRbR = function (channel, control, value, status) {
  333.     StantonSCS3m.PitchBendButton(status,"R",1);
  334. }
  335.  
  336. StantonSCS3m.PitchBendButton = function (status, side, comp) {
  337.     // Skip if Master button is held or fine-tuning the pitch
  338.     if (StantonSCS3m.modifier["Master"] || StantonSCS3m.modifier["Deck"+side]) return;
  339.     var deck = StantonSCS3m.SideToDeck(side);
  340.     if (engine.getValue("[Channel"+deck+"]","rate_dir") == comp) {   // Go in the appropriate direction
  341.         if ((status & 0xF0) == 0x90)    // If button down
  342.             engine.setValue("[Channel"+deck+"]","rate_temp_up",1);
  343.         else 
  344.             engine.setValue("[Channel"+deck+"]","rate_temp_up",0);
  345.     }
  346.     else {
  347.         if ((status & 0xF0) == 0x90)    // If button down
  348.             engine.setValue("[Channel"+deck+"]","rate_temp_down",1);
  349.         else 
  350.             engine.setValue("[Channel"+deck+"]","rate_temp_down",0);
  351.     }
  352. }
  353.  
  354.  
  355. // Multi-function sliders
  356.  
  357. //      Function select buttons
  358. StantonSCS3m.FXL = function (channel, control, value, status) {
  359.     StantonSCS3m.modeButton(channel, control, status, "fx", "L");
  360. }
  361.  
  362. StantonSCS3m.FXR = function (channel, control, value, status) {
  363.     StantonSCS3m.modeButton(channel, control, status, "fx", "R");
  364. }
  365.  
  366. StantonSCS3m.EQL = function (channel, control, value, status) {
  367.     StantonSCS3m.modeButton(channel, control, status, "eq", "L");
  368. }
  369.  
  370. StantonSCS3m.EQR = function (channel, control, value, status) {
  371.     StantonSCS3m.modeButton(channel, control, status, "eq", "R");
  372. }
  373.  
  374. //      Actual sliders
  375. StantonSCS3m.TripleL1 = function (channel, control, value, status) {
  376.     StantonSCS3m.Triple1(channel, control, value, status, "L");
  377. }
  378.  
  379. StantonSCS3m.TripleL2 = function (channel, control, value, status) {
  380.     StantonSCS3m.Triple2(channel, control, value, status, "L");
  381. }
  382.  
  383. StantonSCS3m.TripleL3 = function (channel, control, value, status) {
  384.     StantonSCS3m.Triple3(channel, control, value, status, "L");
  385. }
  386.  
  387. StantonSCS3m.TripleR1 = function (channel, control, value, status) {
  388.     StantonSCS3m.Triple1(channel, control, value, status, "R");
  389. }
  390.  
  391. StantonSCS3m.TripleR2 = function (channel, control, value, status) {
  392.     StantonSCS3m.Triple2(channel, control, value, status, "R");
  393. }
  394.  
  395. StantonSCS3m.TripleR3 = function (channel, control, value, status) {
  396.     StantonSCS3m.Triple3(channel, control, value, status, "R");
  397. }
  398.  
  399. //      Work functions
  400. StantonSCS3m.Triple1 = function (channel, control, value, status, side) {
  401.     var deck = StantonSCS3m.SideToDeck(side);
  402.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  403.     // If mode button is held down, reset the control to center
  404.     if (StantonSCS3m.modifier[currentMode+side]) {
  405.         switch (currentMode) {
  406.             case "fx": engine.setValue("[Flanger]","lfoDepth",0.5); break;
  407.             case "eq": engine.setValue("[Channel"+deck+"]","filterLow",1); break;
  408.         }
  409.     }
  410.     else switch (currentMode) {
  411.         case "fx": script.absoluteSlider("[Flanger]","lfoDepth",value,0,1); break;
  412.         case "eq": engine.setValue("[Channel"+deck+"]","filterLow",script.absoluteNonLin(value,0,1,4)); break;
  413.     }
  414. }
  415.  
  416. StantonSCS3m.Triple2 = function (channel, control, value, status, side) {
  417.     var deck = StantonSCS3m.SideToDeck(side);
  418.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  419.     // If mode button is held down, reset the control to center
  420.     if (StantonSCS3m.modifier[currentMode+side]) {
  421.         switch (currentMode) {
  422.             case "fx": engine.setValue("[Flanger]","lfoDelay",4950); break; // reset the control to center
  423.             case "eq": engine.setValue("[Channel"+deck+"]","filterMid",1); break;  // reset the control to center
  424.         }
  425.     }
  426.     else switch (currentMode) {
  427.         case "fx": script.absoluteSlider("[Flanger]","lfoDelay",value,50,10000); break;
  428.         case "eq": engine.setValue("[Channel"+deck+"]","filterMid",script.absoluteNonLin(value,0,1,4)); break;
  429.     }
  430. }
  431.  
  432. StantonSCS3m.Triple3 = function (channel, control, value, status, side) {
  433.     var deck = StantonSCS3m.SideToDeck(side);
  434.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  435.     // If mode button is held down, reset the control to center
  436.     if (StantonSCS3m.modifier[currentMode+side]) {
  437.         switch (currentMode) {
  438.             case "fx": engine.setValue("[Flanger]","lfoPeriod",1025000); break;
  439.             case "eq": engine.setValue("[Channel"+deck+"]","filterHigh",1); break;
  440.         }
  441.     }
  442.     else switch (currentMode) {
  443.         case "fx": script.absoluteSlider("[Flanger]","lfoPeriod",value,50000,2000000); break;
  444.         case "eq": engine.setValue("[Channel"+deck+"]","filterHigh",script.absoluteNonLin(value,0,1,4)); break;
  445.     }
  446. }
  447.  
  448.  
  449. StantonSCS3m.modeButton = function (channel, control, status, modeName, side) {
  450.     var deck = StantonSCS3m.SideToDeck(side);
  451.     var currentMode = StantonSCS3m.mode_store["[Channel"+deck+"]"];
  452.     var byte1 = 0x90 + channel;
  453.     if ((status & 0xF0) == 0x90) {    // If button down
  454.         // If the deck change button for the side in question is held down,
  455.         //  do special functions
  456.         if (StantonSCS3m.modifier["Deck"+side]) {
  457.             switch (modeName) {
  458.                 case "fx": engine.setValue("[Channel"+deck+"]","flanger",!engine.getValue("[Channel"+deck+"]","flanger")); break;
  459.                 case "eq": engine.setValue("[Channel"+deck+"]","beatsync",1); break;
  460.             }
  461.             return;
  462.         }
  463.         midi.sendShortMsg(byte1,control,0x03); // Make button purple
  464.         StantonSCS3m.modifier[modeName+side]=true;   // Set mode modifier flag
  465.         if (currentMode == modeName) {
  466.             StantonSCS3m.modifier["time"+modeName+side] = new Date();  // Store the current time in milliseconds
  467.         }
  468.         else StantonSCS3m.modifier["time"+modeName+side] = 0.0;
  469.         return;
  470.     }
  471.     
  472.     // If button up
  473.     
  474.     // If the deck change button for the side in question is held down,
  475.     //  do special functions
  476.     if (StantonSCS3m.modifier["Deck"+side]) {
  477.         switch (modeName) {
  478.             case "eq": engine.setValue("[Channel"+deck+"]","beatsync",0); break;
  479.         }
  480.         return;
  481.     }
  482.     
  483.     StantonSCS3m.modifier[currentMode+side] = StantonSCS3m.modifier[modeName+side] = 0;   // Clear mode modifier flags
  484.     switch (side) { // Make both mode buttons blue on that side
  485.         case "L":
  486.             midi.sendShortMsg(byte1,0x0A,0x01);
  487.             midi.sendShortMsg(byte1,0x0C,0x01);
  488.             break;
  489.         case "R":
  490.             midi.sendShortMsg(byte1,0x0B,0x01);
  491.             midi.sendShortMsg(byte1,0x0D,0x01);
  492.             break;
  493.     }
  494.     // If trying to switch to the same mode, or the same physical button was held down for over 1/3 of a second, stay in the current mode
  495.     if (currentMode == modeName || (StantonSCS3m.modifier["time"+modeName+side] != 0.0 && 
  496.         ((new Date() - StantonSCS3m.modifier["time"+modeName+side])>300))) {
  497.         switch (currentMode.charAt(currentMode.length-1)) {   // Return the button to its original color
  498.             case "2": midi.sendShortMsg(byte1,control,0x03); break; // Make button purple
  499.             case "3": midi.sendShortMsg(byte1,control,0x00); break; // Make button black
  500.             default:  midi.sendShortMsg(byte1,control,0x02); break; // Make button red
  501.         }
  502.         // Re-trigger signals
  503.         var signalList = StantonSCS3m.modeSignals[StantonSCS3m.mode_store["[Channel"+deck+"]"]];
  504.         for (i=0; i<signalList.length; i++) {
  505.             var group = signalList[i][0];
  506.             var calledFunction = signalList[i][2]+side;
  507.             if (group=="CurrentChannel") group = "[Channel"+deck+"]";
  508.             engine.trigger(group,signalList[i][1]);
  509.         }
  510.         return;
  511.     }
  512.     
  513.     if (StantonSCS3m.debug) print("Stanton SCS.3m: Switching to "+modeName.toUpperCase()+" mode on the "+side+" side");
  514.     switch (modeName.charAt(modeName.length-1)) {   // Set the button to its new color
  515.         case "2": midi.sendShortMsg(byte1,control,0x03); break;   // Make button purple
  516.         case "3": midi.sendShortMsg(byte1,control,0x00); break;   // Make button black
  517.         default:  midi.sendShortMsg(byte1,control,0x02); break;  // Make button red
  518.     }
  519.     StantonSCS3m.connectModeSignals(channel,side,true);  // Disconnect previous ones
  520.     StantonSCS3m.mode_store["[Channel"+deck+"]"] = modeName;
  521.     StantonSCS3m.connectModeSignals(channel,side);  // Connect new ones
  522. }
  523.  
  524. StantonSCS3m.VolumeL = function (channel, control, value, status) {
  525.     var deck = StantonSCS3m.SideToDeck("L");
  526.     switch (StantonSCS3m.mode_store["Master"]) {
  527.         case "main": 
  528.             if (StantonSCS3m.modifier["DeckL"]) {    // Adjust gain
  529.                 var newValue = engine.getValue("[Channel"+deck+"]","pregain")+(value-64)/128;
  530.                 if (newValue<0.0) newValue=0.0;
  531.                 if (newValue>4.0) newValue=4.0;
  532.                 engine.setValue("[Channel"+deck+"]","pregain",newValue);
  533.             }
  534.             else engine.setValue("[Channel"+deck+"]","volume",value/127);
  535.             break;
  536.         case "alt":
  537.             var newValue = engine.getValue("[Master]","headVolume")+(value-64)/128;
  538.             if (newValue<0.0) newValue=0.0;
  539.             if (newValue>5.0) newValue=5.0;
  540.             engine.setValue("[Master]","headVolume",newValue);
  541.             break;
  542.     }
  543. }
  544.  
  545. StantonSCS3m.VolumeR = function (channel, control, value, status) {
  546.     var deck = StantonSCS3m.SideToDeck("R");
  547.     switch (StantonSCS3m.mode_store["Master"]) {
  548.         case "main": 
  549.             if (StantonSCS3m.modifier["DeckR"]) {    // Adjust gain
  550.                 var newValue = engine.getValue("[Channel"+deck+"]","pregain")+(value-64)/128;
  551.                 if (newValue<0.0) newValue=0.0;
  552.                 if (newValue>4.0) newValue=4.0;
  553.                 engine.setValue("[Channel"+deck+"]","pregain",newValue);
  554.             }
  555.             else engine.setValue("[Channel"+deck+"]","volume",value/127);
  556.             break;
  557.         case "alt": 
  558.             var newValue = engine.getValue("[Master]","volume")+(value-64)/128;
  559.             if (newValue<0.0) newValue=0.0;
  560.             if (newValue>5.0) newValue=5.0;
  561.             engine.setValue("[Master]","volume",newValue);
  562.             break;
  563.     }
  564. }
  565.  
  566. StantonSCS3m.crossfader = function (channel, control, value) {
  567.     var deck;
  568.     // Needle dropping a la Numark's "Strip Search"
  569.     if (StantonSCS3m.modifier["DeckL"]) deck = StantonSCS3m.SideToDeck("L");
  570.     if (StantonSCS3m.modifier["DeckR"]) deck = StantonSCS3m.SideToDeck("R");
  571.     if (deck) {
  572.         engine.setValue("[Channel"+deck+"]","playposition",value/127);
  573.         return;
  574.     }
  575.     // Otherwise regular cross-fader
  576.     engine.setValue("[Master]","crossfader",(value-64)/63);
  577. }
  578.  
  579. StantonSCS3m.cueL = function (channel, control, value, status) {
  580.     StantonSCS3m.cue(status,"L");
  581. }
  582.  
  583. StantonSCS3m.cueR = function (channel, control, value, status) {
  584.     StantonSCS3m.cue(status,"R");
  585. }
  586.  
  587. StantonSCS3m.cue = function (status, side) {
  588.     var deck = StantonSCS3m.SideToDeck(side);
  589.     if ((status & 0xF0) == 0x90) {  // If button down
  590.         StantonSCS3m.modifier["cue"+side] = true;   // Set button modifier flag
  591.         engine.setValue("[Channel"+deck+"]","cue_default",1);
  592.     }
  593.     else {
  594.         StantonSCS3m.modifier["cue"+side] = false;
  595.         if (!StantonSCS3m.modifier["play"+side]) engine.setValue("[Channel"+deck+"]","cue_default",0);
  596.     }
  597. }
  598.  
  599.  
  600. StantonSCS3m.playL = function (channel, control, value, status) {
  601.     StantonSCS3m.play(status,"L");
  602. }
  603.  
  604. StantonSCS3m.playR = function (channel, control, value, status) {
  605.     StantonSCS3m.play(status,"R");
  606. }
  607.  
  608. StantonSCS3m.play = function (status, side) {
  609.     var deck = StantonSCS3m.SideToDeck(side);
  610.     if ((status & 0xF0) == 0x90) {  // If button down
  611.         StantonSCS3m.modifier["play"+side]=true;
  612.         if (StantonSCS3m.modifier["cue"+side]) engine.setValue("[Channel"+deck+"]","play",1);
  613.         else {
  614.             var currentlyPlaying = engine.getValue("[Channel"+deck+"]","play");
  615.             if (currentlyPlaying && engine.getValue("[Channel"+deck+"]","cue_default")==1) engine.setValue("[Channel"+deck+"]","cue_default",0);
  616.             engine.setValue("[Channel"+deck+"]","play", !currentlyPlaying);
  617.         }
  618.         return;
  619.     }
  620.     StantonSCS3m.modifier["play"+side]=false;
  621. }
  622.  
  623. // ------------------- Slot Functions -----------------------
  624.  
  625. StantonSCS3m.crossfaderLEDs = function (value) {
  626.     var add = StantonSCS3m.BoostCut(11, value, -1, 0, 1, 5, 5);
  627.     var byte1 = 0xB0 + StantonSCS3m.channel;
  628.     midi.sendShortMsg(byte1,0x0A,0x15+add);
  629. }
  630.  
  631. StantonSCS3m.needleDropLEDs = function (value) {
  632.     var add = StantonSCS3m.Peak(10,value,0,1);
  633.     var byte1 = 0xB0 + StantonSCS3m.channel;
  634.     midi.sendShortMsg(byte1,0x0A,1+add);
  635. }
  636.  
  637. StantonSCS3m.buttonLED = function (value, note, on, off) {
  638.     var byte1 = 0x90 + StantonSCS3m.channel;
  639.     if (value>0) midi.sendShortMsg(byte1,note,on);
  640.     else midi.sendShortMsg(byte1,note,off);
  641. }
  642.  
  643. StantonSCS3m.EQLButtonLED = function(value) {
  644.     StantonSCS3m.buttonLED(value, 0x0C, 0x02, 0x00);
  645. }
  646.  
  647. StantonSCS3m.EQRButtonLED = function(value) {
  648.     StantonSCS3m.buttonLED(value, 0x0D, 0x02, 0x00);
  649. }
  650.  
  651. StantonSCS3m.FXLButtonLED = function(value) {
  652.     StantonSCS3m.buttonLED(value, 0x0A, 0x02, 0x00);
  653. }
  654.  
  655. StantonSCS3m.FXRButtonLED = function(value) {
  656.     StantonSCS3m.buttonLED(value, 0x0B, 0x02, 0x00);
  657. }
  658.  
  659. StantonSCS3m.EQLowLEDsL = function (value) {
  660.     StantonSCS3m.EQLowLEDs(value,"L");
  661. }
  662.  
  663. StantonSCS3m.EQLowLEDsR = function (value) {
  664.     StantonSCS3m.EQLowLEDs(value,"R");
  665. }
  666.  
  667. StantonSCS3m.EQLowLEDs = function (value, side) {
  668.     var add = StantonSCS3m.BoostCut(7,value, 0, 1, 4, 3, 3);
  669.     var byte1 = 0xB0 + StantonSCS3m.channel;
  670.     switch (side) {
  671.         case "L": midi.sendShortMsg(byte1,0x02,0x15+add); break;
  672.         case "R": midi.sendShortMsg(byte1,0x03,0x15+add); break;
  673.     }
  674. }
  675.  
  676. StantonSCS3m.EQMidLEDsL = function (value) {
  677.     StantonSCS3m.EQMidLEDs(value,"L");
  678. }
  679.  
  680. StantonSCS3m.EQMidLEDsR = function (value) {
  681.     StantonSCS3m.EQMidLEDs(value,"R");
  682. }
  683.  
  684. StantonSCS3m.EQMidLEDs = function (value, side) {
  685.     var add = StantonSCS3m.BoostCut(7,value, 0, 1, 4, 3, 3);
  686.     var byte1 = 0xB0 + StantonSCS3m.channel;
  687.     switch (side) {
  688.         case "L": midi.sendShortMsg(byte1,0x04,0x15+add); break;
  689.         case "R": midi.sendShortMsg(byte1,0x05,0x15+add); break;
  690.     }
  691. }
  692.  
  693. StantonSCS3m.EQHighLEDsL = function (value) {
  694.     StantonSCS3m.EQHighLEDs(value,"L");
  695. }
  696.  
  697. StantonSCS3m.EQHighLEDsR = function (value) {
  698.     StantonSCS3m.EQHighLEDs(value,"R");
  699. }
  700.  
  701. StantonSCS3m.EQHighLEDs = function (value, side) {
  702.     var add = StantonSCS3m.BoostCut(7,value, 0, 1, 4, 3, 3);
  703.     var byte1 = 0xB0 + StantonSCS3m.channel;
  704.     switch (side) {
  705.         case "L": midi.sendShortMsg(byte1,0x06,0x15+add); break;
  706.         case "R": midi.sendShortMsg(byte1,0x07,0x15+add); break;
  707.     }
  708. }
  709.  
  710. StantonSCS3m.FXDepthLEDsL = function (value) {
  711.     StantonSCS3m.FXDepthLEDs(value,"L");
  712. }
  713.  
  714. StantonSCS3m.FXDepthLEDsR = function (value) {
  715.     StantonSCS3m.FXDepthLEDs(value,"R");
  716. }
  717.  
  718. StantonSCS3m.FXDepthLEDs = function (value, side) {
  719.     var add = StantonSCS3m.Peak(7,value,0,1);
  720.     var byte1 = 0xB0 + StantonSCS3m.channel;
  721.     switch (side) {
  722.         case "L": midi.sendShortMsg(byte1,0x02,0x28+add); break;
  723.         case "R": midi.sendShortMsg(byte1,0x03,0x28+add); break;
  724.     }
  725. }
  726.  
  727. StantonSCS3m.FXDelayLEDsL = function (value) {
  728.     StantonSCS3m.FXDelayLEDs(value,"L");
  729. }
  730.  
  731. StantonSCS3m.FXDelayLEDsR = function (value) {
  732.     StantonSCS3m.FXDelayLEDs(value,"R");
  733. }
  734.  
  735. StantonSCS3m.FXDelayLEDs = function (value, side) {
  736.     var add = StantonSCS3m.Peak(7,value,50,10000);
  737.     var byte1 = 0xB0 + StantonSCS3m.channel;
  738.     switch (side) {
  739.         case "L": midi.sendShortMsg(byte1,0x04,0x28+add); break;
  740.         case "R": midi.sendShortMsg(byte1,0x05,0x28+add); break;
  741.     }
  742. }
  743.  
  744. StantonSCS3m.FXPeriodLEDsL = function (value) {
  745.     StantonSCS3m.FXPeriodLEDs(value,"L");
  746. }
  747.  
  748. StantonSCS3m.FXPeriodLEDsR = function (value) {
  749.     StantonSCS3m.FXPeriodLEDs(value,"R");
  750. }
  751.  
  752. StantonSCS3m.FXPeriodLEDs = function (value, side) {
  753.     var add = StantonSCS3m.Peak(7,value,50000,2000000);
  754.     var byte1 = 0xB0 + StantonSCS3m.channel;
  755.     switch (side) {
  756.         case "L": midi.sendShortMsg(byte1,0x06,0x28+add); break;
  757.         case "R": midi.sendShortMsg(byte1,0x07,0x28+add); break;
  758.     }
  759. }
  760.  
  761. StantonSCS3m.pitchLEDsL = function (value) {
  762.     StantonSCS3m.pitchLEDs(value,"L");
  763. }
  764.  
  765. StantonSCS3m.pitchLEDsR = function (value) {
  766.     StantonSCS3m.pitchLEDs(value,"R");
  767. }
  768.  
  769. StantonSCS3m.pitchLEDs = function (value, side) {
  770.     var add = StantonSCS3m.BoostCut(7, value, -1, 0, 1, 3, 3);
  771.     var byte1 = 0xB0 + StantonSCS3m.channel;
  772.     switch (side) {
  773.         case "L": midi.sendShortMsg(byte1,0x00,0x15+add); break;
  774.         case "R": midi.sendShortMsg(byte1,0x01,0x15+add); break;
  775.     }
  776. }
  777.  
  778. StantonSCS3m.gainLEDsL = function (value) {
  779.     StantonSCS3m.gainLEDs(value,0x08);
  780. }
  781.  
  782. StantonSCS3m.gainLEDsR = function (value) {
  783.     StantonSCS3m.gainLEDs(value,0x09);
  784. }
  785.  
  786. StantonSCS3m.gainLEDs = function (value, CC) {
  787.     var add = StantonSCS3m.BoostCut(7, value, 0.0, 1.0, 4.0, 3, 3);
  788.     midi.sendShortMsg(0xB0 + StantonSCS3m.channel,CC,0x15+add);
  789. }
  790.  
  791. StantonSCS3m.volumeLEDsL = function (value) {
  792.     StantonSCS3m.volumeLEDs(value,0x08);
  793. }
  794.  
  795. StantonSCS3m.volumeLEDsR = function (value) {
  796.     StantonSCS3m.volumeLEDs(value,0x09);
  797. }
  798.  
  799. StantonSCS3m.VuL = function (value) {
  800.     StantonSCS3m.volumeLEDs(value,0x0C);
  801. }
  802.  
  803. StantonSCS3m.VuR = function (value) {
  804.     StantonSCS3m.volumeLEDs(value,0x0D);
  805. }
  806.  
  807. StantonSCS3m.volumeLEDs = function (value, CC) {
  808.     var add = StantonSCS3m.Peak(7, value, 0, 1);
  809.     midi.sendShortMsg(0xB0 + StantonSCS3m.channel,CC,0x28+add);
  810. }
  811.  
  812. StantonSCS3m.masterVolumeLEDsL = function (value) {
  813.     StantonSCS3m.masterVolumeLEDs(value,0x08);
  814. }
  815.  
  816. StantonSCS3m.masterVolumeLEDsR = function (value) {
  817.     StantonSCS3m.masterVolumeLEDs(value,0x09);
  818. }
  819.  
  820. StantonSCS3m.masterVolumeLEDs = function (value, CC) {
  821.     var add = StantonSCS3m.BoostCut(7, value, 0.0, 1.0, 5.0, 3, 3);
  822.     var byte1 = 0xB0 + StantonSCS3m.channel;
  823.     midi.sendShortMsg(byte1,CC,0x15+add);
  824. }
  825.  
  826. StantonSCS3m.BoostCut = function (numberLights, value, low, mid, high, lowMidSteps, midHighSteps) {
  827.     var LEDs = 0;
  828.     var lowMidInterval = (mid-low)/(lowMidSteps*2);     // Half the actual interval so the LEDs light in the middle of the interval
  829.     var midHighInterval = (high-mid)/(midHighSteps*2);  // Half the actual interval so the LEDs light in the middle of the interval
  830.     value=value.toFixed(4);
  831.     if (value>low) LEDs++;
  832.     if (value>low+lowMidInterval) LEDs++;
  833.     if (value>low+lowMidInterval*3) LEDs++;
  834.     if (numberLights>=9 && value>low+lowMidInterval*5) LEDs++;
  835.     if (numberLights>=11 && value>low+lowMidInterval*7) LEDs++;
  836.     if (value>mid+midHighInterval) LEDs++;
  837.     if (value>mid+midHighInterval*3) LEDs++;
  838.     if (numberLights>=9 && value>mid+midHighInterval*5) LEDs++;
  839.     if (numberLights>=11 && value>mid+midHighInterval*7) LEDs++;
  840.     if (value>=high) LEDs++;
  841.     return LEDs;
  842. }
  843.  
  844. StantonSCS3m.Peak = function (numberLights, value, low, high) {
  845.     var LEDs = 0;
  846.     var halfInterval = (high-low)/((numberLights-1)*2);    // Half the actual interval so the LEDs light in the middle of the interval
  847.     value=value.toFixed(4);
  848.     if (value>low) LEDs++;
  849.     if (value>low+halfInterval) LEDs++;
  850.     if (value>low+halfInterval*3) LEDs++;
  851.     if (value>low+halfInterval*5) LEDs++;
  852.     if (value>low+halfInterval*7) LEDs++;
  853.     if (value>low+halfInterval*9) LEDs++;
  854.     if (numberLights>=8 && value>low+halfInterval*11) LEDs++;
  855.     if (numberLights>=9 && value>low+halfInterval*13) LEDs++;
  856.     if (numberLights>=10 && value>low+halfInterval*15) LEDs++;
  857.     if (numberLights>=11 && value>low+halfInterval*17) LEDs++;
  858.     if (value>=high) LEDs++;
  859.     return LEDs;
  860. }
  861.  
  862. /*
  863. Possibly add:
  864. - (Deck + Play = Reverse?)
  865. - Reset Master & head vols?
  866.  
  867. TODO:
  868. - Rework slider mode changes to use presets or timers
  869. - Don't use the hardware buttons for pitch bending. Switch the sliders to absolute mode & use the formula from the SCS.3d script.
  870. */
  871.