diff --git a/res/controllers/Hercules_DJControl_Jogvision-scripts.js b/res/controllers/Hercules_DJControl_Jogvision-scripts.js new file mode 100644 index 00000000000..76c93006018 --- /dev/null +++ b/res/controllers/Hercules_DJControl_Jogvision-scripts.js @@ -0,0 +1,422 @@ +// **************************************************************************** +// * Mixxx mapping script file for the Hercules DJControl Jogvision. +// * Author: DJ Phatso, contributions by Kerrick Staley and David TV +// * Version 1.16 (Jun 2020) +// * Version 1.15 (Jun 2020) +// * Version 1.14 (Jun 2020) +// * Version 1.13 (May 2020) +// * Version 1.11 (May 2020) +// * Version 1.10 (May 2020) +// * Version 1.9 (May 2020) +// * Version 1.8 (May 2020) +// * Version 1.6 (January 2020) +// * Version 1.5 (January 2020) +// * Version 1.4 (December 2019) +// * Version 1.3 (November 2019) +// * Version 1.2 (November 2019) +// * Version 1.1 (March 2019) +// * Forum: https://www.mixxx.org/forums/viewtopic.php?f=7&t=12580 +// * Wiki: https://www.mixxx.org/wiki/doku.php/hercules_dj_control_jogvision +// +// Changes to v1.16 +// - Added a "beatDetection" variable to use old school one (way better beat match, but no song position relative) +// +// Changes to v1.15 +// - Reset shift-"Loop ON", to do what Hercules wanted it to be: select FX2 for given channel. Now, +// the loop creation is done with "MODE"+"Loop ON" combo (here, MODE key works like "SHIFT" key ;) +// +// Changes to v1.14 +// - Better beat_active matching +// +// Changes to v1.13 +// - Added "shift"+AIRFX to do a high pass (apart from the default low pass) +// - Added shift+ to set beatgrid at current play position +// +// Changes to v1.12 +// - Added "alternate" beat leds mode +// - Changed "follow" beats led algorithm with a better/more elegant version +// +// Changes to v1.11 +// - Changed beats led algorithm to match song beats (forward and backward) and fix leads positions, +// what allows backward led activation!! (didn't have that working previously) +// +// Changes to v1.10 +// - Changed jogwheel outer led movement based on playposition (much better!) +// - Added a user variable to set or not some effects at ini +// - Minor code convention corrections +// +// Changes to v1.9 +// - Added jogwheel outer led movement when scratch and back/forward spin +// +// Changes to v1.8 +// - Added normal, reverse, blink and follow modes for beat active led (see variable: beatActiveMode) +// +// Changes to v1.7 +// - Added back-spin (and forward-spin) effect on "vinyl" mode when jog wheel pushed from top +// +// Changes to v1.6 +// - Minor code-style changes (use camelCase, use "double quotes" and other if/else styles) +// +// Changes to v1.5 +// - Fixed regression not updating the VuMeters +// - Fixed regression not updating the CUE/MIX buttons +// +// Changes to v1.4 +// - Code cleanup and standarization +// - Added "orage" track led color (ala Serato) when play position is beyond the +// part of the track, but before the "end of track" Mixxx signal +// +// Changes to v1.3 +// - Enabled the creation of beatloop (beatloopActivate) by using SHIFT+LoopON +// - Changed "LOOP SIZE" to adjust the beatjumpSize (you still can change size +// with surrounding buttons: reloop_toggle key) +// - Added SHIFT+"LOOP SIZE" to move loop left or right by N beats (beatjump) +// +// Changes to v1.2 +// - Enabled Jogwheel Outer LED rotation +// - Enabled Beat LEDs +// +// Changes to v1.1 +// - Controller knob/slider values are queried on startup, so MIXXX is synced. +// - Fixed vinyl button behavior the first time it"s pressed. +// +// v1.0 : Original release +// +// **************************************************************************** + +// **************************************************************************** +// User available variables (you may modify them) +var beatActiveMode = "normal"; // normal (default), reverse, blink, follow, alternate +var beatDetection = "normal"; // normal (default), follow (song position accurate, beat much less accurate) +var initUpdateEffects = 1; // 1 (default) - set some effects values at startup; 0 - do not touch effects at startup + +// **************************************************************************** +// Other internal constants (you may NOT modify anything from here) +var on = 0x7F; +var off = 0x00; +var alpha = 1.0 / 8; +var beta = alpha / 16; +var speed = 33 + 1/3; +var ledSpeed = (speed / 60) * 127; +var masterLeds = 0x90; +var ledRotationTimer = 0; +var beatMax; +if (beatActiveMode.match(/^(?:normal|reverse)$/g)) { + beatMax = 4; +} else if (beatActiveMode.match(/^(?:blink|alternate)$/g)) { + beatMax = 2; +} else { + beatMax = 8; +} + +var DJCJV = {}; +DJCJV.vinylModeActive = true; +DJCJV.Channel = []; +DJCJV.Channel["[Channel1]"] = {"central": 0x90, "deck": 0xB0, "beatPosition": 1, "rotation": 0x00, "n": 1, "onBeat": 0, "beatsPassed": 0, "shiftPressed": 0, "modePressed": 0}; +DJCJV.Channel["[Channel2]"] = {"central": 0x91, "deck": 0xB1, "beatPosition": 1, "rotation": 0x00, "n": 2, "onBeat": 0, "beatsPassed": 0, "shiftPressed": 0, "modePressed": 0}; + +// **************************************************************************** +// General functions + +// Function to rotate jogs' outer led (borrowed from the 'Pioneer-DDJ-SX-scripts.js' mapping) +DJCJV.updateJogLeds = function(value, group, control) { + var elapsedTime = value * engine.getValue(group, "duration"); + var wheelPos = parseInt(((value >= 0) ? 0 : 127) + 1 + ((ledSpeed * elapsedTime) % 127)); + + // Only send midi message when the position is actually updated. + if (DJCJV.Channel[group].rotation !== wheelPos) { + midi.sendShortMsg(DJCJV.Channel[group].deck, 0x60, wheelPos); // Update the outer (spin) jog leds + DJCJV.wheelInnerUpdate(value, group, control); // Also update the inner jog leds with updated song position + } + DJCJV.Channel[group].rotation = wheelPos; + + DJCJV.Channel[group].beatsPassed = Math.round((value * engine.getValue(group, "duration")) * (engine.getValue(group, "bpm") / 60)); + DJCJV.Channel[group].beatPosition = Math.floor((DJCJV.Channel[group].beatsPassed % beatMax)) + 1; + + if (beatDetection === "follow") { + // If on beat_active, update the beat leds + if (engine.getValue(group, "beat_active") || ((engine.getValue(group, "beat_closest") < engine.getValue(group, "beat_next"))) && (!DJCJV.Channel[group].onBeat)) { + DJCJV.beatActive(0, group); + DJCJV.Channel[group].onBeat = true; + } else if (engine.getValue(group, "beat_closest") >= engine.getValue(group, "beat_next")) { + DJCJV.Channel[group].onBeat = false; + } + } +}; + +// Initialization +DJCJV.init = function(id) { + + print("Hercules DJControl Jogvision id: \""+id+"\" initializing..."); + print("Using beatActiveMode="+beatActiveMode+" (beatMax="+beatMax+")"); + + // Set all LED states to off + midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x7F, off); + midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x7F, off); + + // Set Vinyl button LED On. + midi.sendShortMsg(masterLeds, 0x45, on); + DJCJV.vinylModeActive = true; + midi.sendShortMsg(masterLeds, 0x46, on); + + // Set Headphone CUE/MIX LED state + if (engine.getValue("[Master]", "headMix") > 0.5) { + midi.sendShortMsg(masterLeds, 0x4C, on); // headset "Mix" button LED + midi.sendShortMsg(masterLeds, 0x4D, off); + } else { + midi.sendShortMsg(masterLeds, 0x4C, off); + midi.sendShortMsg(masterLeds, 0x4D, on); // headset "Cue" button LED + } + + // Enable Soft takeover + engine.softTakeover("[Master]", "crossfader", true); + engine.softTakeover("[QuickEffectRack1_[Channel1]]", "super1", true); + engine.softTakeover("[QuickEffectRack1_[Channel2]]", "super1", true); + + if (initUpdateEffects === 1) { + // Set effects Levels - Dry/Wet - Filters + // Done to work around the limited amount of controls in the Jogvision controller + engine.setParameter("[EffectRack1_EffectUnit1_Effect1]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit1_Effect2]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit1_Effect3]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit2_Effect1]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit2_Effect2]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit2_Effect3]", "meta", 0.6); + engine.setParameter("[EffectRack1_EffectUnit1]", "mix", 0.6); + engine.setParameter("[EffectRack1_EffectUnit2]", "mix", 0.6); + engine.setParameter("[QuickEffectRack1_[Channel1]]", "super1", 0.5); + engine.setParameter("[QuickEffectRack1_[Channel2]]", "super1", 0.5); + } + + // Connect the VUMeters + engine.connectControl("[Channel1]", "VuMeter", "DJCJV.vuMeterUpdate"); + engine.connectControl("[Channel2]", "VuMeter", "DJCJV.vuMeterUpdate"); + + // Set inner jog leds to 0 + midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x61, 0); + midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x61, 0); + // Set outer jog leds to 0 + midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x60, 1); + midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x60, 1); + + // Enable jogs' outer leds rotation and Inner LEDs song position update + engine.connectControl("[Channel1]", "playposition", "DJCJV.updateJogLeds"); + engine.connectControl("[Channel2]", "playposition", "DJCJV.updateJogLeds"); + if (beatDetection === "normal") { + // Connect the beat_active with beat leds + engine.connectControl("[Channel1]", "beat_active", "DJCJV.beatActive"); + engine.connectControl("[Channel2]", "beat_active", "DJCJV.beatActive"); + engine.connectControl("[Channel1]", "stop", "DJCJV.beatInactive"); + engine.connectControl("[Channel2]", "stop", "DJCJV.beatInactive"); + } + + // Ask the controller to send all current knob/slider values over MIDI, which will update the corresponding GUI controls in MIXXX. + midi.sendShortMsg(0xB0, 0x7F, on); + + print("Hercules DJControl Jogvision id: \""+id+"\" initialized"); +}; + +// Finalization +DJCJV.shutdown = function() { + if (ledRotationTimer) { + engine.stopTimer(ledRotationTimer); + ledRotationTimer = 0; + } + // Set all LED states to off + midi.sendShortMsg(DJCJV.Channel["[Channel1]"].deck, 0x7F, off); + midi.sendShortMsg(DJCJV.Channel["[Channel2]"].deck, 0x7F, off); +}; + +// Beat led ACTIVATE (move) +DJCJV.beatActive = function(value, group, _control) { + if (value === 1) { + return; + } + var led = DJCJV.Channel[group].central; + var pos = DJCJV.Channel[group].beatPosition; + + // Normal + if (beatActiveMode === "normal") { + midi.sendShortMsg(led, 0x3A, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3B, pos === 2 ? on : off); + midi.sendShortMsg(led, 0x3C, pos === 3 ? on : off); + midi.sendShortMsg(led, 0x3D, pos === 4 ? on : off); + // Reverse + } else if (beatActiveMode === "reverse") { + midi.sendShortMsg(led, 0x3A, pos !== 1 ? on : off); + midi.sendShortMsg(led, 0x3B, pos !== 2 ? on : off); + midi.sendShortMsg(led, 0x3C, pos !== 3 ? on : off); + midi.sendShortMsg(led, 0x3D, pos !== 4 ? on : off); + // Reverse + } else if (beatActiveMode === "blink") { + midi.sendShortMsg(led, 0x3A, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3B, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3C, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3D, pos === 1 ? on : off); + // Follow + } else if (beatActiveMode === "follow") { + midi.sendShortMsg(led, 0x3A, ((pos >= 1) && (pos <= 4)) ? on : off); + midi.sendShortMsg(led, 0x3B, ((pos >= 2) && (pos <= 5)) ? on : off); + midi.sendShortMsg(led, 0x3C, ((pos >= 3) && (pos <= 6)) ? on : off); + midi.sendShortMsg(led, 0x3D, ((pos >= 4) && (pos <= 7)) ? on : off); + // Alternate + } else if (beatActiveMode === "alternate") { + midi.sendShortMsg(led, 0x3A, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3B, pos === 1 ? on : off); + midi.sendShortMsg(led, 0x3C, pos === 2 ? on : off); + midi.sendShortMsg(led, 0x3D, pos === 2 ? on : off); + } +}; +// Beat led DEACTIVATE (off all) +DJCJV.beatInactive = function(value, group, _control) { + midi.sendShortMsg(DJCJV.Channel[group].central, 0x3A, off); + midi.sendShortMsg(DJCJV.Channel[group].central, 0x3B, off); + midi.sendShortMsg(DJCJV.Channel[group].central, 0x3C, off); + midi.sendShortMsg(DJCJV.Channel[group].central, 0x3D, off); + + DJCJV.Channel[group].beatPosition = 1; +}; + +// Jogwheels inner LED display - Play position +DJCJV.wheelInnerUpdate = function(value, group, _control) { + var playPos = value * 127; + midi.sendShortMsg(DJCJV.Channel[group].deck, 0x61, playPos); + + // Also update the "track" led information + if (engine.getValue(group, "end_of_track")) { + // Let Mixxx"s engine turn flashing red automatically + return; + } else if (playPos > 64) { + // Turn "track" led to orange if position is beyond the half + midi.sendShortMsg(DJCJV.Channel[group].central, 0x45, 0x02); + } else { + // Turn "track" led to green if position is in the first half + midi.sendShortMsg(DJCJV.Channel[group].central, 0x45, 0x07); + } +}; + +// Vu Meter +DJCJV.vuMeterUpdate = function(value, group, _control) { + midi.sendShortMsg(DJCJV.Channel[group].central, 0x44, value * 6); +}; + +// Headphone CUE/MIX buttons status +DJCJV.headCue = function(midino, control, value, status, group) { + if (engine.getValue(group, "headMix") === 0) { + engine.setValue(group, "headMix", -1.0); + midi.sendShortMsg(masterLeds, 0x4D, 0x7f); + midi.sendShortMsg(masterLeds, 0x4C, 0x00); + } +}; +DJCJV.headMix = function(midino, control, value, status, group) { + if (engine.getValue(group, "headMix") !== 1) { + engine.setValue(group, "headMix", 0); + midi.sendShortMsg(masterLeds, 0x4D, 0x00); + midi.sendShortMsg(masterLeds, 0x4C, 0x7f); + } +}; + +// Filter (AIR FX) +DJCJV.Filter = function(channel, control, value, status, group) { + var deck = group.substr(18, 10); + var delta = DJCJV.Channel[deck].shiftPressed ? (value / 255) : (-1 * (value / 255)); + engine.setValue(group, "super1", 0.5 + delta); +}; + +// Sniff decks' SHIFT presses and store them +DJCJV.shiftKey = function(channel, control, value, status, group) { + DJCJV.Channel[group].shiftPressed = (value === 127); + return value; +}; + +// Sniff decks' MODE presses and store them +DJCJV.modeKey = function(channel, control, value, status, group) { + DJCJV.Channel[group].modePressed = (value === 127); + return value; +}; + +// Loop section +// SHIFT + Loop ON creates a loop at given point +DJCJV.beatloopActivate = function(channel, control, value, status, group) { + if (!DJCJV.Channel[group].modePressed) { + return value; + } + engine.setValue(group, "beatloop_activate", (value !== 0)); +}; + +// SHIFT+FX(Loop) Knob MOVES the existing loop one beat forward/backward +DJCJV.beatjumpMove = function(channel, control, value, status, group) { + if (value > 64) { + engine.setValue(group, "beatjump_backward", 1); + engine.setValue(group, "beatjump_backward", 0); + } else { + engine.setValue(group, "beatjump_forward", 1); + engine.setValue(group, "beatjump_forward", 0); + } +}; +// FX(Loop) Knob changes the AMOUNT of beats to move the loop when requested +DJCJV.beatjumpSize = function(channel, control, value, status, group) { + var currentValue = engine.getValue(group, "beatjump_size"); + if (value > 64) { + engine.setValue(group, "beatjump_size", currentValue /= 2); + } else { + engine.setValue(group, "beatjump_size", currentValue *= 2); + } +}; + +// The Vinyl button, used to enable or disable scratching on the jog wheels. +DJCJV.vinylButton = function(channel, control, value, _status, _group) { + if (!value) { + return; + } + + if (DJCJV.vinylModeActive) { + DJCJV.vinylModeActive = false; + midi.sendShortMsg(masterLeds, 0x46, off); + } else { + DJCJV.vinylModeActive = true; + midi.sendShortMsg(masterLeds, 0x46, on); + } +}; + +// The pressure action over the jog wheel +DJCJV.wheelTouch = function(channel, control, value, status, group) { + if (value > 0 && (engine.getValue(group, "play") !== 1 || DJCJV.vinylModeActive)) { + engine.scratchEnable(DJCJV.Channel[group].n, 400, speed, alpha, beta); // Touching the wheel + } else { + engine.scratchDisable(DJCJV.Channel[group].n); // Released the wheel + } +}; + +// Using the top of wheel for scratching (Vinyl button On) and bending (Vinyl button Off) +DJCJV.scratchWheel = function(channel, control, value, status, group) { + if (engine.isScratching(DJCJV.Channel[group].n)) { + // Scratch! + if (value >= 64) { + // Backward + engine.scratchTick(DJCJV.Channel[group].n, value - 128); + } else { + // Forward + engine.scratchTick(DJCJV.Channel[group].n, value); + } + } else { + // Pitch bend + DJCJV.bendWheel(channel, control, value, status, group); + } +}; + +// Bending by either using the side of wheel, or with the Job surface when not in vinyl-mode +DJCJV.bendWheel = function(channel, control, value, status, group) { + // if scratching engaged, do back/forward spin (keep on scratching while jog wheel moves...) + if (engine.isScratching(DJCJV.Channel[group].n)) { + if (value >= 64) { + // Backward spin + engine.scratchTick(DJCJV.Channel[group].n, -1.5); + } else { + // Forward spin + engine.scratchTick(DJCJV.Channel[group].n, 1.5); + } + } else { + engine.setValue(group, "jog", (value >= 64) ? value - 128 : value); // Pitch bend + } +}; diff --git a/res/controllers/Hercules_DJControl_Jogvision.midi.xml b/res/controllers/Hercules_DJControl_Jogvision.midi.xml new file mode 100644 index 00000000000..fe123421f95 --- /dev/null +++ b/res/controllers/Hercules_DJControl_Jogvision.midi.xml @@ -0,0 +1,2181 @@ + + + + Hercules DJControl Jogvision + DJ Phatso for Hercules Technical Support + MIDI Mapping for Hercules DJControl Jogvision + https://www.mixxx.org/forums/viewtopic.php?f=7&t=12580 + https://www.mixxx.org/wiki/doku.php/hercules_dj_control_jogvision + + + + + + + + + + [Channel1] + DJCJV.modeKey + Deck A MODE key management + 0x90 + 0x57 + + + + + + [Channel2] + DJCJV.modeKey + Deck B MODE key management + 0x91 + 0x57 + + + + + + [Channel1] + DJCJV.shiftKey + Deck A Shift key management + 0x90 + 0x56 + + + + + + [Channel2] + DJCJV.shiftKey + Deck B Shift key management + 0x91 + 0x56 + + + + + + + + [Channel1] + play + Play button + 0x90 + 0x32 + + + + + + [Channel1] + play_stutter + SHIFT + Play: Play Stutter + 0x90 + 0x37 + + + + + + + [Channel1] + cue_default + Cue button + 0x90 + 0x31 + + + + + + [Channel1] + start_play + SHIFT + Cue: REWIND to beginning + 0x90 + 0x36 + + + + + + + [Channel1] + sync_enabled + Sync button + 0x90 + 0x30 + + + + + + [Channel1] + sync_master + SHIFT + Sync: Sync Master + 0x90 + 0x35 + + + + + + + [Channel1] + pfl + PFL button + 0x90 + 0x33 + + + + + + [Master] + DJCJV.headCue + Headphone CUE button + 0x90 + 0x4D + + + + + + [Master] + DJCJV.headMix + Headphone MIX button + 0x90 + 0x4C + + + + + + + [Channel1] + LoadSelectedTrack + LOAD A button + 0x90 + 0x51 + + + + + + + [Channel1] + keylock + keylock button + 0x90 + 0x34 + + + + + + + [Channel1] + slip_enabled + SLIP button + 0x90 + 0x39 + + + + + + + [Channel1] + DJCJV.wheelTouch + Jog Wheel Touch Deck A + 0x90 + 0x55 + + + + + + + [Channel1] + loop_halve + Loop Half + 0x90 + 0x00 + + + + + + [Channel1] + reloop_toggle + Loop On button + 0x90 + 0x01 + + + + + + [Channel1] + DJCJV.beatloopActivate + Beatloop activate button + 0x90 + 0x01 + + + + + + [Channel1] + loop_double + Loop Double + 0x90 + 0x02 + + + + + + + [EffectRack1_EffectUnit1_Effect1] + enabled + FX Unit 1 - Slot 1 On/Off + 0x90 + 0x04 + + + + + + [EffectRack1_EffectUnit1_Effect2] + enabled + FX Unit 1 - Slot 2 On/Off + 0x90 + 0x05 + + + + + + [EffectRack1_EffectUnit1_Effect3] + enabled + FX Unit 1 - Slot 3 On/Off + 0x90 + 0x06 + + + + + + [EffectRack1_EffectUnit1_Effect1] + effect_selector + FX Unit 1 - Slot 1 Select + 0x90 + 0x0C + + + + + + [EffectRack1_EffectUnit1_Effect2] + effect_selector + FX Unit 1 - Slot 2 Select + 0x90 + 0x0D + + + + + + [EffectRack1_EffectUnit1_Effect3] + effect_selector + FX Unit 1 - Slot 3 Select + 0x90 + 0x0E + + + + + + + [Channel1] + hotcue_1_activate + PAD 1 + 0x90 + 0x10 + + + + + + [Channel1] + hotcue_2_activate + PAD 2 + 0x90 + 0x11 + + + + + + [Channel1] + hotcue_3_activate + PAD 3 + 0x90 + 0x12 + + + + + + [Channel1] + hotcue_4_activate + PAD 4 + 0x90 + 0x13 + + + + + + [Channel1] + hotcue_5_activate + PAD 5 + 0x90 + 0x14 + + + + + + [Channel1] + hotcue_6_activate + PAD 6 + 0x90 + 0x15 + + + + + + [Channel1] + hotcue_7_activate + PAD 7 + 0x90 + 0x16 + + + + + + [Channel1] + hotcue_8_activate + PAD 8 + 0x90 + 0x17 + + + + + + + [Channel1] + hotcue_1_clear + PAD 1 + 0x90 + 0x18 + + + + + + [Channel1] + hotcue_2_clear + PAD 2 + 0x90 + 0x19 + + + + + + [Channel1] + hotcue_3_clear + PAD 3 + 0x90 + 0x1A + + + + + + [Channel1] + hotcue_4_clear + PAD 4 + 0x90 + 0x1B + + + + + + [Channel1] + hotcue_5_clear + PAD 5 + 0x90 + 0x1C + + + + + + [Channel1] + hotcue_6_clear + PAD 6 + 0x90 + 0x1D + + + + + + [Channel1] + hotcue_7_clear + PAD 7 + 0x90 + 0x1E + + + + + + [Channel1] + hotcue_8_clear + PAD 8 + 0x90 + 0x1F + + + + + + + [Sampler1] + cue_gotoandplay + PAD 1 + 0x90 + 0x20 + + + + + + [Sampler2] + cue_gotoandplay + PAD 2 + 0x90 + 0x21 + + + + + + [Sampler3] + cue_gotoandplay + PAD 3 + 0x90 + 0x22 + + + + + + [Sampler4] + cue_gotoandplay + PAD 4 + 0x90 + 0x23 + + + + + + [Sampler5] + cue_gotoandplay + PAD 5 + 0x90 + 0x24 + + + + + + [Sampler6] + cue_gotoandplay + PAD 6 + 0x90 + 0x25 + + + + + + [Sampler7] + cue_gotoandplay + PAD 7 + 0x90 + 0x26 + + + + + + [Sampler8] + cue_gotoandplay + PAD 8 + 0x90 + 0x27 + + + + + + + + [Channel2] + play + Play button + 0x91 + 0x32 + + + + + + [Channel2] + play_stutter + SHIFT + Play: Play Stutter + 0x91 + 0x37 + + + + + + + [Channel2] + cue_default + Cue button + 0x91 + 0x31 + + + + + + [Channel2] + start_play + SHIFT + Cue: REWIND to beginning + 0x91 + 0x36 + + + + + + + [Channel2] + sync_enabled + Sync button + 0x91 + 0x30 + + + + + + [Channel2] + sync_master + SHIFT + Sync: Sync Master + 0x91 + 0x35 + + + + + + + [Channel2] + pfl + PFL button + 0x91 + 0x33 + + + + + + + [Channel2] + LoadSelectedTrack + LOAD B button + 0x91 + 0x51 + + + + + + + [Channel2] + keylock + keylock button + 0x91 + 0x34 + + + + + + + [Channel2] + slip_enabled + SLIP button + 0x91 + 0x39 + + + + + + + [Channel2] + DJCJV.wheelTouch + Jog Wheel Touch Deck B + 0x91 + 0x55 + + + + + + + [Channel2] + loop_halve + Loop Half + 0x91 + 0x00 + + + + + + [Channel2] + reloop_toggle + Loop On button + 0x91 + 0x01 + + + + + + [Channel2] + DJCJV.beatloopActivate + Beatloop activate button + 0x91 + 0x01 + + + + + + [Channel2] + loop_double + Loop Double + 0x91 + 0x02 + + + + + + + [EffectRack1_EffectUnit2_Effect1] + enabled + FX Unit 2 - Slot 1 On/Off + 0x91 + 0x04 + + + + + + [EffectRack1_EffectUnit2_Effect2] + enabled + FX Unit 2 - Slot 2 On/Off + 0x91 + 0x05 + + + + + + [EffectRack1_EffectUnit2_Effect3] + enabled + FX Unit 2 - Slot 3 On/Off + 0x91 + 0x06 + + + + + + [EffectRack1_EffectUnit2_Effect1] + effect_selector + FX Unit 2 - Slot 1 Select + 0x91 + 0x0C + + + + + + [EffectRack1_EffectUnit2_Effect2] + effect_selector + FX Unit 2 - Slot 2 Select + 0x91 + 0x0D + + + + + + [EffectRack1_EffectUnit2_Effect3] + effect_selector + FX Unit 2 - Slot 3 Select + 0x91 + 0x0E + + + + + + + [Channel2] + hotcue_1_activate + PAD 1 + 0x91 + 0x10 + + + + + + [Channel2] + hotcue_2_activate + PAD 2 + 0x91 + 0x11 + + + + + + [Channel2] + hotcue_3_activate + PAD 3 + 0x91 + 0x12 + + + + + + [Channel2] + hotcue_4_activate + PAD 4 + 0x91 + 0x13 + + + + + + [Channel2] + hotcue_5_activate + PAD 5 + 0x91 + 0x14 + + + + + + [Channel2] + hotcue_6_activate + PAD 6 + 0x91 + 0x15 + + + + + + [Channel2] + hotcue_7_activate + PAD 7 + 0x91 + 0x16 + + + + + + [Channel2] + hotcue_8_activate + PAD 8 + 0x91 + 0x17 + + + + + + + [Channel2] + hotcue_1_clear + PAD 1 + 0x91 + 0x18 + + + + + + [Channel2] + hotcue_2_clear + PAD 2 + 0x91 + 0x19 + + + + + + [Channel2] + hotcue_3_clear + PAD 3 + 0x91 + 0x1A + + + + + + [Channel2] + hotcue_4_clear + PAD 4 + 0x91 + 0x1B + + + + + + [Channel2] + hotcue_5_clear + PAD 5 + 0x91 + 0x1C + + + + + + [Channel2] + hotcue_6_clear + PAD 6 + 0x91 + 0x1D + + + + + + [Channel2] + hotcue_7_clear + PAD 7 + 0x91 + 0x1E + + + + + + [Channel2] + hotcue_8_clear + PAD 8 + 0x91 + 0x1F + + + + + + + [Sampler1] + cue_gotoandplay + PAD 1 + 0x91 + 0x20 + + + + + + [Sampler2] + cue_gotoandplay + PAD 2 + 0x91 + 0x21 + + + + + + [Sampler3] + cue_gotoandplay + PAD 3 + 0x91 + 0x22 + + + + + + [Sampler4] + cue_gotoandplay + PAD 4 + 0x91 + 0x23 + + + + + + [Sampler5] + cue_gotoandplay + PAD 5 + 0x91 + 0x24 + + + + + + [Sampler6] + cue_gotoandplay + PAD 6 + 0x91 + 0x25 + + + + + + [Sampler7] + cue_gotoandplay + PAD 7 + 0x91 + 0x26 + + + + + + [Sampler8] + cue_gotoandplay + PAD 8 + 0x91 + 0x27 + + + + + + + + [Master] + DJCJV.vinylButton + Vinyl Deck A + 0x90 + 0x46 + + + + + + + [Master] + maximize_library + Browser button - Maximize Library view + 0x90 + 0x47 + + + + + + + [AutoDJ] + enabled + AutoDJ On/Off + 0x90 + 0x48 + + + + + + + [Library] + MoveFocus + Browser button + 0x90 + 0x4F + + + + + + + [Master] + crossfader + Crossfader + 0xB0 + 0x00 + + + + + + + [Library] + MoveVertical + Move Vertical (Browser Knob) + 0xB0 + 0x4E + + + + + + + + [Channel1] + volume + Volume Deck A + 0xB0 + 0x01 + + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter1 + EQ LOW Deck A + 0xB0 + 0x05 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter2 + EQ MID Deck A + 0xB0 + 0x04 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter3 + EQ HIGH Deck A + 0xB0 + 0x03 + + + + + + + [Channel1] + pregain + Gain Deck A + 0xB0 + 0x4F + + + + + + + [QuickEffectRack1_[Channel1]] + DJCJV.Filter + Filter (AIR FX) Deck A + 0xB0 + 0x0F + + + + + + + [Channel1] + rate + 0xB0 + 0x02 + + + + + + [Channel1] + rate + 0xB0 + 0x22 + + + + + + + [Channel1] + DJCJV.scratchWheel + Scratch Deck A (Jog-Wheel) + 0xB0 + 0x41 + + + + + + [Channel1] + DJCJV.bendWheel + Pitch Bend Deck A (Jog-Wheel) + 0xB0 + 0x40 + + + + + + + [Channel1] + DJCJV.beatjumpSize + Loop Size + 0xB0 + 0x44 + + + + + + [Channel1] + DJCJV.beatjumpMove + Move Loop By N Beats + 0xB0 + 0x4A + + + + + + + [Channel1] + beats_translate_curpos + Align beat grid Deck 1 to current playposition + 0x90 + 0x52 + + + + + + [EffectRack1_EffectUnit1_Effect1] + meta + Effect Rack 1 - Slot 2 Level + 0xB0 + 0x47 + + + + + + [EffectRack1_EffectUnit1_Effect2] + meta + Effect Rack 1 - Slot 2 Level + 0xB0 + 0x48 + + + + + + [EffectRack1_EffectUnit1_Effect3] + meta + Effect Rack 1 - Slot 3 Level + 0xB0 + 0x49 + + + + + + [EffectRack1_EffectUnit1] + mix + Effect Rack 1 - Dry/Wet Level + 0xB0 + 0x46 + + + + + + + + [Channel2] + volume + Volume Deck A + 0xB1 + 0x01 + + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter1 + EQ LOW Deck A + 0xB1 + 0x05 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter2 + EQ MID Deck A + 0xB1 + 0x04 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter3 + EQ HIGH Deck A + 0xB1 + 0x03 + + + + + + + [Channel2] + pregain + Gain Deck A + 0xB1 + 0x4F + + + + + + + [QuickEffectRack1_[Channel2]] + DJCJV.Filter + Filter (AIR FX) Deck B + 0xB1 + 0x0F + + + + + + + [Channel2] + rate + 0xB1 + 0x02 + + + + + + [Channel2] + rate + 0xB1 + 0x22 + + + + + + + [Channel2] + DJCJV.scratchWheel + Scratch Deck B (Jog-Wheel) + 0xB1 + 0x41 + + + + + + [Channel2] + DJCJV.bendWheel + Pitch Bend Deck B (Jog-Wheel) + 0xB1 + 0x40 + + + + + + + [Channel2] + DJCJV.beatjumpSize + Loop Size + 0xB1 + 0x44 + + + + + + [Channel2] + DJCJV.beatjumpMove + Move Loop By N Beats + 0xB1 + 0x4A + + + + + + + [Channel2] + beats_translate_curpos + Align beat grid Deck 2 to current playposition + 0x91 + 0x52 + + + + + + [EffectRack1_EffectUnit2_Effect1] + meta + Effect Rack 1 - Slot 2 Level + 0xB1 + 0x47 + + + + + + [EffectRack1_EffectUnit2_Effect2] + meta + Effect Rack 1 - Slot 2 Level + 0xB1 + 0x48 + + + + + + [EffectRack1_EffectUnit2_Effect3] + meta + Effect Rack 1 - Slot 3 Level + 0xB1 + 0x49 + + + + + + [EffectRack1_EffectUnit2] + mix + Effect Rack 1 - Dry/Wet Level + 0xB1 + 0x46 + + + + + + + + + + [Channel1] + play_indicator + PLAY LED Deck A + 0.5 + 1 + 0x90 + 0x32 + 0x7f + 0x0 + + + [Channel1] + play_stutter + PLAY LED Deck A(SHIFT MODE) + 0.5 + 1 + 0x90 + 0x37 + 0x7f + 0x0 + + + [Channel1] + cue_indicator + CUE LED Deck A + 0.5 + 1 + 0x90 + 0x31 + 0x7f + 0x0 + + + [Channel1] + sync_enabled + SYNC LED Deck A + 0.5 + 1 + 0x90 + 0x30 + 0x7f + 0x0 + + + [Channel1] + sync_master + SYNC LED Deck A(SHIFT mode) + 0.5 + 1 + 0x90 + 0x35 + 0x7f + 0x0 + + + [Channel1] + slip_enabled + Slip button Deck A + 0.5 + 1 + 0x90 + 0x39 + 0x7f + 0x0 + + + [Channel1] + keylock + Q button Deck A + 0.5 + 1 + 0x90 + 0x34 + 0x7f + 0x0 + + + [Channel2] + play_indicator + PLAY LED Deck A + 0.5 + 1 + 0x91 + 0x32 + 0x7f + 0x0 + + + [Channel2] + play_stutter + PLAY LED Deck A(SHIFT MODE) + 0.5 + 1 + 0x91 + 0x37 + 0x7f + 0x0 + + + [Channel2] + cue_indicator + CUE LED Deck A + 0.5 + 1 + 0x91 + 0x31 + 0x7f + 0x0 + + + [Channel2] + sync_enabled + SYNC LED Deck A + 0.5 + 1 + 0x91 + 0x30 + 0x7f + 0x0 + + + [Channel2] + sync_master + SYNC LED Deck A(SHIFT mode) + 0.5 + 1 + 0x91 + 0x35 + 0x7f + 0x0 + + + [Channel2] + slip_enabled + Slip button Deck A + 0.5 + 1 + 0x91 + 0x39 + 0x7f + 0x0 + + + [Channel2] + keylock + Q button Deck A + 0.5 + 1 + 0x91 + 0x34 + 0x7f + 0x0 + + + + [Channel1] + loop_enabled + Loop In LED DA + 0.5 + 1 + 0x90 + 0x01 + 0x7f + 0x00 + + + [Channel2] + loop_enabled + Loop In LED DB + 0.5 + 1 + 0x91 + 0x01 + 0x7f + 0x00 + + + + [Channel1] + pfl + PFL LED DECK A + 0.5 + 1 + 0x90 + 0x33 + 0x7f + 0x0 + + + [Channel2] + pfl + PFL LED DECK B + 0.5 + 1 + 0x91 + 0x33 + 0x7f + 0x0 + + + + [EffectRack1_EffectUnit1_Effect1] + enabled + Effect On/Off button + 0.5 + 1 + 0x90 + 0x04 + 0x7f + 0x0 + + + [EffectRack1_EffectUnit1_Effect2] + enabled + Effect On/Off button + 0.5 + 1 + 0x90 + 0x05 + 0x7f + 0x0 + + + [EffectRack1_EffectUnit1_Effect3] + enabled + Effect On/Off button + 0.5 + 1 + 0x90 + 0x06 + 0x7f + 0x0 + + + [EffectRack1_EffectUnit2_Effect1] + enabled + Effect On/Off buttonn + 0.5 + 1 + 0x91 + 0x04 + 0x7f + 0x0 + + + [EffectRack1_EffectUnit2_Effect2] + enabled + Effect On/Off buttonn + 0.5 + 1 + 0x91 + 0x05 + 0x7f + 0x0 + + + [EffectRack1_EffectUnit2_Effect3] + enabled + Effect On/Off buttonn + 0.5 + 1 + 0x91 + 0x06 + 0x7f + 0x0 + + + + [Channel1] + end_of_track + TRACK LED DECK A + 0.5 + 1 + 0x90 + 0x45 + 0x41 + 0x27 + + + [Channel2] + end_of_track + TRACK LED DECK B + 0.5 + 1 + 0x91 + 0x45 + 0x41 + 0x27 + + + + [Master] + maximize_library + VIEW buton LED + 0.5 + 1 + 0x90 + 0x47 + 0x7F + 0x00 + + + + [AutoDJ] + enabled + LOAD Prepare button LED + 0.5 + 1 + 0x91 + 0x45 + 0x7F + 0x00 + + + + [Channel1] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x90 + 0x10 + 0x7E + 0.5 + + + [Channel1] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x90 + 0x11 + 0x7E + 0.5 + + + [Channel1] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x90 + 0x12 + 0x7E + 0.5 + + + [Channel1] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x90 + 0x13 + 0x7E + 0.5 + + + [Channel1] + hotcue_5_enabled + Hotcue 5 (Pad 5) + 0x90 + 0x14 + 0x7E + 0.5 + + + [Channel1] + hotcue_6_enabled + Hotcue 6 (Pad 6) + 0x90 + 0x15 + 0x7E + 0.5 + + + [Channel1] + hotcue_7_enabled + Hotcue 7 (Pad 7) + 0x90 + 0x16 + 0x7E + 0.5 + + + [Channel1] + hotcue_8_enabled + Hotcue 8 (Pad 8) + 0x90 + 0x17 + 0x7E + 0.5 + + + [Channel2] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x91 + 0x10 + 0x7E + 0.5 + + + [Channel2] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x91 + 0x11 + 0x7E + 0.5 + + + [Channel2] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x91 + 0x12 + 0x7E + 0.5 + + + [Channel2] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x91 + 0x13 + 0x7E + 0.5 + + + [Channel2] + hotcue_5_enabled + Hotcue 5 (Pad 5) + 0x91 + 0x14 + 0x7E + 0.5 + + + [Channel2] + hotcue_6_enabled + Hotcue 6 (Pad 6) + 0x91 + 0x15 + 0x7E + 0.5 + + + [Channel2] + hotcue_7_enabled + Hotcue 7 (Pad 7) + 0x91 + 0x16 + 0x7E + 0.5 + + + [Channel2] + hotcue_8_enabled + Hotcue 8 (Pad 8) + 0x91 + 0x17 + 0x7E + 0.5 + + + + [Channel1] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x90 + 0x18 + 0x7E + 0.5 + + + [Channel1] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x90 + 0x19 + 0x7E + 0.5 + + + [Channel1] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x90 + 0x1A + 0x7E + 0.5 + + + [Channel1] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x90 + 0x1B + 0x7E + 0.5 + + + [Channel1] + hotcue_5_enabled + Hotcue 5 (Pad 5) + 0x90 + 0x1C + 0x7E + 0.5 + + + [Channel1] + hotcue_6_enabled + Hotcue 6 (Pad 6) + 0x90 + 0x1D + 0x7E + 0.5 + + + [Channel1] + hotcue_7_enabled + Hotcue 7 (Pad 7) + 0x90 + 0x1E + 0x7E + 0.5 + + + [Channel1] + hotcue_8_enabled + Hotcue 8 (Pad 8) + 0x90 + 0x1F + 0x7E + 0.5 + + + [Channel2] + hotcue_1_enabled + Hotcue 1 (Pad 1) + 0x91 + 0x18 + 0x7E + 0.5 + + + [Channel2] + hotcue_2_enabled + Hotcue 2 (Pad 2) + 0x91 + 0x19 + 0x7E + 0.5 + + + [Channel2] + hotcue_3_enabled + Hotcue 3 (Pad 3) + 0x91 + 0x1A + 0x7E + 0.5 + + + [Channel2] + hotcue_4_enabled + Hotcue 4 (Pad 4) + 0x91 + 0x1B + 0x7E + 0.5 + + + [Channel2] + hotcue_5_enabled + Hotcue 5 (Pad 5) + 0x91 + 0x1C + 0x7E + 0.5 + + + [Channel2] + hotcue_6_enabled + Hotcue 6 (Pad 6) + 0x91 + 0x1D + 0x7E + 0.5 + + + [Channel2] + hotcue_7_enabled + Hotcue 7 (Pad 7) + 0x91 + 0x1E + 0x7E + 0.5 + + + [Channel2] + hotcue_8_enabled + Hotcue 8 (Pad 8) + 0x91 + 0x1F + 0x7E + 0.5 + + + + [Sampler1] + play_indicator + (Pad 1 DECK A) + 0x90 + 0x20 + 0x7F + 0.5 + + + [Sampler1] + play_indicator + (Pad 1 DECK B) + 0x91 + 0x20 + 0x7F + 0.5 + + + [Sampler2] + play_indicator + (Pad 2 DECK A) + 0x90 + 0x21 + 0x7F + 0.5 + + + [Sampler2] + play_indicator + (Pad 2 DECK B) + 0x91 + 0x21 + 0x7F + 0.5 + + + [Sampler3] + play_indicator + (Pad 3 DECK A) + 0x90 + 0x22 + 0x7F + 0.5 + + + [Sampler3] + play_indicator + (Pad 3 DECK B) + 0x91 + 0x22 + 0x7F + 0.5 + + + [Sampler4] + play_indicator + (Pad 4 DECK A) + 0x90 + 0x23 + 0x7F + 0.5 + + + [Sampler4] + play_indicator + (Pad 4 DECK B) + 0x91 + 0x23 + 0x7F + 0.5 + + + [Sampler5] + play_indicator + (Pad 5 DECK A) + 0x90 + 0x24 + 0x7F + 0.5 + + + [Sampler5] + play_indicator + (Pad 5 DECK B) + 0x91 + 0x24 + 0x7F + 0.5 + + + [Sampler6] + play_indicator + (Pad 6 DECK A) + 0x90 + 0x25 + 0x7F + 0.5 + + + [Sampler6] + play_indicator + (Pad 6 DECK B) + 0x91 + 0x25 + 0x7F + 0.5 + + + [Sampler7] + play_indicator + (Pad 7 DECK A) + 0x90 + 0x26 + 0x7F + 0.5 + + + [Sampler7] + play_indicator + (Pad 7 DECK B) + 0x91 + 0x26 + 0x7F + 0.5 + + + [Sampler8] + play_indicator + (Pad 8 DECK A) + 0x90 + 0x27 + 0x7F + 0.5 + + + [Sampler8] + play_indicator + (Pad 4 DECK B) + 0x91 + 0x27 + 0x7F + 0.5 + + + +