diff --git a/res/controllers/Numark-Mixtrack-3-scripts.js b/res/controllers/Numark-Mixtrack-3-scripts.js index 643b00a5c061..75038eead1d4 100644 --- a/res/controllers/Numark-Mixtrack-3-scripts.js +++ b/res/controllers/Numark-Mixtrack-3-scripts.js @@ -4,11 +4,11 @@ **********************************************************************/ // TrackEndWarning: "true": when you reach the end of the track, // the jog wheel Button will flash. "false": No flash of Jog Wheel Button -var TrackEndWarning = true; +var TrackEndWarning = true; //iCutEnabled: iCut mode will automatically cut your track with the cross fader // when SHIFT enabled and scratching with the jog wheel -var iCutEnabled = true; +var iCutEnabled = true; // fastSeekEnabled: enable fast seek with Jog Wheel with Wheel Off and Shift ON // Shift can be locked or not @@ -20,30 +20,20 @@ var smartPFL = true; // use beatlooproll instead of beatloop var beatlooprollActivate = false; -// PAD Loop button behavior: "true": Loop stops when finger release. -//"false" will force start loop on press and stop on 2nd press -var PADLoopButtonHold = false; - -// PAD Sample button behavior:"true": Sampler stops when finger release. -//"false" will force start Sampler on press and stop on 2nd press -var PADSampleButtonHold = false; - -// LED Flash on Beat Active : "true": TAP LED will flash to the beat -// if Shift Lock is enable TAP LED will remain ON -var OnBeatActiveFlash = true; - // If Dark Metal Skin is used, set this to true: // this is required to expand library view with DM skin. var DarkMetalSkin = false; -// Use Beat knob to adjust Sampler Volume. -// If "true": Deck 1 adjusts Samplers 1-4 ; Deck 2 adjusts Samplers 5-8 -// Shift + Beat knob moves beat grid -// If false; beat knob will adjust beatgrid, shift + knob will adjust grid size -var BeatKnobAsSamplerVolume = true; +// Effects mode +// 1 for multi-effect mode (3 effects controlled in each EffectUnit, best used with Deere Skin) +// 2 for single effect mode (1 effect controlled in each EffectUnit, best used with skins other than Deere) +var FXmode = 1; // multi-effect mode by default //Disable Play on Sync button Double Press -var noPlayOnSyncDoublePress = false; +var noPlayOnSyncDoublePress = false; + +// allow pitch bend with wheel when wheel is not active +var PitchBendOnWheelOff = true; /************************** * scriptpause @@ -59,13 +49,20 @@ var scriptpause = 0; * Constants for scratching : **************************/ var intervalsPerRev = 1200, - rpm = 33 + 1 / 3, //Like a real vinyl !!! :) - alpha = 1.0 / 8, //Adjust to suit. + rpm = 33 + 1 / 3, //Like a real vinyl !!! :) + alpha = 1.0 / 8, //Adjust to suit. beta = alpha / 32; //Adjust to suit. +/************************** + * Loop Size array + * first 4 values used for Autoloop Not shifted + * last 4 values used for Autoloop Shifted + **************************/ +var loopsize = [2, 4, 8, 16, 0.125, 0.25, 0.5, 1]; + /************************ GPL v2 licence ***************************** * Numark Mixtrack Pro 3 controller script - * Author: Stéphane Morin, largely based on script from Chloé AVRILLON (DJ Chloé) + * Author: Stéphane Morin * * Key features * ------------ @@ -73,6 +70,8 @@ var intervalsPerRev = 1200, * - Fader Start * - press/double press/long press handling * - Smart PFL + * - 4 deck support + * - Full effect chains support from Deere Skin ********************************************************************** * User References * --------------- @@ -87,91 +86,28 @@ var intervalsPerRev = 1200, * * Revision history * ---------------- - * 2016-01-12 (0.9) - Chloé AVRILLON - * - Initial revision for Mixxx 2.0+ - * - GPL v2 licence, rework of this header, JSHint.com quality check, - * a few comments, minor changes, typos - * - Make some code reusable (lights : LED object; Special Buttons, iCUT) - * 2016-01-14 (1.0 beta 1) - Chloé AVRILLON - * - Fixed Pitch Bend Button - * - Fixed Syntax error at line 1625, column 1 - * - Fixed line 907 - * - Samplers management integration - * 2016-01-14 (1.0 beta 2) - Chloé AVRILLON - * - Debugging session working with Emulator Pro as a midi controller - * (moved midi.sendmessage calls to a util function - * easy to comment/uncomment - * to avoid midi messages looping over in Mixx) - * 2016-01-15 (1.0 beta 3) - Chloé AVRILLON - * - Fixed bug line 1963 - * - Pitch bend buttons and strip were not bind - * to the javascript () - *2016-02-17 (1.0 beta 4) - Stéphane Morin - * - rewrite of wheel functions (wheel move and wheel touch) - * - ensured Padmode LEDs are lit - * - added global variables for preferences - * - added print statement to aid troubleshooting (these could be removed later) - * - Broke sync LEDs... they don't light up anymore.. can someone fix this? - *2016-02-18 (1.0 beta 5) - Stéphane Morin - * - Sync LEDs fixed - *2016-02-23 (1.0 beta 6) - Stéphane Morin - * - AutoLoop fixed, including LEDs management - * - Samplers fixed, including LEDs management - * - Added Smart PFL - *2016-02-25 (1.0 beta 7) - Stéphane Morin - * - Faderstart corrected - * - Implement PADLoopButtonPressed - *2016-02-25 (1.0 beta 8) - Stéphane Morin - * - replaced a script function (script.deckFromGroup) by - * (NumarkMixtrack3.deckFromGroup) - * a portion of script.deckFromGroup is commented in the common file - * and not usable for this script sampler implementation - *2016-03-07 (1.0 ) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/905 - * - Code Clean up - * - Add Maximize Library function to TAP button - * - Added function: Sampler + Shift Key: play sample with NO Sync - * - Fixed Super Effect button - * - Fixed Sampler Shift - Sync now removed if present - *2016-03-07 (1.1 ) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/905 - * - Corrected Pitch Bend rate of wheel for smoother operation - * - Add option (noPlayOnSyncDoublePress) to disable Play on Double press of Sync button - *2016-04-08 (1.2 ) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/905 - * - Renamed user options: PADLoopButtonPressed to PADLoopButtonHold - * - Renamed user options: PADSampleButtonPressed to PADSampleButtonHold - * - TapExpandLibrary moved from Tap button to Browse Button push - * - Linked printComments to debug value of init function: The debugging parameter is set to 'true' - * if the user specified the --mididebug parameter on the command line - * - Cleaned NumarkMixtrack3.shutdown function - *2016-04-08 (1.3 ) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/905 - * - changed skin option to use boolean for - * DarkMetalSkin. It requires different code to expand library view. - * - removed trailing empty lines at end of script - * - line 1749, change .75 to 0.75 in var gammaOutputRange - * - added spacing in numerous place for easier reading - *2016-09-14 (1.3 ) - Stefan Mikolajczyk - https://github.com/mixxxdj/mixxx/pull/1012 - * - changed PADLoopButton behaviour to fit native serato behaviour (2, 4, 8, 16 instead of 1/8, 1/4, 1/2, 1) - * - * To do - (maybe..) - * ---------------- - * - Add script to control "volume","filterHigh","filterMid","filterLow" and"crossfader" - * In order for engine.softTakeover to work for these controls - * - Add configuration option: enable Samplers Sync by default (True/False) default: - * false - * - Add brake effect when pausing track with Play button - * - Add 4 deck support for script - * - Allow Beat knobs to control FX parameter; this button is Binary. - * knob has 20 notches - it sends only 1 or 127 as output. - * Note to developer: I considered hard using the beat knob to adjust parameterK - * (Deck 1: 1st parameter of effect 1; Deck 2: 2nd parameter of effect 1) for - * units 1 to 3, by selecting the target effect unit using LONG_PRESS + FX buttons - * but since all but one of the 8 effects have more than 2 parameters, - * I could not convince myself of the added value, since you still - * need to adjust effect on the GUI. + * 2016-01-12 (V0.9) to 2016-01-15 (1.0 beta 3) - Chloé AVRILLON + * 2016-02-17 (1.0 beta 4) 2016-04-08 (V1.3 )- Stéphane Morin + * 2016-04-08 (1.3) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/905 + * 2016-09-14 (1.31) - Stefan Mikolajczyk - https://github.com/mixxxdj/mixxx/pull/1012 + * 2016-04-08 (1.4) to 2016-09-26 (1.8) - Stéphane Morin - https://github.com/mixxxdj/mixxx/pull/1014 + * 2016-09-26 (2.0) - Stéphane Morin - 4 deck support + * - Added 4 deck support (Shift + Tap button = deck toggle) + * - Remove TAP LED flashing on BeatActive to prevent confusion with deck selection + * - Change Shift Lock visual indicator from TAP LED to + * Wheel Button LED. It will flash quickly on Shift lock + * with the use of LONG_PRESS (stop on release) and Single press (on/off behavior) + * - Add brake effect: PADMode + FX button 1 + * - Add spinback effect: PADMode + FX button 2 + * 2016-11-03 (2.1) - Stéphane Morin - FX Mode selection based on skin used + * 2016-12-05 (2.2) - Stéphane Morin + * - Always allow use of wheel to position song when song is not playing + * - Add configuration option for to choose if pitch bend is allowed when wheel is off * *********************************************************************** * GPL v2 licence * -------------- - * Numark Mixtrack Pro 3 controller script 1.0 beta 7 for Mixxx 2.0+ + * Numark Mixtrack Pro 3 controller script 2.1 for Mixxx 2.0+ * Copyright (C) 2016 Stéphane Morin * * This program is free software; you can redistribute it and/or @@ -187,14 +123,14 @@ var intervalsPerRev = 1200, * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -***********************************************************************/ + ***********************************************************************/ //////////////////////////////////////////////////////////////////////// // JSHint configuration // //////////////////////////////////////////////////////////////////////// /* global engine */ -/* global script */ /* global print */ /* global midi */ +/* global bpm */ //////////////////////////////////////////////////////////////////////// // Line below to remove warnings from JSHINT page regarding dot notation @@ -208,18 +144,23 @@ NumarkMixtrack3(); // Very important ! Initializes some reusable objects. NumarkMixtrack3.group = "[Master]"; NumarkMixtrack3.decknum = 0; NumarkMixtrack3.decks = []; +NumarkMixtrack3.samplers = []; // Global constants/variables -var ON = 0x7F, OFF = 0x00, DOWN = 0x7F; -var QUICK_PRESS = 1, DOUBLE_PRESS = 2, LONG_PRESS = 3; +var ON = 0x7F, + OFF = 0x00, + DOWN = 0x7F; +var QUICK_PRESS = 1, + DOUBLE_PRESS = 2, + LONG_PRESS = 3; //LEDs constants var ledCategories = { - "master": 0, - "channel1": 1, - "channel2": 2, - "meters": 32 - }; + "master": 0, + "channel1": 1, + "channel2": 2, + "meters": 32 +}; var leds = { // Master: all are first byte 0x90 ( = 0x90+ledcatecories.master ) @@ -256,15 +197,15 @@ var leds = { "PADsampler6": 0x21, "PADsampler7": 0x22, "PADsampler8": 0x23, - - // Meters: first byte 0xb0 ( = 0x90+ledcatecories.meters ) + + // Meters: first byte 0xb0 ( = 0x90+ledcatecories.meters ) "meter1": 0x02, "meter2": 0x03 }; var PADcolors = { - "black" : 0, - "blue" : 32, + "black": 0, + "blue": 32, "yellow": 96, "purple": 127 }; @@ -272,12 +213,8 @@ var PADcolors = { // Utilities // ===================================================================== -function printInfo(string) { - if (NumarkMixtrack3.debug) print(string); -} - function pauseScript(ms) { - if (ms>0) { + if (ms > 0) { var startDate = new Date(); var currentDate = null; while (currentDate - startDate < ms) { @@ -294,12 +231,12 @@ Math.sign = Math.sign || function(x) { return x > 0 ? 1 : -1; }; -function toggleValue(group,key) { - engine.setValue(group,key,!engine.getValue(group,key)); +function toggleValue(group, key) { + engine.setValue(group, key, !engine.getValue(group, key)); } function TrackIsLoaded(group) { - return (engine.getValue(group, "track_samples") > 0) ? true : false; + return (engine.getValue(group, "track_samples") > 0) ? true : false; } function RealDuration(group) { @@ -310,27 +247,42 @@ function RealDuration(group) { // this is an integer : var d1 = engine.getValue(group, "duration"); //this is a real value : - var d2 = engine.getValue(group, "track_samples") / engine.getValue(group, "track_samplerate"); + var d2 = engine.getValue(group, "track_samples") / engine.getValue( + group, "track_samplerate"); - if (d1===d2) { + if (d1 === d2) { //it is mono return d2; } else { - if ( (d1 > Math.floor(d2)) && (d1 < Math.ceil(d2)) ) { + if ((d1 > Math.floor(d2)) && (d1 < Math.ceil(d2))) { //It is mono return d2; - } else { + } else { //It is stereo - return d2/2; + return d2 / 2; } } } } -function sendShortMsg(control,midino,value) { +function sendShortMsg(control, midino, value) { midi.sendShortMsg(control, midino, value); } +function parameterSoftTakeOver(group, control, value) { + var threshold = 0.07; //on the CMD Studio 4a this threshold got the right balance + //between smooth takeover and keeping up with quick turns, but you can adjust the value to suit your needs + var currentKnobVal = value / 127; + var currentParamVal = engine.getParameter(group, control); + var spread = Math.abs(currentParamVal - currentKnobVal); + + if (spread < threshold) { + engine.setParameter(group, control, currentKnobVal); //set the new value + } else { + return; //do nothing until we get close + } +} + // ===================================================================== // Reusable Objects (special buttons handling, LEDs, iCUT and Jog wheels) // ===================================================================== @@ -346,10 +298,10 @@ var LED = function(control, midino) { this.flashDuration = 0; this.flashOnceDuration = 0; this.num_ms_on = 0; - this.valueon = 0; - this.num_ms_off = 0; - this.flashCount = 0; - this.relight = 0; + this.valueon = 0; + this.num_ms_off = 0; + this.flashCount = 0; + this.relight = 0; this.valueoff = 0; }; @@ -373,7 +325,7 @@ LED.prototype.onOff = function(value) { this.flashOnceTimer = 0; this.flashOnceDuration = 0; } - + sendShortMsg(this.control, this.midino, value); pauseScript(scriptpause); this.lit = value; @@ -392,21 +344,22 @@ LED.prototype.onOff = function(value) { // if not set, it considers it as a switch off (default=false) // valueoff : like "value". That permits for instance with two colors (once red(on), once blue(off), once red(on), etc...) -LED.prototype.flashOn = function(num_ms_on, value, num_ms_off, flashCount, relight, valueoff) { +LED.prototype.flashOn = function(num_ms_on, value, num_ms_off, flashCount, + relight, valueoff) { var myself = this; - + // stop pending timers this.flashOff(); // init this.flashDuration = num_ms_on; this.num_ms_on = num_ms_on; - this.valueon = value; - this.num_ms_off = num_ms_off; - this.flashCount = flashCount; - this.relight = relight; + this.valueon = value; + this.num_ms_off = num_ms_off; + this.flashCount = flashCount; + this.relight = relight; this.valueoff = valueoff; - + // 1st flash // This is because the permanent timer below takes // num_ms_on milisecs before first flash. @@ -417,25 +370,31 @@ LED.prototype.flashOn = function(num_ms_on, value, num_ms_off, flashCount, relig // flashcount>0 , means temporary flash, first flash already done, // so we don't need this part if flashcount=1 // permanent timer - - this.flashTimer = engine.beginTimer( num_ms_on + num_ms_off, function() { myself.flashOnceOn(false); } ); + + this.flashTimer = engine.beginTimer(num_ms_on + num_ms_off, + function() { + myself.flashOnceOn(false); + }); } if (flashCount > 1) { // flashcount>0 , means temporary flash, first flash already done, // so we don't need this part if flashcount=1 // temporary timer. The end of this timer stops the permanent flashing - - this.flashTimer2 = engine.beginTimer(flashCount * (num_ms_on + num_ms_off) - num_ms_off, function() { myself.Stopflash(relight); }, true); + + this.flashTimer2 = engine.beginTimer(flashCount * (num_ms_on + + num_ms_off) - num_ms_off, function() { + myself.Stopflash(relight); + }, true); } }; // public LED.prototype.getFlashDuration = function() { - return this.flashDuration; + return this.flashDuration; }; LED.prototype.checkOn = function() { - return this.lit; + return this.lit; }; // private : relight=true : restore light state before it was flashing @@ -479,8 +438,11 @@ LED.prototype.flashOnceOn = function(relight) { var myself = this; sendShortMsg(this.control, this.midino, this.valueon); pauseScript(scriptpause); - this.flashOnceDuration = this.num_ms_on; - this.flashOnceTimer = engine.beginTimer(this.num_ms_on - scriptpause, function() { myself.flashOnceOff(relight); }, true); + this.flashOnceDuration = this.num_ms_on; + this.flashOnceTimer = engine.beginTimer(this.num_ms_on - scriptpause, + function() { + myself.flashOnceOff(relight); + }, true); }; // private :call back function (called in flashOnceOn() ) @@ -497,7 +459,7 @@ LED.prototype.flashOnceOff = function(relight) { this.lit = OFF; } }; - + // ********* special buttons handlers (SHIFT ,LOAD, PFL and SYNC buttons) // ======================= SingleDoubleBtn // Callback : Callback function you have to provide (see end of @@ -516,7 +478,7 @@ LED.prototype.flashOnceOff = function(relight) { // but as a new press cycle event (default = 400ms). var SingleDoubleBtn = function(Callback, DoublePressTimeOut) { this.channel = 0; - this.control = 0; + this.control = 0; this.value = 0; this.status = 0; this.group = ""; @@ -532,18 +494,21 @@ var SingleDoubleBtn = function(Callback, DoublePressTimeOut) { }; // Button pressed -SingleDoubleBtn.prototype.ButtonDown = function(channel, control, value, status, group) { +SingleDoubleBtn.prototype.ButtonDown = function(channel, control, value, + status, group) { var myself = this; this.channel = channel; - this.control = control; + this.control = control; this.value = value; this.status = status; this.group = group; if (this.ButtonTimer === 0) { // first press - + this.ButtonTimer = engine.beginTimer(this.DoublePressTimeOut, - function() { myself.ButtonDecide(); }, true); + function() { + myself.ButtonDecide(); + }, true); this.ButtonCount = 1; } else { // 2nd press (before timer's out) engine.stopTimer(this.ButtonTimer); @@ -556,7 +521,8 @@ SingleDoubleBtn.prototype.ButtonDown = function(channel, control, value, status, // Take action SingleDoubleBtn.prototype.ButtonDecide = function() { this.ButtonTimer = 0; - this.Callback(this.channel, this.control, this.value, this.status, this.group, this.ButtonCount); + this.Callback(this.channel, this.control, this.value, this.status, this + .group, this.ButtonCount); this.ButtonCount = 0; }; @@ -579,7 +545,7 @@ SingleDoubleBtn.prototype.ButtonDecide = function() { var LongShortBtn = function(Callback, LongPressThreshold, CallBackOKLongPress) { this.Callback = Callback; this.channel = 0; - this.control = 0; + this.control = 0; this.value = 0; this.status = 0; this.group = ""; @@ -604,19 +570,24 @@ LongShortBtn.prototype.ButtonAssertLongPress = function() { // Make sure the callback is a function​ and exist if (typeof callback === "function") { // Call it, since we have confirmed it is callable​ - this.CallBackOKLongPress(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS); + this.CallBackOKLongPress(this.channel, this.control, this.value, + this.status, this.group, LONG_PRESS); } }; -LongShortBtn.prototype.ButtonDown = function(channel, control, value, status, group) { +LongShortBtn.prototype.ButtonDown = function(channel, control, value, status, + group) { var myself = this; this.channel = channel; - this.control = control; + this.control = control; this.value = value; this.status = status; this.group = group; this.ButtonLongPress = false; - this.ButtonLongPressTimer = engine.beginTimer(this.LongPressThreshold, function() { myself.ButtonAssertLongPress(); }, true); + this.ButtonLongPressTimer = engine.beginTimer(this.LongPressThreshold, + function() { + myself.ButtonAssertLongPress(); + }, true); }; LongShortBtn.prototype.ButtonUp = function() { @@ -625,9 +596,11 @@ LongShortBtn.prototype.ButtonUp = function() { this.ButtonLongPressTimer = 0; } if (this.ButtonLongPress) { - this.Callback(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS); + this.Callback(this.channel, this.control, this.value, this.status, + this.group, LONG_PRESS); } else { - this.Callback(this.channel, this.control, this.value, this.status, this.group, QUICK_PRESS); + this.Callback(this.channel, this.control, this.value, this.status, + this.group, QUICK_PRESS); } }; @@ -649,10 +622,11 @@ LongShortBtn.prototype.ButtonUp = function() { // button will not be considered as a potential double // but as a new press cycle event (default = 400ms). -var LongShortDoubleBtn = function(Callback, LongPressThreshold, DoublePressTimeOut) { +var LongShortDoubleBtn = function(Callback, LongPressThreshold, + DoublePressTimeOut) { this.Callback = Callback; this.channel = 0; - this.control = 0; + this.control = 0; this.value = 0; this.status = 0; this.group = ""; @@ -701,14 +675,15 @@ LongShortDoubleBtn.prototype.ButtonAssert1Press = function() { }; // Button pressed (function called by mapper's code) -LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, status, group) { +LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, + status, group) { var myself = this; this.channel = channel; - this.control = control; + this.control = control; this.value = value; this.status = status; this.group = group; - + if (this.ButtonCount === 0) { //first press (inits) // 1st press this.ButtonCount = 1; @@ -716,12 +691,16 @@ LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, stat this.ButtonLongPress = false; this.ButtonLongPressTimer = engine.beginTimer(this.LongPressThreshold, - function() { myself.ButtonAssertLongPress(); }, - true); + function() { + myself.ButtonAssertLongPress(); + }, + true); this.ButtonTimer = engine.beginTimer(this.DoublePressTimeOut, - function() { myself.ButtonAssert1Press(); }, - true); + function() { + myself.ButtonAssert1Press(); + }, + true); } else if (this.ButtonCount === 1) { // 2nd press (before short timer's out) // stop timers... if (this.ButtonLongPressTimer !== 0) { @@ -736,7 +715,7 @@ LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, stat // "stopTimer(timer)/timer=0" if (this.ButtonTimer !== 0) { engine.stopTimer(this.ButtonTimer); - this.ButtonTimer = 0 ; + this.ButtonTimer = 0; } // 2nd press @@ -745,8 +724,8 @@ LongShortDoubleBtn.prototype.ButtonDown = function(channel, control, value, stat // ...and take action immediatly this.ButtonDecide(); } // else : - // 2nd press after short timer's out, this cannot happen, - // do nothing + // 2nd press after short timer's out, this cannot happen, + // do nothing }; // Button released (function called by mapper's code) @@ -764,7 +743,7 @@ LongShortDoubleBtn.prototype.ButtonUp = function() { this.ButtonLongPressTimer = 0; } } // else : - // longpressed is confirmed, we already took action in ButtonAssertLongPress + // longpressed is confirmed, we already took action in ButtonAssertLongPress }; // Take actions and call callback @@ -776,12 +755,15 @@ LongShortDoubleBtn.prototype.ButtonDecide = function() { this.ButtonTimer = 0; if (this.ButtonLongPress) { - this.Callback(this.channel, this.control, this.value, this.status, this.group, LONG_PRESS); + this.Callback(this.channel, this.control, this.value, this.status, + this.group, LONG_PRESS); } else { if (this.ButtonCount === 2) { - this.Callback(this.channel, this.control, this.value, this.status, this.group, DOUBLE_PRESS); + this.Callback(this.channel, this.control, this.value, this.status, + this.group, DOUBLE_PRESS); } else { // We pressed sync only once - this.Callback(this.channel, this.control, this.value, this.status, this.group, QUICK_PRESS); + this.Callback(this.channel, this.control, this.value, this.status, + this.group, QUICK_PRESS); } } // re-init @@ -791,13 +773,13 @@ LongShortDoubleBtn.prototype.ButtonDecide = function() { // ************************************************* // iCut mode management -// **** +// ************************************************* // this mode simulates a scratch routine. When the jog wheel is turned back // the crossfader closes, when the jog wheel is turned forward the crossfader // will open. -var AutoCut = function (deckNum) { - this.deckNum = deckNum; +var AutoCut = function(decknum) { + this.decknum = decknum; this.timer = 0; this.delay = 20; this.fadersave = 0; @@ -811,16 +793,16 @@ AutoCut.prototype.On = function() { } }; -AutoCut.prototype.FaderCut = function(jogValue) { +AutoCut.prototype.FaderCut = function(jogValue, decknum) { if (this.enabled) { var direction = Math.sign(jogValue); //Get Jog wheel direction // Backward=-1 (close), forward =0 (open) if (direction > 0) { direction = 0; - } - // Left Deck ? direction = 0 (open : crossfader to zéro) or 1 (close : crossfader to the right) - // Right Deck ? direction = 0 (open : crossfader to zéro) or -1 (close : crossfader to the left) - if (this.deckNum === 1) { + } + // Left Deck direction = 0 (open : crossfader to zero) or 1 (close : crossfader to the right) + // Right Deck direction = 0 (open : crossfader to zero) or -1 (close : crossfader to the left) + if (decknum === 1) { direction = -direction; } // else direction is of the good sign engine.setValue('[Master]', 'crossfader', direction); @@ -837,71 +819,26 @@ AutoCut.prototype.Off = function() { // ***************************************************************** // Jog wheel management (scratching, bending, ...) -// ****** -// Thank you to the authors of the Vestax VCI 400 mapping script -// Your controller is a "Model A" controller for scratching, -// if it centers on 0. -// See http://www.mixxx.org/wiki/doku.php/midi_scripting#scratching - -var Jogger = function (group, deckNum, model) { - this.deckNum = deckNum; +// ************************************************* + +var Jogger = function(group, decknum, model) { + this.decknum = decknum; this.group = group; this.wheelTouchInertiaTimer = 0; - this.iCUT = new AutoCut(deckNum); + this.iCUT = new AutoCut(decknum); this.model = model; }; -NumarkMixtrack3.SamplerBank = function() { - this.bankactive = 1; - this.loaded = []; - this.loaded.length = 17; -}; - -//Sample action -NumarkMixtrack3.SamplerBank.prototype.play = function(samplerindex,value) { - - var deck = NumarkMixtrack3.decks["D" + samplerindex]; - var isplaying = engine.getValue("[Sampler" + samplerindex + "]", "play"); - - if (value) { - if (!isplaying) { - if (deck.shiftKey) { - //Shift is on, play sampler with no Sync - engine.setValue("[Sampler" + samplerindex + "]", "beatsync", 0); - engine.setValue("[Sampler" + samplerindex + "]", "cue_gotoandplay", 1); - deck.LEDs["PADsampler" + samplerindex].flashOn(300, PADcolors.purple, 300); - } else { - //play sampler with Sync - engine.setValue("[Sampler" + samplerindex + "]", "cue_gotoandplay", 1); - engine.setValue("[Sampler" + samplerindex + "]", "beatsync", 1); - deck.LEDs["PADsampler" + samplerindex].flashOn(300, PADcolors.purple, 300); - } - } else { - engine.setValue("[Sampler" + samplerindex + "]", "stop", 1); - NumarkMixtrack3.decks["D"+ samplerindex].LEDs["PADsampler"+ samplerindex].onOff(ON); - } - } else { - engine.setValue("[Sampler" + samplerindex + "]", "stop", 1); - NumarkMixtrack3.decks["D"+ samplerindex].LEDs["PADsampler"+ samplerindex].onOff(ON); - } -}; - -// ****************************************************************** -// Samplers - create object -// ********* - -NumarkMixtrack3.samplers = new NumarkMixtrack3.SamplerBank(); - // ****************************************************************** // Decks -// ********* -NumarkMixtrack3.deck = function(deckNum) { - this.deckNum = deckNum; - this.group = "[Channel" + deckNum + "]"; +// ****************************************************************** +NumarkMixtrack3.deck = function(decknum) { + this.decknum = decknum; + this.group = "[Channel" + decknum + "]"; this.loaded = false; this.LoadInitiated = false; this.jogWheelsInScratchMode = false; - this.PADMode = 0; //0=Manual Loop;1=Auto Loop; 2=Sampler ??? // Needed? + this.PADMode = false; //false = not pressed; true = pressed this.shiftKey = false; this.shiftLock = false; this.touch = false; @@ -910,12 +847,29 @@ NumarkMixtrack3.deck = function(deckNum) { this.lastfadervalue = 0; this.scratchTimer = 0; this.seekingfast = false; - this.iCutStatus = false; - this.LEDs=[]; + this.iCutStatus = false; + this.LEDs = []; + this.TapDown = false; + this.InstantFX = []; + this.Jog = new Jogger(this.group, this.decknum, "A"); + this.duration = 0; // NMTP3 is a "Model A" controller for scratching, it centers on 0. // See http://www.mixxx.org/wiki/doku.php/midi_scripting#scratching // and see "Jogger" object constructor - this.Jog = new Jogger(this.group, this.deckNum, "A"); +}; + +// ****************************************************************** +// Samplers - object +// ****************************************************************** + +NumarkMixtrack3.sampler = function(decknum) { + this.decknum = decknum; + this.group = "[Sampler" + decknum + "]"; + this.loaded = false; + this.LoadInitiated = false; + this.PitchFaderHigh = 0; + this.lastfadervalue = 0; + this.LEDs = []; }; NumarkMixtrack3.deck.prototype.TrackIsLoaded = function() { @@ -923,375 +877,532 @@ NumarkMixtrack3.deck.prototype.TrackIsLoaded = function() { }; NumarkMixtrack3.deck.prototype.StripEffect = function(value, decknum) { - // var decknum = NumarkMixtrack3.deckFromGroup(group); - // var deck = NumarkMixtrack3.decks["D" + decknum]; - - if (decknum === 1) { - engine.setValue("[EffectRack1_EffectUnit1]", "super1", value/127); - engine.setValue("[EffectRack1_EffectUnit2]", "super1", value/127); - engine.setValue("[EffectRack1_EffectUnit3]", "super1", value/127); - } else { - engine.setValue("[EffectRack1_EffectUnit1]", "mix", value/127); - engine.setValue("[EffectRack1_EffectUnit2]", "mix", value/127); - engine.setValue("[EffectRack1_EffectUnit3]", "mix", value/127); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var ButtonNum; + var arrayLength = deck.InstantFX.length; + var i; + + if (FXmode === 1) { //3 FX in 4 FX Units + + if (!deck.shiftKey) { + // if deck.shiftKey is true, we are fast seeking thru the track + for (i = 0; i < arrayLength; i++) { + ButtonNum = deck.InstantFX[i]; + engine.setValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", + "enabled", true); + } + } + + engine.setValue("[EffectRack1_EffectUnit" + decknum + "]", "super1", value / 127); + + } else { // 1 FX in 3 FX unit + + if (!deck.shiftKey) { + // if deck.shiftKey is true, we are fast seeking thru the track + for (i = 0; i < arrayLength; i++) { + ButtonNum = deck.InstantFX[i]; + engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", + "group_[Channel" + decknum + "]_enable", true); + } + } + engine.setValue("[EffectRack1_EffectUnit1]", "super1", value / 127); + engine.setValue("[EffectRack1_EffectUnit2]", "super1", value / 127); + engine.setValue("[EffectRack1_EffectUnit3]", "super1", value / 127); } }; // ===================================================================== // Initialization of the mapping // ===================================================================== -// Create decks -// not completely clean... D1 and D2 are for the actual decks, D1 to D8 are for samplers. -// this will need to be fixed if someone is to enable the ability to map Deck 3 and 4 NumarkMixtrack3.decks.D1 = new NumarkMixtrack3.deck("1"); NumarkMixtrack3.decks.D2 = new NumarkMixtrack3.deck("2"); NumarkMixtrack3.decks.D3 = new NumarkMixtrack3.deck("3"); NumarkMixtrack3.decks.D4 = new NumarkMixtrack3.deck("4"); -NumarkMixtrack3.decks.D5 = new NumarkMixtrack3.deck("5"); -NumarkMixtrack3.decks.D6 = new NumarkMixtrack3.deck("6"); -NumarkMixtrack3.decks.D7 = new NumarkMixtrack3.deck("7"); -NumarkMixtrack3.decks.D8 = new NumarkMixtrack3.deck("8"); - +NumarkMixtrack3.samplers.S1 = new NumarkMixtrack3.sampler("1"); +NumarkMixtrack3.samplers.S2 = new NumarkMixtrack3.sampler("2"); +NumarkMixtrack3.samplers.S3 = new NumarkMixtrack3.sampler("3"); +NumarkMixtrack3.samplers.S4 = new NumarkMixtrack3.sampler("4"); +NumarkMixtrack3.samplers.S5 = new NumarkMixtrack3.sampler("5"); +NumarkMixtrack3.samplers.S6 = new NumarkMixtrack3.sampler("6"); +NumarkMixtrack3.samplers.S7 = new NumarkMixtrack3.sampler("7"); +NumarkMixtrack3.samplers.S8 = new NumarkMixtrack3.sampler("8"); NumarkMixtrack3.initLEDsObjects = function() { var i; // Lets create some LEDs NumarkMixtrack3.AllLeds = - new LED(0x90+ledCategories.master, leds.all); - NumarkMixtrack3.decks["D1"].LEDs.PADsampler1 = - new LED(0x91,leds.PADsampler1); - NumarkMixtrack3.decks["D2"].LEDs.PADsampler2 = - new LED(0x91,leds.PADsampler2); - NumarkMixtrack3.decks["D3"].LEDs.PADsampler3 = - new LED(0x91,leds.PADsampler3); - NumarkMixtrack3.decks["D4"].LEDs.PADsampler4 = - new LED(0x91,leds.PADsampler4); - NumarkMixtrack3.decks["D5"].LEDs.PADsampler5 = - new LED(0x92,leds.PADsampler5); - NumarkMixtrack3.decks["D6"].LEDs.PADsampler6 = - new LED(0x92,leds.PADsampler6); - NumarkMixtrack3.decks["D7"].LEDs.PADsampler7 = - new LED(0x92,leds.PADsampler7); - NumarkMixtrack3.decks["D8"].LEDs.PADsampler8= - new LED(0x92,leds.PADsampler8); - - - for (i=1;i<=2;i++) { - NumarkMixtrack3.decks["D"+i].LEDs.headphones = - new LED(0x90+ledCategories.master,leds.headphones1-1+i); - NumarkMixtrack3.decks["D"+i].LEDs.jogWheelsInScratchMode = - new LED(0x90+i,leds.jogWheelsInScratchMode); - NumarkMixtrack3.decks["D"+i].LEDs.loopin = - new LED(0x90+i,leds.loopin); - NumarkMixtrack3.decks["D"+i].LEDs.loopout = - new LED(0x90+i,leds.loopout); - NumarkMixtrack3.decks["D"+i].LEDs.reloop_exit = - new LED(0x90+i,leds.reloop_exit); - NumarkMixtrack3.decks["D"+i].LEDs.loop_halve = - new LED(0x90+i,leds.loop_halve); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue1 = - new LED(0x90+i,leds.hotCue1); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue2 = - new LED(0x90+i,leds.hotCue2); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue3 = - new LED(0x90+i,leds.hotCue3); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue4 = - new LED(0x90+i,leds.hotCue4); - NumarkMixtrack3.decks["D"+i].LEDs.Cue = - new LED(0x90+i,leds.Cue); - NumarkMixtrack3.decks["D"+i].LEDs.sync = - new LED(0x90+i,leds.sync); - NumarkMixtrack3.decks["D"+i].LEDs.play = - new LED(0x90+i,leds.play); - NumarkMixtrack3.decks["D"+i].LEDs.fx1 = - new LED(0x90+i,leds.fx1); - NumarkMixtrack3.decks["D"+i].LEDs.fx2 = - new LED(0x90+i,leds.fx2); - NumarkMixtrack3.decks["D"+i].LEDs.fx3 = - new LED(0x90+i,leds.fx3); - NumarkMixtrack3.decks["D"+i].LEDs.tap = - new LED(0x90+i,leds.tap); - NumarkMixtrack3.decks["D"+i].LEDs.PADloop1 = - new LED(0x90+i,leds.PADloop1); - NumarkMixtrack3.decks["D"+i].LEDs.PADloop2 = - new LED(0x90+i,leds.PADloop2); - NumarkMixtrack3.decks["D"+i].LEDs.PADloop3 = - new LED(0x90+i,leds.PADloop3); - NumarkMixtrack3.decks["D"+i].LEDs.PADloop4 = - new LED(0x90+i,leds.PADloop4); - - NumarkMixtrack3.decks["D"+i].LEDs.meter = - new LED(0x90+ledCategories.meters,leds.meter1-1+i); + new LED(0x90 + ledCategories.master, leds.all); + NumarkMixtrack3.samplers["S1"].LEDs.PADsampler1 = + new LED(0x91, leds.PADsampler1); + NumarkMixtrack3.samplers["S2"].LEDs.PADsampler2 = + new LED(0x91, leds.PADsampler2); + NumarkMixtrack3.samplers["S3"].LEDs.PADsampler3 = + new LED(0x91, leds.PADsampler3); + NumarkMixtrack3.samplers["S4"].LEDs.PADsampler4 = + new LED(0x91, leds.PADsampler4); + NumarkMixtrack3.samplers["S5"].LEDs.PADsampler5 = + new LED(0x92, leds.PADsampler5); + NumarkMixtrack3.samplers["S6"].LEDs.PADsampler6 = + new LED(0x92, leds.PADsampler6); + NumarkMixtrack3.samplers["S7"].LEDs.PADsampler7 = + new LED(0x92, leds.PADsampler7); + NumarkMixtrack3.samplers["S8"].LEDs.PADsampler8 = + new LED(0x92, leds.PADsampler8); + + for (i = 1; i <= 2; i++) { + NumarkMixtrack3.decks["D" + i].LEDs.headphones = + new LED(0x90 + ledCategories.master, leds.headphones1 - 1 + i); + NumarkMixtrack3.decks["D" + i].LEDs.jogWheelsInScratchMode = + new LED(0x90 + i, leds.jogWheelsInScratchMode); + NumarkMixtrack3.decks["D" + i].LEDs.loopin = + new LED(0x90 + i, leds.loopin); + NumarkMixtrack3.decks["D" + i].LEDs.loopout = + new LED(0x90 + i, leds.loopout); + NumarkMixtrack3.decks["D" + i].LEDs.reloop_exit = + new LED(0x90 + i, leds.reloop_exit); + NumarkMixtrack3.decks["D" + i].LEDs.loop_halve = + new LED(0x90 + i, leds.loop_halve); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue1 = + new LED(0x90 + i, leds.hotCue1); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue2 = + new LED(0x90 + i, leds.hotCue2); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue3 = + new LED(0x90 + i, leds.hotCue3); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue4 = + new LED(0x90 + i, leds.hotCue4); + NumarkMixtrack3.decks["D" + i].LEDs.Cue = + new LED(0x90 + i, leds.Cue); + NumarkMixtrack3.decks["D" + i].LEDs.sync = + new LED(0x90 + i, leds.sync); + NumarkMixtrack3.decks["D" + i].LEDs.play = + new LED(0x90 + i, leds.play); + NumarkMixtrack3.decks["D" + i].LEDs.fx1 = + new LED(0x90 + i, leds.fx1); + NumarkMixtrack3.decks["D" + i].LEDs.fx2 = + new LED(0x90 + i, leds.fx2); + NumarkMixtrack3.decks["D" + i].LEDs.fx3 = + new LED(0x90 + i, leds.fx3); + NumarkMixtrack3.decks["D" + i].LEDs.tap = + new LED(0x90 + i, leds.tap); + NumarkMixtrack3.decks["D" + i].LEDs.PADloop1 = + new LED(0x90 + i, leds.PADloop1); + NumarkMixtrack3.decks["D" + i].LEDs.PADloop2 = + new LED(0x90 + i, leds.PADloop2); + NumarkMixtrack3.decks["D" + i].LEDs.PADloop3 = + new LED(0x90 + i, leds.PADloop3); + NumarkMixtrack3.decks["D" + i].LEDs.PADloop4 = + new LED(0x90 + i, leds.PADloop4); + NumarkMixtrack3.decks["D" + i].LEDs.meter = + new LED(0x90 + ledCategories.meters, leds.meter1 - 1 + i); + } + // LEDs for Deck 3 and 4 + for (i = 1; i <= 2; i++) { + + var j = i + 2; + NumarkMixtrack3.decks["D" + j].LEDs.headphones = + new LED(0x90 + ledCategories.master, leds.headphones1 - 1 + i); + NumarkMixtrack3.decks["D" + j].LEDs.jogWheelsInScratchMode = + new LED(0x90 + i, leds.jogWheelsInScratchMode); + NumarkMixtrack3.decks["D" + j].LEDs.loopin = + new LED(0x90 + i, leds.loopin); + NumarkMixtrack3.decks["D" + j].LEDs.loopout = + new LED(0x90 + i, leds.loopout); + NumarkMixtrack3.decks["D" + j].LEDs.reloop_exit = + new LED(0x90 + i, leds.reloop_exit); + NumarkMixtrack3.decks["D" + j].LEDs.loop_halve = + new LED(0x90 + i, leds.loop_halve); + NumarkMixtrack3.decks["D" + j].LEDs.hotCue1 = + new LED(0x90 + i, leds.hotCue1); + NumarkMixtrack3.decks["D" + j].LEDs.hotCue2 = + new LED(0x90 + i, leds.hotCue2); + NumarkMixtrack3.decks["D" + j].LEDs.hotCue3 = + new LED(0x90 + i, leds.hotCue3); + NumarkMixtrack3.decks["D" + j].LEDs.hotCue4 = + new LED(0x90 + i, leds.hotCue4); + NumarkMixtrack3.decks["D" + j].LEDs.Cue = + new LED(0x90 + i, leds.Cue); + NumarkMixtrack3.decks["D" + j].LEDs.sync = + new LED(0x90 + i, leds.sync); + NumarkMixtrack3.decks["D" + j].LEDs.play = + new LED(0x90 + i, leds.play); + NumarkMixtrack3.decks["D" + j].LEDs.fx1 = + new LED(0x90 + i, leds.fx1); + NumarkMixtrack3.decks["D" + j].LEDs.fx2 = + new LED(0x90 + i, leds.fx2); + NumarkMixtrack3.decks["D" + j].LEDs.fx3 = + new LED(0x90 + i, leds.fx3); + NumarkMixtrack3.decks["D" + j].LEDs.tap = + new LED(0x90 + i, leds.tap); + NumarkMixtrack3.decks["D" + j].LEDs.PADloop1 = + new LED(0x90 + i, leds.PADloop1); + NumarkMixtrack3.decks["D" + j].LEDs.PADloop2 = + new LED(0x90 + i, leds.PADloop2); + NumarkMixtrack3.decks["D" + j].LEDs.PADloop3 = + new LED(0x90 + i, leds.PADloop3); + NumarkMixtrack3.decks["D" + j].LEDs.PADloop4 = + new LED(0x90 + i, leds.PADloop4); + NumarkMixtrack3.decks["D" + j].LEDs.meter = + new LED(0x90 + ledCategories.meters, leds.meter1 - 1 + i); } }; NumarkMixtrack3.initButtonsObjects = function() { var i; - for (i=1;i<=2;i++) { - NumarkMixtrack3.decks["D"+i].LoadButtonControl = + + for (i = 1; i <= 4; i++) { + NumarkMixtrack3.decks["D" + i].LoadButtonControl = new LongShortBtn(NumarkMixtrack3.OnLoadButton); - NumarkMixtrack3.decks["D"+i].SyncButtonControl = + NumarkMixtrack3.decks["D" + i].SyncButtonControl = new LongShortDoubleBtn(NumarkMixtrack3.OnSyncButton); - NumarkMixtrack3.decks["D"+i].ShiftButtonControl = - new SingleDoubleBtn(NumarkMixtrack3.OnShiftButton); - NumarkMixtrack3.decks["D"+i].ShiftedPFLButtonControl = + NumarkMixtrack3.decks["D" + i].ShiftedPFLButtonControl = new SingleDoubleBtn(NumarkMixtrack3.OnShiftedPFLButton); + NumarkMixtrack3.decks["D" + i].PADLoopButtonHold = + new LongShortBtn(NumarkMixtrack3.onPADLoopButtonHold); + } + for (i = 1; i <= 8; i++) { + NumarkMixtrack3.samplers["S" + i].PADSampleButtonHold = + new LongShortBtn(NumarkMixtrack3.onPADSampleButtonHold); } }; -// Called when the MIDI device is opened & set up -NumarkMixtrack3.init = function(id,debug) { +NumarkMixtrack3.init = function(id, debug) { + // Set up the controller to manipulate decks 1 & 2 when this script is loaded + print("********* Initialisation process engaged *****************"); - print(" Mapping initialization"); - print("============================"); + print(" Mapping initialization"); + print(""); + + print("=========================================================="); + print(" Initialize variables"); + print(""); - var i,j,k; + NumarkMixtrack3.libraryMode = false; NumarkMixtrack3.id = id; // Store the ID of this device for later use NumarkMixtrack3.debug = debug; - //print comments on prompt screen in order to facilitate debugging - print (" Debug and printComments setting: " + NumarkMixtrack3.debug); + NumarkMixtrack3.deckGroup = { + '[Channel1]': '[Channel1]', + '[Channel2]': '[Channel2]', + '[Channel3]': '[Channel3]', + '[Channel4]': '[Channel4]' + }; - NumarkMixtrack3.libraryMode = false; + NumarkMixtrack3.fxControls = { // used to determine FX Button + '[EffectRack1_EffectUnit1_Effect1]': 1, + '[EffectRack1_EffectUnit1_Effect2]': 2, + '[EffectRack1_EffectUnit1_Effect3]': 3, + '[EffectRack1_EffectUnit2_Effect1]': 1, + '[EffectRack1_EffectUnit2_Effect2]': 2, + '[EffectRack1_EffectUnit2_Effect3]': 3, + '[EffectRack1_EffectUnit3_Effect1]': 1, + '[EffectRack1_EffectUnit3_Effect2]': 2, + '[EffectRack1_EffectUnit3_Effect3]': 3, + '[EffectRack1_EffectUnit4_Effect1]': 1, + '[EffectRack1_EffectUnit4_Effect2]': 2, + '[EffectRack1_EffectUnit4_Effect3]': 3, + '[EffectRack1_EffectUnit1]': 1, //FXmode !== 1 + '[EffectRack1_EffectUnit2]': 2, //FXmode !== 1 + '[EffectRack1_EffectUnit3]': 3, //FXmode !== 1 + '[EffectRack1_EffectUnit4]': 4 //FXmode !== 1 + }; + + NumarkMixtrack3.fxGroups = { //Used to determine deck + '[EffectRack1_EffectUnit1_Effect1]': 1, + '[EffectRack1_EffectUnit1_Effect2]': 1, + '[EffectRack1_EffectUnit1_Effect3]': 1, + '[EffectRack1_EffectUnit2_Effect1]': 2, + '[EffectRack1_EffectUnit2_Effect2]': 2, + '[EffectRack1_EffectUnit2_Effect3]': 2, + '[EffectRack1_EffectUnit3_Effect1]': 3, + '[EffectRack1_EffectUnit3_Effect2]': 3, + '[EffectRack1_EffectUnit3_Effect3]': 3, + '[EffectRack1_EffectUnit4_Effect1]': 4, + '[EffectRack1_EffectUnit4_Effect2]': 4, + '[EffectRack1_EffectUnit4_Effect3]': 4, + 'group_[Channel1]_enable': 1, //FXmode !== 1 + 'group_[Channel2]_enable': 2, //FXmode !== 1 + 'group_[Channel3]_enable': 3, //FXmode !== 1 + 'group_[Channel4]_enable': 4 //FXmode !== 1 + }; + + NumarkMixtrack3.Autoloop = { + 'beatloop_2_enabled': 1, + 'beatloop_4_enabled': 2, + 'beatloop_8_enabled': 3, + 'beatloop_16_enabled': 4, + 'beatloop_0.125_enabled': 1, + 'beatloop_0.25_enabled': 2, + 'beatloop_0.5_enabled': 3, + 'beatloop_1_enabled': 4 + }; + + var i, j, k; + + print("=========================================================="); + print(" Initialize LEDs"); + print(""); - print(" Init LEDs"); + // Create LEDs Objects NumarkMixtrack3.initLEDsObjects(); - print(" Init Buttons"); - NumarkMixtrack3.initButtonsObjects(); // Turn ON all the lights: the only way PADMode Leds light up NumarkMixtrack3.AllLeds.onOff(ON); + // Initialise some others (PAD LEDs) - for (i=1;i<=2;i++) { - for (j=1;j<=4;j++) { - NumarkMixtrack3.decks["D"+i].LEDs["PADloop"+j].onOff(PADcolors.black); - } - for (k=1;k<=8;k++) { - NumarkMixtrack3.decks["D"+k].LEDs["PADsampler"+k].onOff(PADcolors.black); - } - NumarkMixtrack3.decks["D"+i].LEDs.jogWheelsInScratchMode.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.headphones.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.loopin.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.loopout.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.reloop_exit.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.loop_halve.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue1.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue2.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue3.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.hotCue4.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.Cue.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.sync.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.play.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.fx1.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.fx2.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.fx3.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.tap.onOff(OFF); - NumarkMixtrack3.decks["D"+i].LEDs.meter.onOff(OFF); - - print(" set LEDs state "+"D"+i); + for (k = 1; k <= 8; k++) { + NumarkMixtrack3.samplers["S" + k].LEDs["PADsampler" + k].onOff( + PADcolors.black); } - - print(" Init Soft Takeovers"); - // Enable soft-takeover for Pitch slider - engine.softTakeover("[Channel1]", "rate", true); - engine.softTakeover("[Channel2]", "rate", true); - + + for (i = 1; i <= 4; i++) { + for (j = 1; j <= 4; j++) { + NumarkMixtrack3.decks["D" + i].LEDs["PADloop" + j].onOff( + PADcolors.black); + } + + NumarkMixtrack3.decks["D" + i].LEDs.jogWheelsInScratchMode.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.headphones.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.loopin.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.loopout.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.reloop_exit.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.loop_halve.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue1.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue2.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue3.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.hotCue4.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.Cue.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.sync.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.play.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.fx1.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.fx2.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.fx3.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.tap.onOff(OFF); + NumarkMixtrack3.decks["D" + i].LEDs.meter.onOff(OFF); + + print(" LEDs state set for deck " + "D" + i); + } + + print("=========================================================="); + print(" Initialize Buttons"); + print(""); + NumarkMixtrack3.initButtonsObjects(); + + print("=========================================================="); + print(" Init Soft Takeovers"); + print(""); + // Set soft-takeover for all Sampler volumes for (i = engine.getValue("[Master]", "num_samplers"); i >= 1; i--) { engine.softTakeover("[Sampler" + i + "]", "pregain", true); } - // Set soft-takeover for all applicable Deck controls - // the following controls are mapped in the XML file, not by script - // therefore this is not required - - /* + for (i = engine.getValue("[Master]", "num_decks"); i >= 1; i--) { - engine.softTakeover("[Channel" + i + "]", "volume", true); - engine.softTakeover("[Channel" + i + "]", "filterHigh", true); - engine.softTakeover("[Channel" + i + "]", "filterMid", true); - engine.softTakeover("[Channel" + i + "]", "filterLow", true); - } + engine.softTakeover("[Channel" + i + "]", "rate", true); // Enable soft-takeover for Pitch slider + engine.softTakeover("[Channel" + i + "]", "volume", true); // Enable soft-takeover for volume + engine.setParameter("[Channel" + i + "]", "volume", 0); // Set volume to zero for each deck (initial load only) + } - engine.softTakeover("[Master]", "crossfader", true); - */ - for (i = 1; i <= 4; i++) { - engine.softTakeover("[EffectRack1_EffectUnit" + i + "]", "super1", true); + for (i = 1; i <= 8; i++) { + engine.connectControl("[Sampler" + i + "]", "play", + "NumarkMixtrack3.OnSamplePlayStop"); } - - for (i = 1; i <= 4; i++) { - engine.softTakeover("[EffectRack1_EffectUnit" + i + "]", "mix", true); + + NumarkMixtrack3.initDeck('[Channel1]', false); //Initial load, "remove" is set to false + NumarkMixtrack3.initDeck('[Channel2]', false); + + print("********* Controller is ready *******************"); + print("********* End of Initialisation process *******************"); +}; + +NumarkMixtrack3.initDeck = function(group, remove) { + var disconnectDeck = parseInt(NumarkMixtrack3.channelRegEx.exec(group)[1]); + var connectedLED = disconnectDeck; + if (disconnectDeck <= 2) { + disconnectDeck += 2; + } else { + disconnectDeck -= 2; } - - print(" Init Connect controls"); - // Add event listeners - engine.connectControl("[Channel1]", "hotcue_1_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 1); - }); - engine.connectControl("[Channel2]", "hotcue_1_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 1); - }); - engine.connectControl("[Channel1]", "hotcue_2_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 2); - }); - engine.connectControl("[Channel2]", "hotcue_2_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 2); - }); - engine.connectControl("[Channel1]", "hotcue_3_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 3); - }); - engine.connectControl("[Channel2]", "hotcue_3_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 3); - }); - engine.connectControl("[Channel1]", "hotcue_4_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 4); - }); - engine.connectControl("[Channel2]", "hotcue_4_enabled", function(value, group, control) { - NumarkMixtrack3.OnHotcueChange(value, group, control, 4); - }); - - // The track_samples control is being used to tell if a track has successfully loaded - engine.connectControl("[Channel1]", "track_samples", "NumarkMixtrack3.OnTrackLoaded"); - engine.connectControl("[Channel2]", "track_samples", "NumarkMixtrack3.OnTrackLoaded"); - // VU Meters - engine.connectControl("[Channel1]", "VuMeter", "NumarkMixtrack3.OnVuMeterChange"); - engine.connectControl("[Channel2]", "VuMeter", "NumarkMixtrack3.OnVuMeterChange"); - - //other lights - engine.connectControl("[Channel1]", "playposition", "NumarkMixtrack3.OnPlaypositionChange"); - engine.connectControl("[Channel2]", "playposition", "NumarkMixtrack3.OnPlaypositionChange"); - engine.connectControl("[Channel1]", "volume", "NumarkMixtrack3.OnVolumeChange"); - engine.connectControl("[Channel2]", "volume", "NumarkMixtrack3.OnVolumeChange"); - engine.connectControl("[Channel1]", "pfl", "NumarkMixtrack3.OnPFLStatusChange"); - engine.connectControl("[Channel2]", "pfl", "NumarkMixtrack3.OnPFLStatusChange"); - engine.connectControl("[Channel1]", "play_indicator", "NumarkMixtrack3.OnPlayIndicatorChange"); - engine.connectControl("[Channel2]", "play_indicator", "NumarkMixtrack3.OnPlayIndicatorChange"); - engine.connectControl("[Channel1]", "beat_active", "NumarkMixtrack3.OnBeatActive"); - engine.connectControl("[Channel2]", "beat_active", "NumarkMixtrack3.OnBeatActive"); - engine.connectControl("[Channel1]", "cue_indicator", "NumarkMixtrack3.OnCuePointChange"); - engine.connectControl("[Channel2]", "cue_indicator", "NumarkMixtrack3.OnCuePointChange"); - engine.connectControl("[Channel1]", "loop_start_position", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel2]", "loop_start_position", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel1]", "loop_end_position", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel2]", "loop_end_position", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel1]", "loop_enabled", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel2]", "loop_enabled", "NumarkMixtrack3.OnLoopInOutChange"); - engine.connectControl("[Channel1]", "sync_enabled", "NumarkMixtrack3.OnSyncButtonChange"); - engine.connectControl("[Channel2]", "sync_enabled", "NumarkMixtrack3.OnSyncButtonChange"); - - var loopsize = [0.125, 0.25, 0.5, 1, 2, 4, 8, 16]; - var l; - for (l=0;l Open/Close selected side bar item engine.setValue(group, "ToggleSelectedSidebarItem", true); } else { // Browse push : maximize/minimize library view if (value === ON) { - - NumarkMixtrack3.libraryMode = !NumarkMixtrack3.libraryMode; - if (maxview) { - engine.setValue(LibraryGroup,LibraryCommand,expand); - - } else { - engine.setValue(LibraryGroup,LibraryCommand,contract); - - } - } - } -}; -NumarkMixtrack3.PadModeButton = function(channel, control, value, status, group) { - var decknum = NumarkMixtrack3.deckFromGroup(group); - var deck = NumarkMixtrack3.decks["D" + decknum]; - var loopsize = [0.125, 0.25, 0.5, 1, 2, 4, 8, 16]; - var i; + NumarkMixtrack3.libraryMode = !NumarkMixtrack3.libraryMode; + if (maxview) { + engine.setValue(LibraryGroup, LibraryCommand, expand); -NumarkMixtrack3.PadModeButton = !NumarkMixtrack3.PadModeButton; - - if (value === DOWN) { - //ensure all LEDs are ON (default) - if (decknum === 1) { - NumarkMixtrack3.decks["D1"].LEDs["PADsampler1"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D2"].LEDs["PADsampler2"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D3"].LEDs["PADsampler3"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D4"].LEDs["PADsampler4"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D1"].LEDs["PADloop1"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D1"].LEDs["PADloop2"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D1"].LEDs["PADloop3"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D1"].LEDs["PADloop4"].onOff(PADcolors.yellow); - } - - if (decknum === 2) { - NumarkMixtrack3.decks["D5"].LEDs["PADsampler5"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D6"].LEDs["PADsampler6"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D7"].LEDs["PADsampler7"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D8"].LEDs["PADsampler8"].onOff(PADcolors.purple); - NumarkMixtrack3.decks["D2"].LEDs["PADloop1"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D2"].LEDs["PADloop2"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D2"].LEDs["PADloop3"].onOff(PADcolors.yellow); - NumarkMixtrack3.decks["D2"].LEDs["PADloop4"].onOff(PADcolors.yellow); - } - } - - // Now check which one should be blinking - // Need to check if loop is enabled; if yes, stop it , else start it - //Autoloop - if (value === DOWN) { - for (i=0;i4) { - index = index - 4; + } else { + engine.setValue(LibraryGroup, LibraryCommand, contract); } - - if (engine.getValue(group, "beatloop_" + loopsize[i] + "_enabled")) { - deck.LEDs["PADloop" + index].flashOn(300, PADcolors.yellow, 300); - } } - - //Sampler - for (i = 1; i <= 8; i++) { - engine.trigger("[Sampler" + i + "]", "play"); - } - } - + } }; NumarkMixtrack3.BrowseKnob = function(channel, control, value, status, group) { var i; - var shifted = NumarkMixtrack3.decks.D1.shiftKey || NumarkMixtrack3.decks.D1.shiftKey; + var shifted = (NumarkMixtrack3.decks.D1.shiftKey || NumarkMixtrack3.decks + .D2.shiftKey || NumarkMixtrack3.decks.D3.shiftKey || NumarkMixtrack3.decks.D4.shiftKey); // value = 1 / 2 / 3 ... for positive //value = 1 / 2 / 3 - var nval = (value>0x40 ? value-0x80 : value); + var nval = (value > 0x40 ? value - 0x80 : value); if (shifted) { // SHIFT+Turn BROWSE Knob : directory mode --> select Play List/Side bar item @@ -1450,6 +1507,50 @@ NumarkMixtrack3.BrowseKnob = function(channel, control, value, status, group) { } }; +NumarkMixtrack3.PadModeButton = function(channel, control, value, status, + group) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var i; + deck.PADMode = false; + + if (value === DOWN) { + deck.PADMode = true; + //ensure all LEDs are ON (default) + for (i = 1; i <= 8; i++) { + NumarkMixtrack3.samplers["S" + i + ""].LEDs["PADsampler" + i + ""].onOff(PADcolors + .purple); + } + NumarkMixtrack3.decks["D" + decknum].LEDs["PADloop1"].onOff(PADcolors.yellow); + NumarkMixtrack3.decks["D" + decknum].LEDs["PADloop2"].onOff(PADcolors.yellow); + NumarkMixtrack3.decks["D" + decknum].LEDs["PADloop3"].onOff(PADcolors.yellow); + NumarkMixtrack3.decks["D" + decknum].LEDs["PADloop4"].onOff(PADcolors.yellow); + } + + // Now check which one should be blinking + // Need to check if loop is enabled; if yes, stop it , else start it + //Autoloop + if (value === DOWN) { + for (i = 0; i < loopsize.length; i++) { + var index = i + 1; + if (index > 4) { + index = index - 4; + } + + if (engine.getValue("[Channel" + decknum + "]", "beatloop_" + loopsize[i] + + "_enabled")) { + deck.LEDs["PADloop" + index].flashOn(300, PADcolors.yellow, + 300); + } + } + + //Sampler + for (i = 1; i <= 8; i++) { + engine.trigger("[Sampler" + i + "]", "play"); + } + } +}; + /****************** Load button : * - Load a track : Press these buttons to load the selected track from * (short press) the Browser to left or right deck. The LED of the @@ -1460,61 +1561,63 @@ NumarkMixtrack3.BrowseKnob = function(channel, control, value, status, group) { NumarkMixtrack3.LoadButton = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - - //deck.faderstart = false; - var groupOff; - var deckOff; - if (decknum === 1) { - groupOff = "[Channel2]"; - deckOff = NumarkMixtrack3.decks["D2"]; - }else{ - groupOff = "[Channel1]"; - deckOff = NumarkMixtrack3.decks["D1"]; - } - - if (value === DOWN) { + var i; + + if (value === DOWN) { deck.LEDs["headphones"].onOff(ON); deck.faderstart = false; - + if (smartPFL) { - print("smartPFL" +smartPFL); - engine.setValue(group, 'pfl', true); - engine.setValue(groupOff, 'pfl', false); - deck.LEDs["headphones"].onOff(ON); - deckOff.LEDs["headphones"].onOff(ON); + for (i = 1; i <= 4; i++) { + //Change headphone cue (pfl) to the deck on which the song loaded. + engine.setValue("[Channel" + i + "]", "pfl", (decknum === i) ? 1 : 0); + } } - - + if (deck.shiftKey) { // SHIFT + Load = fader start activated - + deck.faderstart = true; deck.LEDs["headphones"].flashOn(250, ON, 250); - - if (!deck.TrackIsLoaded) { - printInfo("track not loaded, load track"); - engine.setValue(group, 'LoadSelectedTrack', true); - } + if (!deck.TrackIsLoaded) { + engine.setValue("[Channel" + decknum + "]", 'LoadSelectedTrack', true); + } } - - deck.LoadButtonControl.ButtonDown(channel, control, value, status, group); + + deck.LoadButtonControl.ButtonDown(channel, control, value, status, + "[Channel" + decknum + "]"); } else { deck.LoadButtonControl.ButtonUp(); - } + } }; // Callback for the Load Button -NumarkMixtrack3.OnLoadButton = function(channel, control, value, status, group, eventkind) { - // var decknum = NumarkMixtrack3.deckFromGroup(group); - // var deck = NumarkMixtrack3.decks["D" + decknum]; - +NumarkMixtrack3.OnLoadButton = function(channel, control, value, status, group, + eventkind) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + if (eventkind === LONG_PRESS) { - engine.setValue(group, 'eject', true); + engine.setValue("[Channel" + decknum + "]", 'eject', true); } else { - engine.setValue(group, 'LoadSelectedTrack', true); + engine.setValue("[Channel" + decknum + "]", 'LoadSelectedTrack', true); + } +}; + +NumarkMixtrack3.OnLoadSelectedTrack = function(value, group, control) { + var decknum = script.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var TrackDuration = engine.getValue("[Channel" + decknum + "]", "duration"); + var i; + + if (smartPFL && deck.duration !== TrackDuration && TrackDuration !== 0) { + for (i = 1; i <= 4; i++) { + //Change headphone cue (pfl) to the deck on which the song loaded. + engine.setValue("[Channel" + i + "]", "pfl", (decknum === i) ? 1 : 0); + } } + deck.duration = engine.getValue("[Channel" + decknum + "]", "duration"); }; /****************** Sync button : @@ -1540,24 +1643,26 @@ NumarkMixtrack3.SyncButton = function(channel, control, value, status, group) { if (!deck.shiftKey) { if (value === DOWN) { - deck.SyncButtonControl.ButtonDown(channel, control, value, status, group); + deck.SyncButtonControl.ButtonDown(channel, control, value, + status, "[Channel" + decknum + "]"); } else { deck.SyncButtonControl.ButtonUp(); } } else { if (value === DOWN) { - toggleValue(group,"keylock"); + toggleValue("[Channel" + decknum + "]", "keylock"); } } }; // Callback for the SYNC Button -NumarkMixtrack3.OnSyncButton = function(channel, control, value, status, group, eventkind) { - var decknum = NumarkMixtrack3.deckFromGroup(group); +NumarkMixtrack3.OnSyncButton = function(channel, control, value, status, group, + eventkind) { + var decknum = script.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - + if (eventkind === LONG_PRESS) { deck.LEDs.sync.onOff(ON); engine.setValue(group, 'sync_enabled', true); @@ -1575,7 +1680,7 @@ NumarkMixtrack3.OnSyncButton = function(channel, control, value, status, group, deck.LEDs.sync.flashOn(100, ON, 100, 3); } else { // We pressed sync only once, we sync the track - // with the other track (eventkind === QUICK_PRESS + // with the other track (eventkind === QUICK_PRESS engine.setValue(group, 'beatsync', true); deck.LEDs.sync.flashOn(100, ON, 100, 3); } @@ -1583,17 +1688,16 @@ NumarkMixtrack3.OnSyncButton = function(channel, control, value, status, group, } }; - NumarkMixtrack3.OnSyncButtonChange = function(value, group, key) { - var decknum = NumarkMixtrack3.deckFromGroup(group); + var decknum = script.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; var valIn = engine.getValue(group, 'sync_enabled'); - + if (valIn) { deck.LEDs.sync.onOff(ON); - }else{ + } else { deck.LEDs.sync.onOff(OFF); - } + } }; /****************** Cue button : @@ -1603,48 +1707,55 @@ NumarkMixtrack3.OnSyncButtonChange = function(value, group, key) { NumarkMixtrack3.CueButton = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - + if (!deck.shiftKey) { // Don't set Cue accidentaly at the end of the song - if (engine.getValue(group, "playposition") <= 0.97) { - engine.setValue(group, "cue_default", value ? 1 : 0); + if (engine.getValue("[Channel" + decknum + "]", "playposition") <= 0.97) { + engine.setValue("[Channel" + decknum + "]", "cue_default", value ? 1 : 0); } else { - engine.setValue(group, "cue_preview", value ? 1 : 0); + engine.setValue("[Channel" + decknum + "]", "cue_preview", value ? 1 : 0); } } else { - engine.setValue(group, "start", true); + engine.setValue("[Channel" + decknum + "]", "start", true); } }; +NumarkMixtrack3.OnCuePointChange = function(value, group, control) { + var decknum = script.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + deck.LEDs.Cue.onOff((value) ? ON : OFF); +}; + // Pitch faders send 2*7bits -NumarkMixtrack3.PitchFaderHighValue = function(channel, control, value, status, group) { +NumarkMixtrack3.PitchFaderHighValue = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; deck.PitchFaderHigh = value; }; -NumarkMixtrack3.PitchFaderLowValue = function(channel, control, value, status, group) { +NumarkMixtrack3.PitchFaderLowValue = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - var calcvalue = (8192-((deck.PitchFaderHigh*128)+value))/8192; - engine.setValue(group, "rate", calcvalue); + var calcvalue = (8192 - ((deck.PitchFaderHigh * 128) + value)) / 8192; + engine.setValue("[Channel" + decknum + "]", "rate", calcvalue); }; - -NumarkMixtrack3.toggleJogMode = function(channel, control, value, status, group) { +NumarkMixtrack3.toggleJogMode = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - + if (value === DOWN) { // Toggle setting and light deck.jogWheelsInScratchMode = !deck.jogWheelsInScratchMode; - deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? ON : OFF); + deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? + ON : OFF); } }; - - -NumarkMixtrack3.WheelTouch = function(channel, control, value, status, group) { +NumarkMixtrack3.WheelTouch = function(channel, control, value, status, group) { /* This function sets the variable to assign the wheel move action - Pitch bend / jog = default @@ -1654,333 +1765,541 @@ NumarkMixtrack3.WheelTouch = function(channel, control, value, status, group) { */ var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - + var isplaying = engine.getValue("[Channel" + decknum + "]", "play"); + deck.touch = false; deck.iCutStatus = false; deck.seekingfast = false; - - printInfo("Start WheelMove decknum=" + decknum +"; deck="+deck+"; group="+group+"; WheelTouch = DOWN (on) "); - + if (value === DOWN) { - printInfo(" WheelTouch = DOWN (on) "); - - if (deck.jogWheelsInScratchMode) { - - engine.scratchEnable(decknum, intervalsPerRev, rpm, alpha, beta); - + + if (deck.jogWheelsInScratchMode || !isplaying) { + + engine.scratchEnable(decknum, intervalsPerRev, rpm, alpha, beta); + // Wheel is On - test for Shift Key"); - - if (deck.shiftKey && iCutEnabled) { - printInfo(" Wheel ON - Shift true - ICUT = true"); + if (deck.shiftKey && iCutEnabled) { deck.iCutStatus = true; deck.Jog.iCUT.On(); - + } else { - printInfo(" Wheel ON - Shift = false - Scratching - deck.touch = true"); deck.iCutStatus = false; deck.touch = true; deck.Jog.iCUT.Off(); } - } else { - + if (fastSeekEnabled && deck.shiftKey) { - printInfo(" Wheel Off - Shift true - Fast Seek"); - deck.seekingfast = true; - } + deck.seekingfast = true; + } } } else { - - printInfo(" WheelTouch = UP (off) "); engine.scratchDisable(decknum, true); deck.seekingfast = false; deck.Jog.iCUT.Off(); - } }; - - NumarkMixtrack3.WheelMove = function(channel, control, value, status, group) { +NumarkMixtrack3.WheelMove = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - + + // Set jog value var adjustedJog = parseFloat(value); var posNeg = 1; - + if (adjustedJog > 63) { // Counter-clockwise posNeg = -1; adjustedJog = value - 128; } - -/* This function performs that actions defined by wheel touch - - Pitch bend / jog = default - - fast seek - deck.seekingfast = true - - iCut = deck.iCutStatus = true - - Scratching = deck.touch = true */ - + + /* This function performs that actions defined by wheel touch + - Pitch bend / jog = default + - fast seek - deck.seekingfast = true + - iCut = deck.iCutStatus = true + - Scratching = deck.touch = true */ if (deck.iCutStatus) { - printInfo(" WheelMove - ICUT = true - adjustedJog =" +adjustedJog +" value="+value); deck.Jog.iCUT.On(); - deck.Jog.iCUT.FaderCut(adjustedJog); - } - - // the 2 conditions below may not be required as the simply default to - if (deck.touch) { - printInfo(" WheelMove - Scratching = true - adjustedJog =" +adjustedJog+" value="+value); - // scratch is enabled in wheel touch, we just record ticks - } - - if (!deck.seekingfast && !deck.iCutStatus && !deck.touch) { - printInfo(" WheelMove - Jog / Pitch bend"); + deck.Jog.iCUT.FaderCut(adjustedJog, decknum); } - + + if (!deck.seekingfast && !deck.iCutStatus && !deck.touch && deck.jogWheelsInScratchMode) { + } + if (deck.seekingfast) { - printInfo(" WheelMove - seekingfast = true - adjustedJog =" +adjustedJog+" value="+value); engine.setValue(deck.Jog.group, "beatjump", adjustedJog * 2); } - + engine.scratchTick(decknum, adjustedJog); - printInfo( "engine.scratchTick("+ decknum +"," +adjustedJog+") value="+value); - - //Pitch bend when playing - side or platter have same effect - if (engine.getValue(deck.Jog.group, "play")) { - var gammaInputRange = 13; // Max jog speed - var maxOutFraction = 0.8; // Where on the curve it should peak; 0.5 is half-way - var sensitivity = 0.5; // Adjustment gamma - var gammaOutputRange = 0.75; // Max rate change - - adjustedJog = posNeg * gammaOutputRange * Math.pow(Math.abs( - adjustedJog) / (gammaInputRange * maxOutFraction), - sensitivity); - engine.setValue(deck.Jog.group, "jog", adjustedJog); - } -}; + if(PitchBendOnWheelOff) { + //Pitch bend when playing - side or platter have same effect + if (engine.getValue(deck.Jog.group, "play")) { + var gammaInputRange = 13; // Max jog speed + var maxOutFraction = 0.8; // Where on the curve it should peak; 0.5 is half-way + var sensitivity = 0.5; // Adjustment gamma + var gammaOutputRange = 0.75; // Max rate change + + adjustedJog = posNeg * gammaOutputRange * Math.pow(Math.abs( + adjustedJog) / (gammaInputRange * maxOutFraction), + sensitivity); + engine.setValue(deck.Jog.group, "jog", adjustedJog); + } + } else { + //Pitch bend when playing - side or platter have same effect + if (deck.jogWheelsInScratchMode) { + if (engine.getValue(deck.Jog.group, "play")) { + var gammaInputRange = 13; // Max jog speed + var maxOutFraction = 0.8; // Where on the curve it should peak; 0.5 is half-way + var sensitivity = 0.5; // Adjustment gamma + var gammaOutputRange = 0.75; // Max rate change + + adjustedJog = posNeg * gammaOutputRange * Math.pow(Math.abs( + adjustedJog) / (gammaInputRange * maxOutFraction), + sensitivity); + engine.setValue(deck.Jog.group, "jog", adjustedJog); + } + } + } +}; NumarkMixtrack3.HotCueButton = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; var hotCue = control - leds.hotCue1 + 1; - // onHotCueChange called automatically if (deck.shiftKey) { if (value === DOWN) { - engine.setValue(group, "hotcue_" + hotCue + "_clear", true); + engine.setValue("[Channel" + decknum + "]", "hotcue_" + hotCue + "_clear", true); deck.LEDs["hotCue" + hotCue].onOff(OFF); } } else { if (value === DOWN) { - engine.setValue(group, "hotcue_" + hotCue + "_activate", 1); + engine.setValue("[Channel" + decknum + "]", "hotcue_" + hotCue + "_activate", 1); } else { - engine.setValue(group, "hotcue_" + hotCue + "_activate", 0); + engine.setValue("[Channel" + decknum + "]", "hotcue_" + hotCue + "_activate", 0); } } }; -// Returns the deck number of a "ChannelN" or "SamplerN" group -// copied from the common script because for some reason the section for extracting the sampler number -// is commented out in the common script -NumarkMixtrack3.deckFromGroup = function (group) { - var deck = 0; - if (group.substring(2,8)=="hannel") { - // Extract deck number from the group text - deck = group.substring(8,group.length-1); +NumarkMixtrack3.OnHotcueChange = function(value, group, control) { + var decknum = script.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var padindex = parseInt(NumarkMixtrack3.channelRegEx.exec(control)[1]); + + deck.LEDs["hotCue" + padindex].onOff((value) ? ON : OFF); +}; + +NumarkMixtrack3.SamplerButton = function(channel, control, value, status, + group) { + var isplaying = engine.getValue(group, "play"); + var padindex = parseInt(group.substring(8, 9)); + var decknum = padindex; + + if (decknum > 4) { + decknum = 2; + engine.setValue("[Deere]","sampler_bank_2", true); + } else { + decknum = 1; + engine.setValue("[Deere]","sampler_bank_1", true); } - else if (group.substring(2,8)=="ampler") { - // Extract sampler number from the group text - deck = group.substring(8,group.length-1); + decknum = NumarkMixtrack3.deckFromGroup("[Channel" + decknum + "]"); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var sampler = NumarkMixtrack3.samplers["S" + padindex]; + + if (value === DOWN) { + + + sampler.PADSampleButtonHold.ButtonDown(channel, control, value, status, group); + + if (!isplaying) { + if (deck.shiftKey) { + //Shift is on, play sampler with no Sync + engine.setValue(group, "beatsync", 0); + engine.setValue(group, "cue_gotoandplay", 1); + sampler.LEDs["PADsampler" + padindex].flashOn(300, + PADcolors.purple, 300); + } else { + //play sampler with Sync + engine.setValue(group, "cue_gotoandplay", 1); + engine.setValue(group, "beatsync", 1); + sampler.LEDs["PADsampler" + padindex].flashOn(300, + PADcolors.purple, 300); + } + } else { + engine.setValue(group, "stop", 1); + sampler.LEDs["PADsampler" + padindex].onOff(ON); + } } - return parseInt(deck); + if (value === OFF) { + sampler.PADSampleButtonHold.ButtonUp(); + } }; -NumarkMixtrack3.SamplerButton = function(channel, control, value, status, group) { - var decknum = NumarkMixtrack3.deckFromGroup(group); - var padindex = decknum; +NumarkMixtrack3.onPADSampleButtonHold = function(channel, control, value, status, + group, eventkind) { + var decknum = parseInt(group.substring(8, 9)); + var sampler = NumarkMixtrack3.samplers["S" + decknum]; + var padindex = parseInt(group.substring(8, 9)); - if (value=== DOWN) { - NumarkMixtrack3.samplers.play(padindex,true); + if (decknum > 4) { + decknum = 2; + } else { + decknum = 1; + } + + //The event is a Long Press, LONG_PRESS is true, we set a variable so that when the + // pad button is lifted, the Sampler stops + if (eventkind === LONG_PRESS) { + engine.setValue(group, "stop", 1); + sampler.LEDs["PADsampler" + padindex].onOff(ON); } - - if (value === OFF && PADSampleButtonHold) { - NumarkMixtrack3.samplers.play(padindex,false); - } }; -NumarkMixtrack3.PADLoopButton = function(channel, control, value, status, group) { +NumarkMixtrack3.OnSamplePlayStop = function(value, group, control) { + var decknum = parseInt(group.substring(8, 9)); + var sampler = NumarkMixtrack3.samplers["S" + decknum]; + + if (value === 1) { + sampler.LEDs["PADsampler" + decknum].flashOn(300, PADcolors.purple, + 300); + } else { + sampler.LEDs["PADsampler" + decknum].onOff(ON); + } +}; + +NumarkMixtrack3.PADLoopButton = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; var padindex = control - leds.PADloop1 + 1; - var loopsize = 1; var trueFalse; - + var loopsizeNew; + if (deck.shiftKey) { - loopsize = Math.pow(2, padindex - 4); + loopsizeNew = loopsize[padindex + 3]; } else { - loopsize = Math.pow(2, padindex); + loopsizeNew = loopsize[padindex - 1]; } - + var loopCommand1; //verify if loop is active var loopCommand2; //enable loop var loopCommand3; //stop loop - + if (beatlooprollActivate) { - loopCommand1 = "beatlooproll_" + loopsize + "_activate"; - loopCommand2 = "beatlooproll_" + loopsize + "_activate"; - loopCommand3 = "beatlooproll_" + loopsize + "_activate"; + loopCommand1 = "beatlooproll_" + loopsizeNew + "_activate"; + loopCommand2 = "beatlooproll_" + loopsizeNew + "_activate"; + loopCommand3 = "beatlooproll_" + loopsizeNew + "_activate"; trueFalse = false; } else { - loopCommand1 = "beatloop_" + loopsize + "_enabled"; - loopCommand2 = "beatloop_" + loopsize + "_toggle"; + loopCommand1 = "beatloop_" + loopsizeNew + "_enabled"; + loopCommand2 = "beatloop_" + loopsizeNew + "_toggle"; loopCommand3 = "reloop_exit"; trueFalse = true; } - - if (value === DOWN) { - // make sure all LED are ON - deck.LEDs["PADloop1"].onOff(PADcolors.yellow); - deck.LEDs["PADloop2"].onOff(PADcolors.yellow); - deck.LEDs["PADloop3"].onOff(PADcolors.yellow); - deck.LEDs["PADloop4"].onOff(PADcolors.yellow); - - if (engine.getValue(group,loopCommand1)) { + + if (value === DOWN && deck.duration !== 0) { + // make sure all LED are ON + deck.LEDs["PADloop1"].onOff(PADcolors.yellow); + deck.LEDs["PADloop2"].onOff(PADcolors.yellow); + deck.LEDs["PADloop3"].onOff(PADcolors.yellow); + deck.LEDs["PADloop4"].onOff(PADcolors.yellow); + + if (engine.getValue(group, loopCommand1)) { // Loop is active, turn it off - print("LED ON - loop OFF "+ padindex); - engine.setValue(group,loopCommand3, trueFalse); + engine.setValue("[Channel" + decknum + "]", loopCommand3, trueFalse); deck.LEDs["PADloop" + padindex].onOff(PADcolors.yellow); - - } else { + + } else { // Loop is not active, turn it on - print("Flash LED - loop "+ padindex); - deck.LEDs["PADloop" + padindex].flashOn(250, PADcolors.yellow, 250); - print("loopCommand2 "+ loopCommand2); - engine.setValue(group,loopCommand2,true); + deck.LEDs["PADloop" + padindex].flashOn(250, PADcolors.yellow, + 250); + engine.setValue("[Channel" + decknum + "]", loopCommand2, true); + } + // Event if long press + deck.PADLoopButtonHold.ButtonDown(channel, control, value, status, + "[Channel" + decknum + "]"); + } + + if (value === OFF && deck.duration !== 0) { //This triggers the callback function for "PADLoopButtonHold" + deck.PADLoopButtonHold.ButtonUp(); + } +}; + +NumarkMixtrack3.onPADLoopButtonHold = function(channel, control, value, status, + group, eventkind) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var padindex = control - leds.PADloop1 + 1; + var loopsizeNew; - } + if (deck.shiftKey) { + loopsizeNew = loopsize[padindex + 3]; + } else { + loopsizeNew = loopsize[padindex - 1]; } - if (value === OFF && PADLoopButtonHold) { - engine.setValue(group,loopCommand2,false); - deck.LEDs["PADloop" + padindex].onOff(PADcolors.yellow); + if (eventkind === LONG_PRESS) { + if (beatlooprollActivate) { + engine.setValue("[Channel" + decknum + "]", "reloop_exit", true); + } else { + engine.setValue("[Channel" + decknum + "]", "beatlooproll_" + loopsizeNew + "_activate", false); + } } }; +NumarkMixtrack3.OnPADLoopButtonChange = function(value, group, control) { + var decknum = script.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var padindex = NumarkMixtrack3.Autoloop[control]; + var i; + var index; -NumarkMixtrack3.StripTouchEffect = function(channel, control, value, status, group) { + if (value === 1) { + deck.LEDs["PADloop" + padindex].flashOn(300, PADcolors.yellow, 300); + } else { + deck.LEDs["PADloop" + padindex].onOff(PADcolors.yellow); + } + + // on initialization of deck, the value "0" would cause the pad LED to stop blinking on the 2nd pass + // of triggers. This gives ensures that the PAD mode reflect the proper state of AutoLoop + for (i = 0; i < loopsize.length; i++) { + index = i + 1; + if (index > 4) { + index = index - 4; + } + + var test = engine.getValue("[Channel" + decknum + "]", "beatloop_" + loopsize[i] + + "_enabled"); + + if (test) { + NumarkMixtrack3.decks["D" + decknum].LEDs["PADloop" + index].flashOn(300, PADcolors.yellow, 300); + } + } +}; + +NumarkMixtrack3.StripTouchEffect = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; if (deck.shiftKey) { - engine.setValue(group, "playposition", value / 127); + engine.setValue("[Channel" + decknum + "]", "playposition", value / 127); } else { - deck.StripEffect(value, decknum); + deck.StripEffect(value, decknum); } }; -NumarkMixtrack3.StripTouchSearch = function(channel, control, value, status, group) { +NumarkMixtrack3.InstantFXOff = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - if (deck.shiftKey) { - engine.setValue(group, "playposition", value / 127); - } else { - deck.StripEffect(value, decknum); + var i; + var ButtonNum; + var arrayLength = deck.InstantFX.length; + + for (i = 0; i < arrayLength; i++) { + ButtonNum = deck.InstantFX[i]; + + if (FXmode === 1) { //3 FX in 4 FX Units + engine.setValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", + "enabled", false); + } else { // 1 FX in 3 FX unit + engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", + "group_[Channel" + decknum + "]_enable", false); + } } }; NumarkMixtrack3.FXButton = function(channel, control, value, status, group) { - if (!value) return; + //if (!value) return; //not sure why this is there var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - var ButtonNum = control - leds.fx1+1; - if (value === DOWN) { + var ButtonNum = control - leds.fx1 + 1; + var i; + var new_value; + + if (value === DOWN && deck.TapDown && !deck.PADMode) { + + if (deck.InstantFX.indexOf(ButtonNum) > -1) { + // we are removing the instantFX option from the selected FX button + // Find and remove item from an array + i = deck.InstantFX.indexOf(ButtonNum); + if (i != -1) { + deck.InstantFX.splice(i, 1); + } + + if (deck.InstantFX.indexOf(ButtonNum) === -1) { + new_value = engine.getValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + + ButtonNum + "]", "enabled"); + deck.LEDs["fx" + ButtonNum].onOff(new_value ? ON : OFF); + } + + } else { + + // we are adding the effect to the InstantFX list, or removing it + // tap + FX button enables/disables InstantFX, we check deck.TapDown to know if tap is pressed + //in order for FX LEDs to flas in sync, we need to loop thru the array to reset the LEDs + deck.InstantFX.push(ButtonNum); + + // Get all LEDs to flash in sync + var arrayLength = deck.InstantFX.length; + for (i = 0; i < arrayLength; i++) { + + ButtonNum = deck.InstantFX[i]; + deck.LEDs["fx" + ButtonNum].flashOn(250, ON, 250); + } + } + } else if (value === DOWN && !deck.TapDown && !deck.PADMode) { if (deck.shiftKey) { // Select Effect - if (decknum===1) { - engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", "prev_chain", true); + if (FXmode === 1) { //3 FX in 4 FX Units + engine.setValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", + "next_effect", true); // Load FX, but not active + engine.setValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", + "enabled", false); // Load FX, but not active + engine.setValue("[EffectRack1_EffectUnit" + decknum + "]", + "group_[Channel" + decknum + "]_enable", true); // An FX is loaded, activate Effect Unit } else { - engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", "next_chain", true); + engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", "prev_chain", true); } } else { - // Toggle effect - var new_value = !engine.getValue("[EffectRack1_EffectUnit" + ButtonNum + "]","group_" + group + "_enable"); - engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]","group_" + group + "_enable",new_value); - deck.LEDs["fx" + ButtonNum].onOff(new_value?ON:OFF); + // Toggle effect if InstantFX is not active + if (deck.InstantFX.indexOf(ButtonNum) === -1) { + if (FXmode === 1) { //3 FX in 4 FX Units + new_value = !engine.getValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", + "enabled"); + engine.setValue("[EffectRack1_EffectUnit" + decknum + "_Effect" + ButtonNum + "]", "enabled", + new_value); + } else { + new_value = !engine.getValue("[EffectRack1_EffectUnit" + + ButtonNum + "]", "group_[Channel" + decknum + "]_enable"); + engine.setValue("[EffectRack1_EffectUnit" + ButtonNum + "]", + "group_[Channel" + decknum + "]_enable", new_value); + } + deck.LEDs["fx" + ButtonNum].onOff(new_value ? ON : OFF); + } } } -}; + + // Standard FX Control done, now deal with extra features + + if (value === DOWN && deck.PADMode && ButtonNum === 2) { + engine.spinback(decknum, true); // enable spinback effect + } else { + engine.spinback(decknum, false); // disable spinback effect + } + + if (deck.PADMode && ButtonNum === 1) { + NumarkMixtrack3.brake_button(decknum, value); + } +}; + +NumarkMixtrack3.brake_button = function(decknum, value) { + var activate = value > 0; + + if (activate) { + engine.brake(decknum, true); // enable brake effect + } else { + engine.brake(decknum, false); // disable brake effect + } +}; + +NumarkMixtrack3.OnEffectEnabled = function(value, group, control) { + var index; + var decknum; + if (FXmode === 1) { + index = NumarkMixtrack3.fxControls[group]; + decknum = NumarkMixtrack3.fxGroups[group]; + } else { + index = NumarkMixtrack3.fxControls[group]; + decknum = NumarkMixtrack3.fxGroups[control]; + } + + var deck = NumarkMixtrack3.decks["D" + decknum]; + + if (deck.InstantFX.indexOf(index) === -1) { + var new_value = engine.getValue(group, control); + deck.LEDs["fx" + index].onOff(new_value ? ON : OFF); + } +}; /****************** Shift Button : * - Press : toggle PFL * - SHIFT + press : toggle slip mode * - SHIFT + double press : toggle quantize mode * *********************************************************************/ -NumarkMixtrack3.PFLButton = function(channel, control, value, status, group) { +NumarkMixtrack3.PFLButton = function(channel, control, value, status, group) { if (!value) return; var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; + var i; + if (value === DOWN) { if (deck.shiftKey) { - deck.ShiftedPFLButtonControl.ButtonDown(channel, control, value, status, group); + deck.ShiftedPFLButtonControl.ButtonDown(channel, control, value, + status, "[Channel" + decknum + "]"); } else { - toggleValue(group,"pfl"); + toggleValue("[Channel" + decknum + "]", "pfl"); + for (i = 1; i <= 4 ; i++) { + if (i != decknum) { + engine.setValue("[Channel" + i + "]", "pfl", false); + } + } } } -}; +}; + +NumarkMixtrack3.OnPFLStatusChange = function(value, group, control) { + var decknum = script.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + + deck.LEDs.headphones.onOff((value) ? ON : OFF); +}; // Callback for the PFL Button -NumarkMixtrack3.OnShiftedPFLButton = function(channel, control, value, status, group, eventkind) { +NumarkMixtrack3.OnShiftedPFLButton = function(channel, control, value, status, + group, eventkind) { if (eventkind === DOUBLE_PRESS) { // Double press : toggle slip mode - toggleValue(group,"slip_enabled"); + toggleValue(group, "slip_enabled"); } else { // Single press : toggle quantize mode - toggleValue(group,"quantize"); - } -}; - -NumarkMixtrack3.LoopHalveButton = function(channel, control, value, status, group) { - if (value===DOWN) { - var decknum = NumarkMixtrack3.deckFromGroup(group); - var deck = NumarkMixtrack3.decks["D" + decknum]; - - if (deck.shiftKey) { - engine.setValue(group, "loop_double", true); - } else { - engine.setValue(group, "loop_halve", true); - } + toggleValue(group, "quantize"); } }; -NumarkMixtrack3.PitchBendMinusButton = function(channel, control, value, status, group) { +NumarkMixtrack3.PitchBendMinusButton = function(channel, control, value, + status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - if (value===DOWN) { - if (deck.shiftKey) { - engine.setValue(group, "beatjump_1_backward", true); + if (value === DOWN) { + if (deck.shiftKey) { + engine.setValue("[Channel" + decknum + "]", "beatjump_1_backward", true); } else { - engine.setValue(group, "rate_temp_down", true); + engine.setValue("[Channel" + decknum + "]", "rate_temp_down", true); } } else if (!deck.shiftKey) { - engine.setValue(group, "rate_temp_down", false); + engine.setValue("[Channel" + decknum + "]", "rate_temp_down", false); } }; -NumarkMixtrack3.PitchBendPlusButton = function(channel, control, value, status, group) { +NumarkMixtrack3.PitchBendPlusButton = function(channel, control, value, status, + group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - - if (value===DOWN) { - if (deck.shiftKey) { - engine.setValue(group, "beatjump_1_forward", true); + if (value === DOWN) { + + if (deck.shiftKey) { + engine.setValue("[Channel" + decknum + "]", "beatjump_1_forward", true); } else { - engine.setValue(group, "rate_temp_up", true); + engine.setValue("[Channel" + decknum + "]", "rate_temp_up", true); } - } - else if (!deck.shiftKey) { - engine.setValue(group, "rate_temp_up", false); + } else if (!deck.shiftKey) { + engine.setValue("[Channel" + decknum + "]", "rate_temp_up", false); } }; @@ -1989,144 +2308,345 @@ NumarkMixtrack3.BeatKnob = function(channel, control, value, status, group) { var deck = NumarkMixtrack3.decks["D" + decknum]; var gainIncrement; var gainValue = []; - var i,j; + var i; var knobValue; - - if (!BeatKnobAsSamplerVolume) { - // Default configuration option, use knob for Beatgrid only - if (value-64 > 0) { - knobValue = value-128; + + if (!deck.PADMode) { + + // Default mode, direct interaction with knob, without any button combination + for (i = 1; i <= 4; i++) { + + gainValue[i - 1] = engine.getParameter( + "[EffectRack1_EffectUnit" + [i] + "]", "mix"); + + // increment value between 0 and 1 + gainIncrement = 1 / 20; // 20 increments in one full knob turn + + // beat knobs sends 1 or 127 as value. If value = 127, turn is counterclockwise, we reduce gain + if (value === 127) { + gainIncrement = -gainIncrement; + } + + gainValue[i - 1] = gainValue[i - 1] + gainIncrement; + + if ((gainValue[i - 1] + gainIncrement) < 0) { + gainValue[i - 1] = 0; + } + if ((gainValue[i - 1] + gainIncrement) > 1) { + gainValue[i - 1] = 1; + } + + } + + // we adjust pregain with adjusted value + for (i = 1; i <= 5; i++) { + if (gainValue[i - 1] >= 0 && gainValue[i - 1] <= 4) { + if (deck.TapDown) { + engine.setParameter("[EffectRack1_EffectUnit" + i + + "_Effect1]", "parameter2", gainValue[i - 1]); + } else { + if (FXmode === 1){ + if (decknum === i) { + engine.setParameter("[EffectRack1_EffectUnit" + i + + "]", "mix", gainValue[i - 1]); + } + } else { //FX Mode = 1 FX 3 Units + engine.setParameter("[EffectRack1_EffectUnit" + i + + "]", "mix", gainValue[i - 1]); + } + } + } + } + + } + + if (deck.shiftKey) { + if (value - 64 > 0) { + knobValue = value - 128; } else { knobValue = value; } - if (deck.shiftKey) { - if (knobValue<0) { - engine.setValue(group, "beats_adjust_slower", true); - } else { - engine.setValue(group, "beats_adjust_faster", true); - } + if (knobValue < 0) { + engine.setValue("[Channel" + decknum + "]", "beats_translate_earlier", true); } else { - if (knobValue<0) { - engine.setValue(group, "beats_translate_earlier", true); - } else { - engine.setValue(group, "beats_translate_later", true); - } + engine.setValue("[Channel" + decknum + "]", "beats_translate_later", true); } - - } else { - // Option: use BeatKnob to adjust Sampler volumes - if (deck.shiftKey) { - if (value-64 > 0) { - knobValue = value-128; + } + + if (deck.PADMode) { + // PadMode button is used, Shift key is not used, we adjust Sampler volumes + // Define new value of sampler pregain + // Off = 1, centered = 1, max = 4 + + var startingSampler; + if (decknum === 1 || decknum === 3) { + startingSampler = 1; + } else { + startingSampler = 5; + } + + for (i = startingSampler; i <= startingSampler + 3; i++) { + + gainValue[i - 1] = engine.getValue("[Sampler" + [i] + "]", + "pregain"); + + if (gainValue[i - 1] <= 1) { + // increment value between 0 and 1 + gainIncrement = 1 / 20; // 20 increments in one full knob turn } else { - knobValue = value; + // increment value between 1 and 4 + gainIncrement = 3 / 20; // 20 increments in one full knob turn } - - if (knobValue<0) { - engine.setValue(group, "beats_translate_earlier", true); - } else { - engine.setValue(group, "beats_translate_later", true); + + // beat knobs sends 1 or 127 as value. If value = 127, turn is counterclockwise, we reduce gain + if (value === 127) { + gainIncrement = -gainIncrement; } - } else { - // Shift key is not used, we adjust Sampler volumes - // Define new value of sampler pregain - // Off = 1, centered = 1, max = 4 - if (decknum === 1) { - for (i = 1; i <= 4; i++) { - gainValue[i-1] = engine.getValue("[Sampler" + [i] + "]", "pregain"); - - if (gainValue[i-1] <= 1) { - // increment value between 0 and 1 - gainIncrement = 1/20; // 20 increments in one full knob turn - }else{ - // increment value between 1 and 4 - gainIncrement = 3/20; // 20 increments in one full knob turn - } - - // beat knobs sends 1 or 127 as value. If value = 127, turn is counterclockwise, we reduce gain - if (value === 127) { - gainIncrement = - gainIncrement; - } - - gainValue[i-1] = gainValue[i-1] + gainIncrement; - - if ((gainValue[i-1] + gainIncrement) <0) { - gainValue[i-1] = 0; - } - - if ((gainValue[i-1] + gainIncrement) >4) { - gainValue[i-1] = 4; - } - - } - } else { - for (j = 5; j <= 8; j++) { - gainValue[j-1] = engine.getValue("[Sampler" + [j] + "]", "pregain"); - - if (gainValue[j-1] <= 1) { - // increment value between 0 and 1 - gainIncrement = 1/20; // 20 increments in one full knob turn - }else{ - // increment value between 1 and 4 - gainIncrement = 3/20; // 20 increments in one full knob turn - } - - // beat knobs sends 1 or 127 as value. If value = 127, turn is counterclockwise, we reduce gain - if (value === 127) { - gainIncrement = - gainIncrement; - } - - gainValue[j-1] = gainValue[j-1] + gainIncrement; - - if ((gainValue[j-1] + gainIncrement) <0) { - gainValue[j-1] = 0; - } - - if ((gainValue[j-1] + gainIncrement) >4) { - gainValue[j-1] = 4; - } - } + + gainValue[i - 1] = gainValue[i - 1] + gainIncrement; + + if ((gainValue[i - 1] + gainIncrement) < 0) { + gainValue[i - 1] = 0; } - // we adjust pregain with adjusted value - if (decknum === 1) { - for (i = 1; i <= 4; i++) { - if (gainValue[i-1] >=0 && gainValue[i-1] <= 4) { - engine.setValue("[Sampler" + i + "]", "pregain", gainValue[i-1]); - } - } + if ((gainValue[i - 1] + gainIncrement) > 4) { + gainValue[i - 1] = 4; + } + + if (gainValue[i - 1] >= 0 && gainValue[i - 1] <= 4) { + engine.setValue("[Sampler" + i + "]", "pregain", + gainValue[i - 1]); + } + } + } +}; + +NumarkMixtrack3.bpmTap = function(channel, control, value, status, group) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + + deck.TapDown = false; + + if (value === DOWN) { + + deck.TapDown = true; //to use TAP button as a "shift" key (e.g. InstantFX) + + if (deck.shiftKey) { // Toggle decks + if (decknum <= 2) { + decknum += 2; } else { - for (i = 5; i <= 8; i++) { - if (gainValue[i-1] >= 0 && gainValue[i-1] <= 4) { - engine.setValue("[Sampler" + i + "]", "pregain", gainValue[i-1]); - } - } + decknum -= 2; } + //determine the deck that we want to switch to: + NumarkMixtrack3.deckGroup[group] = '[Channel' + decknum + ']'; + NumarkMixtrack3.initDeck(NumarkMixtrack3.deckGroup[group], true); + } else { //Either use the button as a modifier, or as TAP button + bpm.tapButton(decknum); + engine.setValue("[Channel" + decknum + "]", "bpm_tap", true); } } + engine.setValue("[Channel" + decknum + "]", "bpm_tap", false); }; -NumarkMixtrack3.bpmTap = function(channel, control, value, status, group) { +NumarkMixtrack3.EQKnob = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; + var EQp, FXp; + + switch (control) { + case 1: // Treble + EQp = 3; + FXp = 1; + break; + case 2: // Mid + EQp = 2; + FXp = 2; + break; + case 3: // Bass + EQp = 1; + FXp = 3; + break; + } - if (value===DOWN) { - engine.setValue(group, "bpm_tap", true); + if (!deck.shiftKey && !deck.PADMode && !deck.TapDown) { + parameterSoftTakeOver("[EqualizerRack1_[Channel" + decknum + + "]_Effect1]", "parameter" + EQp, value); + } + + if (FXmode === 1) { + if (deck.shiftKey) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect1]", "parameter" + FXp, value); + } + if (deck.PADMode) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect2]", "parameter" + FXp, value); + } + if (deck.TapDown) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect3]", "parameter" + FXp, value); + } } else { - engine.setValue(group, "bpm_tap", false); - } + + if (deck.shiftKey) { + parameterSoftTakeOver("[EffectRack1_EffectUnit1_Effect1]", "parameter" + FXp, value); + } + if (deck.PADMode) { + parameterSoftTakeOver("[EffectRack1_EffectUnit2_Effect1]", "parameter" + FXp, value); + } + if (deck.TapDown) { + parameterSoftTakeOver("[EffectRack1_EffectUnit3_Effect1]", "parameter" + FXp, value); + } + } }; -// ************************ Connected controls -NumarkMixtrack3.OnVuMeterChange = function(value, group, control) { +NumarkMixtrack3.FilterKnob = function(channel, control, value, status, group) { + var decknum = group.substring(26, 27); + decknum = NumarkMixtrack3.deckFromGroup("[Channel" + decknum + "]"); + var deck = NumarkMixtrack3.decks["D" + decknum]; + + if (!deck.shiftKey && !deck.PADMode && !deck.TapDown) { + parameterSoftTakeOver("[QuickEffectRack1_[Channel" + decknum + "]]", "super1", value); + } + + if (FXmode === 1) { + if (deck.shiftKey) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect1]", "parameter4", value); + } + if (deck.PADMode) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect2]", "parameter4", value); + } + if (deck.TapDown) { + parameterSoftTakeOver("[EffectRack1_EffectUnit" + decknum + + "_Effect3]", "parameter4", value); + } + } else { + if (deck.shiftKey) { + parameterSoftTakeOver("[EffectRack1_EffectUnit1_Effect1]", "parameter4", value); + } + if (deck.PADMode) { + parameterSoftTakeOver("[EffectRack1_EffectUnit2_Effect1]", "parameter4", value); + } + if (deck.TapDown) { + parameterSoftTakeOver("[EffectRack1_EffectUnit3_Effect1]", "parameter4", value); + } + } +}; + +NumarkMixtrack3.loop_in = function(channel, control, value, status, group) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + + if (value === DOWN) { + engine.setValue("[Channel" + decknum + "]", "loop_in", value ? 1 : 0); + } +}; + +NumarkMixtrack3.loop_out = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); + + if (value === DOWN) { + engine.setValue("[Channel" + decknum + "]", "loop_out", value ? 1 : 0); + } +}; + +NumarkMixtrack3.reloop_exit = function(channel, control, value, status, group) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + + if (value === DOWN) { + engine.setValue("[Channel" + decknum + "]", "reloop_exit", value ? 1 : 0); + } +}; + +NumarkMixtrack3.LoopHalveButton = function(channel, control, value, status, + group) { + if (value === DOWN) { + var decknum = NumarkMixtrack3.deckFromGroup(group); + var deck = NumarkMixtrack3.decks["D" + decknum]; + + if (deck.shiftKey) { + engine.setValue("[Channel" + decknum + "]", "loop_double", true); + } else { + engine.setValue("[Channel" + decknum + "]", "loop_halve", true); + } + } +}; + +NumarkMixtrack3.OnLoopInOutChange = function(value, group, control) { + var decknum = script.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - deck.LEDs.meter.onOff(120*value); + var valIn = engine.getValue("[Channel" + decknum + "]", "loop_start_position"); + var valOut = engine.getValue("[Channel" + decknum + "]", "loop_end_position"); + var valEnabled = engine.getValue("[Channel" + decknum + "]", "loop_enabled"); + + if (valIn == -1) { + if (deck.LEDs.loopin.getFlashDuration() !== 300) { + deck.LEDs.loopin.flashOn(300, PADcolors.blue, 300); + } + deck.LEDs.loopout.onOff(OFF); + deck.LEDs.reloop_exit.onOff(OFF); + deck.LEDs.loop_halve.onOff(OFF); + + } else if (valOut == -1 && deck.loaded) { + deck.LEDs.loopin.onOff(PADcolors.blue); + if (deck.LEDs.loopout.getFlashDuration() !== 300) { + deck.LEDs.loopout.flashOn(300, PADcolors.blue, 300); + } + deck.LEDs.reloop_exit.onOff(OFF); + deck.LEDs.loop_halve.onOff(OFF); + + } else if (!valEnabled) { + deck.LEDs.loopin.onOff(PADcolors.blue); + deck.LEDs.loopout.onOff(PADcolors.blue); + if (deck.LEDs.reloop_exit.getFlashDuration() !== 300) { + deck.LEDs.reloop_exit.flashOn(300, PADcolors.blue, 300); + } + deck.LEDs.loop_halve.onOff(PADcolors.blue); + + } else { + deck.LEDs.loopin.onOff(PADcolors.blue); + deck.LEDs.loopout.onOff(PADcolors.blue); + deck.LEDs.reloop_exit.onOff(PADcolors.blue); + deck.LEDs.loop_halve.onOff(PADcolors.blue); + } }; -NumarkMixtrack3.OnPlaypositionChange = function(value, group, control) { +NumarkMixtrack3.volume = function(channel, control, value, status, group) { var decknum = NumarkMixtrack3.deckFromGroup(group); + + engine.setValue("[Channel" + decknum + "]", "volume", value / 127); +}; + +NumarkMixtrack3.OnVolumeChange = function(value, group, control) { + var decknum = parseInt(group.substring(8, 9)); + var deck = NumarkMixtrack3.decks["D" + decknum]; + var delta = value - deck.lastfadervalue; + + if (deck.faderstart) { + if (value <= 0.01 && deck.isplaying) { + engine.setValue(group, "play", 0); + deck.isplaying = false; + } else { + if (delta > 0 && !deck.isplaying) { + engine.setValue(group, "play", 1); + deck.isplaying = true; + } + } + } + deck.lastfadervalue = value; +}; + +NumarkMixtrack3.OnVuMeterChange = function(value, group, control) { + var decknum = parseInt(group.substring(8, 9)); + var deck = NumarkMixtrack3.decks["D" + decknum]; + deck.LEDs.meter.onOff(120 * value); +}; + +NumarkMixtrack3.OnPlaypositionChange = function(value, group, control) { + + var decknum = script.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; if (deck.loaded) { @@ -2147,11 +2667,13 @@ NumarkMixtrack3.OnPlaypositionChange = function(value, group, control) { switch (trackwarning) { case 0: - deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? ON : OFF); + deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? + ON : OFF); break; case 1: // if less than 30 seconds before end of track : flashing slowly - if (deck.LEDs.jogWheelsInScratchMode.getFlashDuration() !== 1000) { + if (deck.LEDs.jogWheelsInScratchMode.getFlashDuration() !== + 1000) { deck.LEDs.jogWheelsInScratchMode.flashOn(1000, ON, 1000); } break; @@ -2163,40 +2685,35 @@ NumarkMixtrack3.OnPlaypositionChange = function(value, group, control) { break; case 3: // end of strack : full ring lit - deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? ON : OFF); + deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? + ON : OFF); break; default: break; } } else { - deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? ON : OFF); + deck.LEDs.jogWheelsInScratchMode.onOff(deck.jogWheelsInScratchMode ? + ON : OFF); } }; -NumarkMixtrack3.OnHotcueChange = function(value, group, control, padindex) { - var decknum = parseInt(group.substring(8,9)); - var deck = NumarkMixtrack3.decks["D" + decknum]; - deck.LEDs["hotCue" + padindex].onOff((value) ? ON : OFF); -}; - NumarkMixtrack3.OnTrackLoaded = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); + var decknum = parseInt(group.substring(8, 9)); var deck = NumarkMixtrack3.decks["D" + decknum]; - - if (value!==0) { - if ( !deck.faderstart ) { + + if (value !== 0) { + if (!deck.faderstart) { // Light up the PFL light indicating that a track is loaded deck.LEDs["headphones"].onOff(ON); } else { // Flash up the PFL light button indicating that a track is loaded with fader start - deck.LEDs["headphones"].flashOn(300,ON,300); - + deck.LEDs["headphones"].flashOn(300, ON, 300); } } else { // Switch off the PFL light indicating that a track is ejected - deck.LEDs["headphones"].onOff(OFF); + deck.LEDs["headphones"].onOff(OFF); } - + var oldloaded = deck.loaded; deck.loaded = (value !== 0); if (oldloaded !== deck.loaded) { // if this value changed we update the jog light @@ -2204,151 +2721,9 @@ NumarkMixtrack3.OnTrackLoaded = function(value, group, control) { } }; -NumarkMixtrack3.OnVolumeChange = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); - var deck = NumarkMixtrack3.decks["D" + decknum]; - var delta = value - deck.lastfadervalue; - - if (deck.faderstart) { - if (value<=0.01) { - engine.setValue(group, "play", 0); - } else { - if (delta>0) { - engine.setValue(group, "play", 1); - } - } - } - deck.lastfadervalue = value; -}; - -NumarkMixtrack3.OnPFLStatusChange = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); - var deck = NumarkMixtrack3.decks["D" + decknum]; - deck.LEDs.headphones.onOff((value) ? ON : OFF); -}; - NumarkMixtrack3.OnPlayIndicatorChange = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); - var deck = NumarkMixtrack3.decks["D" + decknum]; - deck.LEDs.play.onOff((value) ? ON : OFF); -}; - -NumarkMixtrack3.OnBeatActive = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); + var decknum = script.deckFromGroup(group); var deck = NumarkMixtrack3.decks["D" + decknum]; - if (!deck.shiftKey && OnBeatActiveFlash) { - deck.LEDs.tap.onOff((value) ? ON : OFF); - } -}; - -NumarkMixtrack3.OnCuePointChange = function(value, group, control) { - var decknum = parseInt(group.substring(8,9)); - var deck = NumarkMixtrack3.decks["D" + decknum]; - deck.LEDs.Cue.onOff((value) ? ON : OFF); -}; - -NumarkMixtrack3.OnLoopInOutChange = function(value, group, key) { - var decknum = NumarkMixtrack3.deckFromGroup(group); - var deck = NumarkMixtrack3.decks["D" + decknum]; - var valIn = engine.getValue(group, "loop_start_position"); - var valOut = engine.getValue(group, "loop_end_position"); - var valEnabled = engine.getValue(group, "loop_enabled"); - - if (valIn==-1) { - if (deck.LEDs.loopin.getFlashDuration()!==300) { - deck.LEDs.loopin.flashOn(300,PADcolors.blue,300); - } - deck.LEDs.loopout.onOff(OFF); - deck.LEDs.reloop_exit.onOff(OFF); - deck.LEDs.loop_halve.onOff(OFF); - } else if (valOut==-1) { - deck.LEDs.loopin.onOff(PADcolors.blue); - if (deck.LEDs.loopout.getFlashDuration()!==300) { - deck.LEDs.loopout.flashOn(300,PADcolors.blue,300); - } - deck.LEDs.reloop_exit.onOff(OFF); - deck.LEDs.loop_halve.onOff(OFF); - } else if (!valEnabled) { - deck.LEDs.loopin.onOff(PADcolors.blue); - deck.LEDs.loopout.onOff(PADcolors.blue); - if (deck.LEDs.reloop_exit.getFlashDuration()!==300) { - deck.LEDs.reloop_exit.flashOn(300,PADcolors.blue,300); - } - deck.LEDs.loop_halve.onOff(PADcolors.blue); - } else { - deck.LEDs.loopin.onOff(PADcolors.blue); - deck.LEDs.loopout.onOff(PADcolors.blue); - deck.LEDs.reloop_exit.onOff(PADcolors.blue); - deck.LEDs.loop_halve.onOff(PADcolors.blue); - } -}; -NumarkMixtrack3.OnEffectLoaded = function(value, group, control, index) { - var i; - var parameterlinkedcount = 0; - var linktype = 0; - if (value) { - var numparams = engine.getValue("[EffectRack1_EffectUnit" + index + "_Effect1]", "num_parameters"); - if (numparams > 0) { - for (i = 1; i <= numparams; i++) { - linktype = engine.getValue("[EffectRack1_EffectUnit" + index + "_Effect1]", "parameter" + i + "_link_type"); - if (linktype !== 0) { - parameterlinkedcount += 1; - } - } - } - if (parameterlinkedcount === 0) { - for (i = 1; i <= numparams; i++) { - engine.setValue("[EffectRack1_EffectUnit" + index + "_Effect1]", "parameter" + i + "_link_type", 1); - } - } - } -}; - -NumarkMixtrack3.OnSamplePlayStop = function(value, group, control) { - var decknum = NumarkMixtrack3.deckFromGroup(group); - var deck = NumarkMixtrack3.decks["D" + decknum]; - - if (value === 1) { - deck.LEDs["PADsampler" + decknum].flashOn(300, PADcolors.purple, 300); - } else { - deck.LEDs["PADsampler" + decknum].onOff(ON); - } -}; - -NumarkMixtrack3.OnPADLoopButtonChange = function(value, group, control) { - var loopsize = [0.125, 0.25, 0.5, 1, 2, 4, 8, 16]; - var decknum = NumarkMixtrack3.deckFromGroup(group); - var deck = NumarkMixtrack3.decks["D" + decknum]; - var l; - var index; - - if (value === 1) { - for (l=0;l4) { - index = index - 4; - } - - deck.LEDs["PADloop" + index].flashOn(300, PADcolors.yellow, 300); - - } - } - } else { - - for (l=0;l4) { - index = index - 4; - } - - deck.LEDs["PADloop"+ index].onOff(PADcolors.yellow); - } - } - } - -}; + deck.LEDs.play.onOff((value) ? ON : OFF); +}; \ No newline at end of file diff --git a/res/controllers/Numark-Mixtrack-3.midi.xml b/res/controllers/Numark-Mixtrack-3.midi.xml index 5bd526bcef39..4cae84e95914 100644 --- a/res/controllers/Numark-Mixtrack-3.midi.xml +++ b/res/controllers/Numark-Mixtrack-3.midi.xml @@ -1,16 +1,16 @@ - + - Numark Mixtrack (Pro) 3 - Stéphane Morin - The Numark Mixtrack 3 and Numark Mixtrack Pro 3 are the same controller except that the Pro version has an integrated sound card. + Numark Mixtrack (Pro) 3 + Stéphane Morin + The Numark Mixtrack 3 and Numark Mixtrack Pro 3 are the same controller except that the Pro version has an integrated sound card. http://mixxx.org/forums/viewtopic.php?f=7&t=7286 http://www.mixxx.org/wiki/doku.php/numark_mixtrack_pro_3 - + @@ -20,27 +20,27 @@ 0xB0 0x07 - + [Channel1] - volume + NumarkMixtrack3.volume Channel 1 line fader 0xB1 0x05 - + [Channel2] - volume + NumarkMixtrack3.volume Channel 2 line fader 0xB2 0x05 - + @@ -113,7 +113,7 @@ - + [Channel1] NumarkMixtrack3.PadModeButton Channel 1 Pad Mode button @@ -153,7 +153,7 @@ - + [Channel1] NumarkMixtrack3.FXButton Channel 1 FX 1 button @@ -173,7 +173,7 @@ - + [Channel1] NumarkMixtrack3.FXButton Channel 1 FX 2 button @@ -193,7 +193,7 @@ - + [Channel1] NumarkMixtrack3.FXButton Channel 1 FX 3 button @@ -315,142 +315,142 @@ [Channel1] - filterLow + NumarkMixtrack3.EQKnob Channel 1 low EQ knob 0xB1 0x03 - + [Channel2] - filterLow + NumarkMixtrack3.EQKnob Channel 2 low EQ knob 0xB2 0x03 - + - + [Channel1] - filterMid + NumarkMixtrack3.EQKnob Channel 1 mid EQ knob 0xB1 0x02 - + [Channel2] - filterMid + NumarkMixtrack3.EQKnob Channel 2 mid EQ knob 0xB2 0x02 - + [Channel1] - filterHigh + NumarkMixtrack3.EQKnob Channel 1 high EQ knob 0xB1 0x01 - + [Channel2] - filterHigh + NumarkMixtrack3.EQKnob Channel 2 high EQ knob 0xB2 0x01 - + [QuickEffectRack1_[Channel1]] - super1 + NumarkMixtrack3.FilterKnob Channel 1 filter knob 0xB1 0x04 - + [QuickEffectRack1_[Channel2]] - super1 + NumarkMixtrack3.FilterKnob Channel 2 filter knob 0xB2 0x04 - + [Channel1] - loop_in + NumarkMixtrack3.loop_in Channel 1 loop in button 0x91 0x13 - + [Channel2] - loop_in + NumarkMixtrack3.loop_in Channel 1 loop in button 0x92 0x13 - + [Channel1] - loop_out + NumarkMixtrack3.loop_out Channel 1 loop out button 0x91 0x14 - + [Channel2] - loop_out + NumarkMixtrack3.loop_out Channel 2 loop out button 0x92 0x14 - + [Channel1] - reloop_exit + NumarkMixtrack3.reloop_exit Channel 1 loop on/off button 0x91 0x15 - + [Channel2] - reloop_exit + NumarkMixtrack3.reloop_exit Channel 2 loop on/off button 0x92 0x15 - + @@ -473,7 +473,7 @@ - + [Channel1] NumarkMixtrack3.PADLoopButton Channel 1 PAD loop button 1 @@ -713,7 +713,7 @@ - + [Channel1] NumarkMixtrack3.PitchFaderLowValue Channel 1 pitch fader precision bits @@ -732,7 +732,7 @@ - + [Channel1] NumarkMixtrack3.PitchBendPlusButton @@ -784,7 +784,7 @@ - [Sampler1] + [Sampler5] NumarkMixtrack3.SamplerButton Channel 2 sampler 1 button 0x92 @@ -804,7 +804,7 @@ - [Sampler2] + [Sampler6] NumarkMixtrack3.SamplerButton Channel 2 sampler 2 button 0x92 @@ -824,7 +824,7 @@ - [Sampler3] + [Sampler7] NumarkMixtrack3.SamplerButton Channel 2 sampler 3 button 0x92 @@ -844,7 +844,7 @@ - [Sampler4] + [Sampler8] NumarkMixtrack3.SamplerButton Channel 2 sampler 4 button 0x92 @@ -853,10 +853,10 @@ - + [Channel1] NumarkMixtrack3.StripTouchEffect - Channel 1 strip + Channel 1 strip 0xB1 0x1A @@ -866,7 +866,7 @@ [Channel2] NumarkMixtrack3.StripTouchEffect - Channel 2 strip + Channel 2 strip 0xB2 0x1A @@ -875,8 +875,8 @@ [Channel1] - NumarkMixtrack3.StripTouchSearch - Channel 1 SHIFT+strip + NumarkMixtrack3.StripTouchEffect + Channel 1 SHIFT+strip 0xB1 0x1B @@ -885,15 +885,35 @@ [Channel2] - NumarkMixtrack3.StripTouchSearch - Channel 2 SHIFT+strip + NumarkMixtrack3.StripTouchEffect + Channel 2 SHIFT+strip 0xB2 0x1B - + + [Channel1] + NumarkMixtrack3.InstantFXOff + Channel 1 strip Instant FX Off + 0x91 + 0x1F + + + + + + [Channel2] + NumarkMixtrack3.InstantFXOff + Channel 2 strip Instant FX Off + 0x92 + 0x1F + + + + + [Channel1] NumarkMixtrack3.BeatKnob Channel 1 FX 3 Knob @@ -912,8 +932,8 @@ - + - + - + \ No newline at end of file