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 / Numark-Total-Control-scripts.js < prev    next >
Encoding:
Text File  |  2010-12-02  |  16.7 KB  |  459 lines

  1. function NumarkTotalControl() {}
  2.  
  3. NumarkTotalControl.init = function(id) {    // called when the MIDI device is opened & set up
  4.     NumarkTotalControl.id = id;    // Store the ID of this device for later use
  5.     
  6.     NumarkTotalControl.directoryMode = false;
  7.     
  8.     NumarkTotalControl.scratchMode = [false, false];
  9.     NumarkTotalControl.scratchTimer = [-1, -1];
  10.     
  11.     NumarkTotalControl.simpleCue = false;
  12.     
  13.     NumarkTotalControl.extendedLooping = false;
  14.     NumarkTotalControl.oldLoopStart = [-1, -1];
  15.     NumarkTotalControl.extendedLoopingType = { "None": 0, "SetBegin": 1, "SetLength": 2 };
  16.     NumarkTotalControl.extendedLoopingState = [NumarkTotalControl.extendedLoopingType.None, NumarkTotalControl.extendedLoopingType.None];
  17.     NumarkTotalControl.extendedLoopingChanged = [false, false];
  18.     NumarkTotalControl.extendedLoopingLEDState = [false, false];
  19.     NumarkTotalControl.extendedLoopingLEDTimer = [-1, -1];
  20.     NumarkTotalControl.extendedLoopingJogCarryOver = [0, 0];
  21.     
  22.     NumarkTotalControl.leds = [
  23.         // Common
  24.         { "directory": 0x56, "simpleCue": 0x33, "extendedLooping": 0x44 },
  25.         // Deck 1
  26.         { "rate": 0x34, "tap": 0x30, "scratchMode": 0x31, "loopIn": 0x3a, "loopOut": 0x3b, "loopHalve": 0x38, "loopDouble": 0x39 },
  27.         // Deck 2
  28.         { "rate": 0x43, "tap": 0x47, "scratchMode": 0x45, "loopIn": 0x4a, "loopOut": 0x4b, "loopHalve": 0x48, "loopDouble": 0x49 }
  29.     ];
  30.     
  31.     NumarkTotalControl.setLED(NumarkTotalControl.leds[1]["rate"], true);    // Turn on 0 rate lights
  32.     NumarkTotalControl.setLED(NumarkTotalControl.leds[2]["rate"], true);    // Turn on 0 rate lights
  33.     
  34.     engine.connectControl("[Channel1]", "loop_enabled", "NumarkTotalControl.loopLEDs");
  35.     engine.connectControl("[Channel2]", "loop_enabled", "NumarkTotalControl.loopLEDs");
  36. }
  37.  
  38. NumarkTotalControl.shutdown = function(id) {    // called when the MIDI device is closed
  39.     engine.connectControl("[Channel1]", "loop_enabled", "NumarkTotalControl.loopLEDs", true);
  40.     engine.connectControl("[Channel2]", "loop_enabled", "NumarkTotalControl.loopLEDs", true);
  41.     
  42.     var lowestLED = 0x30;
  43.     var highestLED = 0x56;
  44.     for (var i=lowestLED; i<=highestLED; i++) {
  45.         NumarkTotalControl.setLED(i, false);    // Turn off all the lights
  46.     }
  47. }
  48.  
  49. NumarkTotalControl.groupToDeck = function(group) {
  50.     var matches = group.match(/^\[Channel(\d+)\]$/);
  51.     if (matches == null) {
  52.         return -1;
  53.     } else {
  54.         return matches[1];
  55.     }
  56. }
  57.  
  58. NumarkTotalControl.samplesPerBeat = function(group) {
  59.     // FIXME: Get correct samplerate and channels for current deck
  60.     var sampleRate = 44100;
  61.     var channels = 2;
  62.     var bpm = engine.getValue(group, "file_bpm");
  63.     return channels * sampleRate * 60 / bpm;
  64. }
  65.  
  66. NumarkTotalControl.setLED = function(value, status) {
  67.     if (status) {
  68.         status = 0x64;
  69.     } else {
  70.         status = 0x00;
  71.     }
  72.     midi.sendShortMsg(0x90, value, status);
  73. }
  74.  
  75. NumarkTotalControl.selectKnob = function(channel, control, value, status, group) {
  76.     if (value > 63) {
  77.         value = value - 128;
  78.     }
  79.     if (NumarkTotalControl.directoryMode) {
  80.         if (value > 0) {
  81.             for (var i = 0; i < value; i++) {
  82.                 engine.setValue(group, "SelectNextPlaylist", 1);
  83.             }
  84.         } else {
  85.             for (var i = 0; i < -value; i++) {
  86.                 engine.setValue(group, "SelectPrevPlaylist", 1);
  87.             }
  88.         }
  89.     } else {
  90.         engine.setValue(group, "SelectTrackKnob", value);
  91.     }
  92. }
  93.  
  94. NumarkTotalControl.loopIn = function(channel, control, value, status, group) {
  95.     if (value) {
  96.         if (engine.getValue(group, "loop_enabled")) {
  97.             engine.setValue(group, "reloop_exit", 1);
  98.         }
  99.         engine.setValue(group, "loop_in", 1);
  100.         engine.setValue(group, "loop_end_position", -1);
  101.     }
  102. }
  103.  
  104. NumarkTotalControl.loopOut = function(channel, control, value, status, group) {
  105.     if (value) {
  106.         var start = engine.getValue(group, "loop_start_position");
  107.         var end = engine.getValue(group, "loop_end_position");
  108.         if (start != -1) {
  109.             if (end != -1) {
  110.                 // Loop In and Out set -> call Reloop/Exit
  111.                 engine.setValue(group, "reloop_exit", 1);
  112.             } else {
  113.                 // Loop In set -> call Loop Out
  114.                 if (NumarkTotalControl.extendedLooping) {
  115.                     var deck = NumarkTotalControl.groupToDeck(group);
  116.                     if (NumarkTotalControl.oldLoopStart[deck-1] == -1) {
  117.                         // Get current position by temporary setting loop start
  118.                         NumarkTotalControl.oldLoopStart[deck-1] = start;
  119.                         engine.setValue(group, "loop_in", 1);
  120.                         engine.beginTimer(20, "NumarkTotalControl.loopExtendedAdjustment('" + group + "')", true);
  121.                     }
  122.                 } else {
  123.                     engine.setValue(group, "loop_out", 1);
  124.                 }
  125.             }
  126.         }
  127.     }
  128. }
  129.  
  130. // Adjust loop length
  131. NumarkTotalControl.loopExtendedAdjustment = function(group) {
  132.     var deck = NumarkTotalControl.groupToDeck(group);
  133.     // Check if temporary loop start is already set
  134.     var start = engine.getValue(group, "loop_start_position");
  135.     if (start == NumarkTotalControl.oldLoopStart[deck-1]) {
  136.         // Still old loop start -> retry later
  137.         engine.beginTimer(20, "NumarkTotalControl.loopExtendedAdjustment('" + group + "')", true);
  138.         return;
  139.     }
  140.     
  141.     // Restore loop start position
  142.     var currentPosition = start;
  143.     start = NumarkTotalControl.oldLoopStart[deck-1];
  144.     engine.setValue(group, "loop_start_position", start);
  145.     NumarkTotalControl.oldLoopStart[deck-1] = -1;
  146.     var len = currentPosition - start;
  147.     
  148.     // Calculate nearest beat
  149.     var beatSamples = NumarkTotalControl.samplesPerBeat(group);
  150.     var lenInBeats = len / beatSamples;
  151.     if (lenInBeats > 1) {
  152.         print("Full: " + Math.ceil(lenInBeats));
  153.         print("Mult2: " + (Math.ceil(lenInBeats / 2) * 2));
  154.         print("Pot2: " + Math.pow(2, Math.ceil(Math.log(lenInBeats) / Math.log(2))));
  155.         
  156.         // Round to full beats
  157.         //lenInBeats = Math.ceil(lenInBeats);
  158.         
  159.         // Round to 2*x beats
  160.         //lenInBeats = Math.ceil(lenInBeats / 2) * 2;
  161.         
  162.         // Round to 2^x beats
  163.         lenInBeats = Math.pow(2, Math.ceil(Math.log(lenInBeats) / Math.log(2)));
  164.     } else {
  165.         print("Full: 1 / " + Math.floor(1 / lenInBeats));
  166.         print("Mult2: 1 / " + (Math.floor(1 / lenInBeats / 2) * 2));
  167.         print("Pot2: 1 / " + Math.pow(2, Math.floor(Math.log(1 / lenInBeats) / Math.log(2))));
  168.         
  169.         // Round to beat fragments
  170.         //lenInBeats = 1 / Math.floor(1 / lenInBeats);
  171.         
  172.         // Round to fragments of 2*x beats
  173.         //lenInBeats = 1 / (Math.floor(1 / lenInBeats / 2) * 2);
  174.         
  175.         // Round to fragments of 2^x beats
  176.         lenInBeats = 1 / Math.pow(2, Math.floor(Math.log(1 / lenInBeats) / Math.log(2)));
  177.     }
  178.     len = lenInBeats * beatSamples;
  179.     
  180.     // Set calculated loop end
  181.     engine.setValue(group, "loop_end_position", start + len);
  182.     
  183.     // Start looping
  184.     engine.setValue(group, "reloop_exit", 1);
  185. }
  186.  
  187. // Activates alternative function
  188. // Called by timer after button was 1sec pressed or by jog wheel movement
  189. NumarkTotalControl.loopExtendedChange = function(group, timerCall) {
  190.     var deck = NumarkTotalControl.groupToDeck(group);
  191.     if (!NumarkTotalControl.extendedLoopingChanged[deck-1]) {
  192.         if (!timerCall) {
  193.             // Stop extended loop change timer
  194.             engine.stopTimer(NumarkTotalControl.extendedLoopingLEDTimer[deck-1]);
  195.         }
  196.         NumarkTotalControl.extendedLoopingChanged[deck-1] = true;
  197.         // Get current LED status
  198.         NumarkTotalControl.extendedLoopingLEDState[deck-1] = engine.getValue(group, "loop_enabled");
  199.         // Start LED blink timer
  200.         NumarkTotalControl.loopLEDBlink(deck);
  201.         NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = engine.beginTimer(333, "NumarkTotalControl.loopLEDBlink(" + deck + ")");
  202.     }
  203. }
  204.  
  205. // Set LEDs to current loop status
  206. NumarkTotalControl.loopLEDs = function(value, group, key) {
  207.     var status = false;
  208.     var deck = NumarkTotalControl.groupToDeck(group);
  209.     if (value) {
  210.         status = true;
  211.     }
  212.     NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopOut"], status);
  213.     
  214.     if (!NumarkTotalControl.extendedLooping) {
  215.         status = false;
  216.     }
  217.     NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopHalve"], status);
  218.     NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopDouble"], status);
  219. }
  220.  
  221. // Let LED blink on alternative function
  222. NumarkTotalControl.loopLEDBlink = function(deck) {
  223.     var led;
  224.     switch (NumarkTotalControl.extendedLoopingState[deck-1]) {
  225.         case NumarkTotalControl.extendedLoopingType.SetBegin:
  226.             led = NumarkTotalControl.leds[deck]["loopHalve"];
  227.             break;
  228.         case NumarkTotalControl.extendedLoopingType.SetLength:
  229.             led = NumarkTotalControl.leds[deck]["loopDouble"];
  230.             break;
  231.         default:
  232.             return;
  233.     }
  234.     if (NumarkTotalControl.extendedLoopingLEDState[deck-1]) {
  235.         NumarkTotalControl.extendedLoopingLEDState[deck-1] = false;
  236.     } else {
  237.         NumarkTotalControl.extendedLoopingLEDState[deck-1] = true;
  238.     }
  239.     NumarkTotalControl.setLED(led, NumarkTotalControl.extendedLoopingLEDState[deck-1]);
  240. }
  241.  
  242. NumarkTotalControl.extendedFunctionButton = function(normalFunction, extendedLoopingFactor, extendedLoopingType, group, value) {
  243.     var deck = NumarkTotalControl.groupToDeck(group);
  244.     if (NumarkTotalControl.extendedLooping) {
  245.         var start = engine.getValue(group, "loop_start_position");
  246.         var end = engine.getValue(group, "loop_end_position");
  247.         if (value) {
  248.             if ((start != -1) && (end != -1) && (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.None)) {
  249.                 NumarkTotalControl.extendedLoopingState[deck-1] = extendedLoopingType;
  250.                 NumarkTotalControl.extendedLoopingChanged[deck-1] = false;
  251.                 NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = 0;
  252.                 // Start alternative function timer -> activated after button was 1sec pressed or jog wheel movement (see jogWheel function)
  253.                 NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = engine.beginTimer(1000, "NumarkTotalControl.loopExtendedChange('" + group + "', true)", true);
  254.             }
  255.         } else {
  256.             // Check if alternative function wasn't used
  257.             if (!NumarkTotalControl.extendedLoopingChanged[deck-1] && (start != -1) && (end != -1)) {
  258.                 // Call default function
  259.                 engine.setValue(group, "loop_end_position", start + (end - start) * extendedLoopingFactor);
  260.             }
  261.             // Stop LED blink or extended loop change timer
  262.             engine.stopTimer(NumarkTotalControl.extendedLoopingLEDTimer[deck-1]);
  263.             NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = -1;
  264.             // Reset LEDs
  265.             NumarkTotalControl.loopLEDs(engine.getValue(group, "loop_enabled"), group, "loop_enabled");
  266.             // Reset alternative function variables
  267.             NumarkTotalControl.extendedLoopingState[deck-1] = NumarkTotalControl.extendedLoopingType.None;
  268.             NumarkTotalControl.extendedLoopingChanged[deck-1] = false;
  269.             NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = 0;
  270.         }
  271.     } else {
  272.         if (value) {
  273.             engine.setValue(group, normalFunction, 1);
  274.         } else {
  275.             engine.setValue(group, normalFunction, 0);
  276.         }
  277.     }
  278. }
  279.  
  280. NumarkTotalControl.leftFunction = function(channel, control, value, status, group) {
  281.     NumarkTotalControl.extendedFunctionButton("rate_temp_down", 0.5, NumarkTotalControl.extendedLoopingType.SetBegin, group, value);
  282. }
  283.  
  284. NumarkTotalControl.rightFunction = function(channel, control, value, status, group) {
  285.     NumarkTotalControl.extendedFunctionButton("rate_temp_up", 2, NumarkTotalControl.extendedLoopingType.SetLength, group, value);
  286. }
  287.  
  288. NumarkTotalControl.finePitch = function(channel, control, value, status, group) {
  289.     if (value > 63) {
  290.         value = value - 128;
  291.     }
  292.     engine.setValue(group, "rate", engine.getValue(group, "rate") + value / 512);
  293. }
  294.  
  295. // Fixes cue_set glitches
  296. NumarkTotalControl.setCue = function(channel, control, value, status, group) {
  297.     if (value) {
  298.         engine.setValue(group, "cue_set", 1);
  299.     }
  300. }
  301.  
  302. // If playing, stutters from cuepoint; otherwise jumps to cuepoint and stops
  303. NumarkTotalControl.playFromCue = function(channel, control, value, status, group) {
  304.     if (NumarkTotalControl.simpleCue) {
  305.         if (value) {
  306.             if (engine.getValue(group, "play")) {
  307.                 engine.setValue(group, "cue_goto", 1);
  308.             } else {
  309.                 engine.setValue(group, "cue_gotoandstop", 1);
  310.             }
  311.         }
  312.     } else {
  313.         if (value) {
  314.             if (engine.getValue(group, "play")) {
  315.                 engine.setValue(group, "play", 0);
  316.                 engine.setValue(group, "cue_gotoandstop", 1);
  317.             } else {
  318.                 engine.setValue(group, "cue_preview", 1);
  319.             }
  320.         } else {
  321.             engine.setValue(group, "cue_preview", 0);
  322.         }
  323.     }
  324. }
  325.  
  326. // Jog values: (counter) fast slow still slow fast (clockwise)
  327. // Jog values:            064  127   -   001  063
  328. NumarkTotalControl.jogWheel = function(channel, control, value, status, group) {
  329.     var deck = NumarkTotalControl.groupToDeck(group);
  330.     var adjustedJog = parseFloat(value);
  331.     var posNeg = 1;
  332.     if (adjustedJog > 63) {    // Counter-clockwise
  333.         posNeg = -1;
  334.         adjustedJog = value - 128;
  335.     }
  336.     
  337.     if (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.SetBegin) {
  338.         var start = engine.getValue(group, "loop_start_position");
  339.         var end = engine.getValue(group, "loop_end_position");
  340.         if ((start != -1) && (end != -1)) {
  341.             // Activate alternative function SetBegin
  342.             NumarkTotalControl.loopExtendedChange(group, false);
  343.             // Adjust jog speed
  344.             // FIXME: Get correct sample rate and channels from deck
  345.             var channels = 2;
  346.             var sampleRate = 44100;
  347.             adjustedJog = adjustedJog * channels * sampleRate / 600;
  348.             // Move loop
  349.             engine.setValue(group, "loop_start_position", start + adjustedJog);
  350.             engine.setValue(group, "loop_end_position", end + adjustedJog);
  351.         }
  352.     } else if (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.SetLength) {
  353.         var start = engine.getValue(group, "loop_start_position");
  354.         var end = engine.getValue(group, "loop_end_position");
  355.         if ((start != -1) && (end != -1)) {
  356.             // Activate alternative function SetLength
  357.             NumarkTotalControl.loopExtendedChange(group, false);
  358.             // Adjust jog speed and add remaining value from last jog change
  359.             adjustedJog = adjustedJog / 40 + NumarkTotalControl.extendedLoopingJogCarryOver[deck-1];
  360.             var beats;
  361.             // Round to full beats
  362.             if (adjustedJog > 0) {
  363.                 beats = Math.floor(adjustedJog);
  364.             } else {
  365.                 beats = Math.ceil(adjustedJog);
  366.             }
  367.             // Save remaining value for next jog change
  368.             NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = adjustedJog - beats;
  369.             // Set new loop end
  370.             engine.setValue(group, "loop_end_position", end + beats * NumarkTotalControl.samplesPerBeat(group));
  371.         }
  372.     } else if (NumarkTotalControl.scratchMode[deck-1]) {
  373.         if (NumarkTotalControl.scratchTimer[deck-1] == -1) {
  374.             engine.scratchEnable(deck, 128, 33+1/3, 1.0/8, (1.0/8)/32);
  375.         } else {
  376.             engine.stopTimer(NumarkTotalControl.scratchTimer[deck-1]);
  377.         }
  378.         engine.scratchTick(deck, adjustedJog);
  379.         NumarkTotalControl.scratchTimer[deck-1] = engine.beginTimer(20, "NumarkTotalControl.jogWheelStopScratch(" + deck + ")", true);
  380.     } else {
  381.         var gammaInputRange = 64;    // Max jog speed
  382.         var maxOutFraction = 0.5;    // Where on the curve it should peak; 0.5 is half-way
  383.         var sensitivity = 0.5;        // Adjustment gamma
  384.         var gammaOutputRange = 3;    // Max rate change
  385.         if (engine.getValue(group,"play")) {
  386.             adjustedJog = posNeg * gammaOutputRange * Math.pow(Math.abs(adjustedJog) / (gammaInputRange * maxOutFraction), sensitivity);
  387.         } else {
  388.             adjustedJog = gammaOutputRange * adjustedJog / (gammaInputRange * maxOutFraction);
  389.         }
  390.         engine.setValue(group, "jog", adjustedJog);
  391.     }
  392. }
  393.  
  394. NumarkTotalControl.jogWheelStopScratch = function(deck) {
  395.     NumarkTotalControl.scratchTimer[deck-1] = -1;
  396.     engine.scratchDisable(deck);
  397. }
  398.  
  399. NumarkTotalControl.tap = function(channel, control, value, status, group) {
  400.     var deck = NumarkTotalControl.groupToDeck(group);
  401.     if (value) {
  402.         NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["tap"], true);
  403.         bpm.tapButton(deck);
  404.     } else {
  405.         NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["tap"], false);
  406.     }
  407. }
  408.  
  409. NumarkTotalControl.toggleDirectoryMode = function(channel, control, value, status, group) {
  410.     // Toggle setting and light
  411.     if (value) {
  412.         if (NumarkTotalControl.directoryMode) {
  413.             NumarkTotalControl.directoryMode = false;
  414.         } else {
  415.             NumarkTotalControl.directoryMode = true;
  416.         }
  417.         NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["directory"], NumarkTotalControl.directoryMode);
  418.     }
  419. }
  420.  
  421. NumarkTotalControl.toggleScratchMode = function(channel, control, value, status, group) {
  422.     var deck = NumarkTotalControl.groupToDeck(group);
  423.     // Toggle setting and light
  424.     if (value) {
  425.         if (NumarkTotalControl.scratchMode[deck-1]) {
  426.             NumarkTotalControl.scratchMode[deck-1] = false;
  427.         } else {
  428.             NumarkTotalControl.scratchMode[deck-1] = true;
  429.         }
  430.         NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["scratchMode"], NumarkTotalControl.scratchMode[deck-1]);
  431.     }
  432. }
  433.  
  434. NumarkTotalControl.toggleSimpleCue = function(channel, control, value, status, group) {
  435.     // Toggle setting and light
  436.     if (value) {
  437.         if (NumarkTotalControl.simpleCue) {
  438.             NumarkTotalControl.simpleCue = false;
  439.         } else {
  440.             NumarkTotalControl.simpleCue = true;
  441.         }
  442.         NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["simpleCue"], NumarkTotalControl.simpleCue);
  443.     }
  444. }
  445.  
  446. NumarkTotalControl.toggleExtendedLooping = function(channel, control, value, status, group) {
  447.     // Toggle setting and light
  448.     if (value) {
  449.         if (NumarkTotalControl.extendedLooping) {
  450.             NumarkTotalControl.extendedLooping = false;
  451.         } else {
  452.             NumarkTotalControl.extendedLooping = true;
  453.         }
  454.         NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["extendedLooping"], NumarkTotalControl.extendedLooping);
  455.         NumarkTotalControl.loopLEDs(engine.getValue("[Channel1]", "loop_enabled"), "[Channel1]", "loop_enabled");
  456.         NumarkTotalControl.loopLEDs(engine.getValue("[Channel2]", "loop_enabled"), "[Channel2]", "loop_enabled");
  457.     }
  458. }
  459.