From 5b65bfef651355eaad58cd8b44e661dcd477e30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Soto?= Date: Wed, 20 Dec 2023 15:14:31 -0600 Subject: [PATCH] Pioneer DDJ-ERGO: added mappings --- res/controllers/PIONEER-DDJ-ERGO-scripts.js | 441 +++++ res/controllers/PIONEER-DDJ-ERGO.midi.xml | 1925 +++++++++++++++++++ 2 files changed, 2366 insertions(+) create mode 100644 res/controllers/PIONEER-DDJ-ERGO-scripts.js create mode 100644 res/controllers/PIONEER-DDJ-ERGO.midi.xml diff --git a/res/controllers/PIONEER-DDJ-ERGO-scripts.js b/res/controllers/PIONEER-DDJ-ERGO-scripts.js new file mode 100644 index 000000000000..ce75ddaafb0b --- /dev/null +++ b/res/controllers/PIONEER-DDJ-ERGO-scripts.js @@ -0,0 +1,441 @@ +//Controller +var DDJERGO = {}; + +//This will hold the last FX button clicked, so the FX on that slot can be manipulated +var selectedEffects = [ + 0, + 0, +]; + +//This helps grab FX dynamically +const effectsStrings = [ + [ + "[EffectRack1_EffectUnit1_Effect1]", + "[EffectRack1_EffectUnit1_Effect2]", + "[EffectRack1_EffectUnit1_Effect3]", + ], + [ + "[EffectRack1_EffectUnit2_Effect1]", + "[EffectRack1_EffectUnit2_Effect2]", + "[EffectRack1_EffectUnit2_Effect3]", + ], +]; + +//This stores the last position of the FX control knob so when this changes a significant amount, a new effect is chosen +var previousEffectKnobPosition = 0; + +//Sample vol knob triggers the last sample played when clicked, and changes it when shift + turn +var selectedSamples = [ + 0, + 0, +]; + +//This helps grab samples dynamically +const samplerStrings = [ + "[Sampler1]", + "[Sampler2]", + "[Sampler3]", + "[Sampler4]", + "[Sampler5]", + "[Sampler6]", + "[Sampler7]", + "[Sampler8]", +]; + +//These store the last beat played timestamp in milliseconds to implement the pulse mode +var timestamps = [ + 0, + 0, +]; + +//These help blink the loop in/out buttons in a Pioneer way +var loopIn = 0; +var loopOut = 0; + +//These store the loop in/out buttons blink state for each channel +var blink = [ + 1, + 1, +]; + +//Init function +DDJERGO.init = function() { + //Sysex message to initialize sound card + const ControllerStatusSysex = [0xB0, 0x4B, 0x20, 0x00, 0xB0, 0x4B, 0x40, 0xF7, 0xB0, 0x4B, 0x42, 0xF7]; + midi.sendSysexMsg(ControllerStatusSysex, ControllerStatusSysex.length); + //Messages to initialize fader LEDs + var i; + for (i = 0; i < 6; i++) { + midi.sendShortMsg(0xB6, 0x1F-i, 0x40); + } + for (i = 0; i < 4; i++) { + midi.sendShortMsg(0xB6, 0x19-2*i, 0x7F); + } + for (i = 0; i < 12; i++) { + midi.sendShortMsg(0xB6, 0x12-i, 0x40); + } + for (i = 0; i < 4; i++) { + midi.sendShortMsg(0xB6, 0x19-2*i, 0x00); + } +}; + +//shutdown +DDJERGO.shutdown = function() { + +}; + +//Scroll through library with browse knob +DDJERGO.browseLibrary = function(channel, control, value) { + var newValue; + if (value-64 > 0) { newValue = value-128; } else { newValue = value; } + engine.setValue("[Library]", "MoveVertical", newValue); +}; + +//Nudge track for beat matching when wheel is turned +DDJERGO.nudge = function(channel, control, value, status, group) { + //this is because the controller never sends a 0x40 message and hence never stops nudging + if (Math.abs(value-0x40)===1) { + value = 0x40; + } + const newValue = value-64; + // 0.5 * val / 64 seems to yield the best results + engine.setValue(group, "wheel", 0.5*newValue/64); +}; + +//Start a beatloop when autoloop is pressed +DDJERGO.beatloop = function(channel, control, value, status, group) { + if (value === 0x7F) { + if (engine.getParameter(group, "loop_enabled") === 1) { + engine.setParameter(group, "reloop_toggle", 1); + } else { + engine.setParameter(group, "beatloop_activate", 1); + } + } +}; + +// The button that enables/disables scratching +DDJERGO.wheelTouch = function(channel, control, value, status, group) { + const deckNumber = script.deckFromGroup(group); + const alpha = 1.0/8; + const beta = alpha/32; + if (value === 0x7F) { + engine.scratchEnable(deckNumber, 2048, 33+1/3, alpha, beta); + } else { + engine.scratchDisable(deckNumber); + } +}; + +// The wheel that actually controls the scratching +DDJERGO.wheelTurn = function(channel, control, value, status, group) { + const deckNumber = script.deckFromGroup(group); + //this is because the controller never sends a 0x40 message and hence never stops scratching + if (Math.abs(value-0x40)===1) { + value = 0x40; + } + const newValue = value - 64; + if (engine.isScratching(deckNumber)) { + engine.scratchTick(deckNumber, newValue); + } else { + engine.setValue(group, "jog", newValue); + } +}; + +//multiply/divide loop size when autoloop wheel is turned +DDJERGO.autoloopMultiply = function(channel, control, value, status, group) { + const newValue = value-64; + if (newValue > 0) { + engine.setParameter(group, "loop_halve", 1); + } + if (newValue < 0) { + engine.setParameter(group, "loop_double", 1); + } +}; + +//this inverts the tempo slider. Didn't seem to work in the xml +DDJERGO.rate = function(channel, control, value, status, group) { + if (control === 0x00) { + const newValue = value-64; + engine.setValue(group, "rate", -1*newValue/64); + } +}; + +//change tempo rate in 8% increments (32% max) with shift + keylock button +DDJERGO.setTempoRange = function(channel, control, value, status, group) { + if (value === 0x7F) { + var curr = engine.getValue(group, "rateRange"); + if (curr > 0.31) { + curr = 0.08; + } else { + curr += 0.08; + } + engine.setValue(group, "rateRange", curr); + } +}; + +//move quickly through the track when shift + jog wheel touch + turn +DDJERGO.searchTrack = function(channel, control, value, status, group) { + //this is because the controller never sends a 0x40 message and hence never stops searching + if (Math.abs(value-0x40)===1) { + value = 0x40; + } + const newValue = value-64; + // 3 * val seems to yield the best results + engine.setValue(group, "rateSearch", 3*newValue); +}; + +//move the current loop by one beat when shift + in/out +DDJERGO.loopMove = function(channel, control, value, status, group) { + if (value === 0x7F) { + if (control === 0x4C) { + engine.setValue(group, "loop_move", -1); + } + if (control === 0x4D) { + engine.setValue(group, "loop_move", 1); + } + } +}; + +//move the beat markers to match the beats with shift + auto loop +DDJERGO.adjustGrid = function(channel, control, value, status, group) { + var newValue; + if (value-64 > 0) { newValue = value-128; } else { newValue = value; } + if (newValue > 0) { + engine.setValue(group, "beats_translate_later", 1); + } + if (newValue < 0) { + engine.setValue(group, "beats_translate_earlier", 1); + } +}; + +//this opens/closes directories when browsing the sidebar and shift + turn the browse wheel +DDJERGO.browseSidebar = function(channel, control, value) { + var newValue; + if (value-64 > 0) { newValue = value-128; } else { newValue = value; } + if (newValue > 0) { + engine.setParameter("[Library]", "MoveRight", 1); + } + if (newValue < 0) { + engine.setParameter("[Library]", "MoveLeft", 1); + } +}; + +//this stores the FX button presses in the selectedEffects variable and enables/disables the effect with the on fx button click +//this also deals with LEDs, turning on the FX slot button currently active and the ON button +DDJERGO.effectsFunction = function(channel, control, value, status) { + var deck = status-0x94; + var effect = selectedEffects[deck]; + //on button pressed + if (control === 0x43 && value === 0x7F) { + const toggleState = 1 - engine.getParameter(effectsStrings[deck][effect], "enabled"); + engine.setParameter(effectsStrings[deck][effect], "enabled", toggleState); + //toggle ON button and selected effect button + midi.sendShortMsg(status, 0x43, 0x7F*toggleState); + midi.sendShortMsg(status, 0x47+effect, 0x7F*toggleState); + } + //fx number button pressed + else if (control >= 0x47 && value === 0x7F) { + selectedEffects[deck] = control - 0x47; + } +}; + +//this modifies the selected effects parameters based on the MSBs of the FX knobs +DDJERGO.effectsParams = function(channel, control, value, status) { + var deck = status-0xB4; + const effect = selectedEffects[deck]; + //if called with MSB + if (control < 0x20) { + //if fx selector turned enough + if (control === 0x00 && previousEffectKnobPosition !== value/5) { + //switch to next or previous fx in list + if (previousEffectKnobPosition > value/5) { + engine.setValue(effectsStrings[deck][effect], "effect_selector", -1); + } else { + engine.setValue(effectsStrings[deck][effect], "effect_selector", 1); + } + previousEffectKnobPosition = value/5; + } + //if fx knob 1 turned + if (control === 0x02) { + engine.setValue(effectsStrings[deck][effect], "meta", value/127); + } + } +}; + +//this plays the samples on the samplers with a click on the samplers buttons and stores its value for the sample vol knob to manipulate it +DDJERGO.samplers = function(channel, control, value, status, group) { + var deck = status-0x90; + if (value === 0x7F) { + if (engine.getParameter(group, "play") === 1) { + engine.setParameter(group, "cue_default", 1); + } else { + engine.setParameter(group, "play", 1); + } + //store sample numbers + selectedSamples[0] = (control - 0x3C)/2 + (deck)*4; + selectedSamples[1] = (control - 0x3C)/2 + (deck)*4; + } +}; + +//this modifies the selected sample volume with sample vol knob rotations +DDJERGO.samplerVolume = function(channel, control, value, status) { + var deck = status-0xB0; + var newValue; + if (value-64 > 0) { newValue = value-128; } else { newValue = value; } + if (newValue > 0) { + script.triggerControl(samplerStrings[selectedSamples[deck]], "pregain_up"); + } + if (newValue < 0) { + script.triggerControl(samplerStrings[selectedSamples[deck]], "pregain_down"); + } +}; + +//this plays the selected sample with a sample vol knob click +DDJERGO.samplerKnobClick = function(channel, control, value, status) { + var deck = status-0x90; + const sample = selectedSamples[deck]; + if (value === 0x7F) { + if (engine.getParameter(samplerStrings[sample], "play") === 1) { + engine.setParameter(samplerStrings[sample], "cue_default", 1); + } else { + engine.setParameter(samplerStrings[sample], "play", 1); + } + } +}; + +//this changes the sample stored in the knob being shift + turned +DDJERGO.rotateSamples = function(channel, control, value, status) { + var deck = status-0xB0; + var newValue; + if (value-64 > 0) { newValue = value-128; } else { newValue = value; } + selectedSamples[deck] += newValue; + //makes sure samples stay within range + if (selectedSamples[deck] < 0) { + selectedSamples[deck] += 8; + } + if (selectedSamples[deck] > 7) { + selectedSamples[deck] -= 8; + } +}; + +//this changes both the mic and aux pregains with the aux/mic vol knob +DDJERGO.micAuxGain = function(channel, control, value) { + //weird non-linear mapping for pregain + if (value < 64) { + value = value/63; + } else { + value = 3*value/64 - 125/64; + } + engine.setValue("[Microphone]", "pregain", value); + engine.setValue("[Auxiliary1]", "pregain", value); +}; + +//this toggles on/off effect 1 or 2 based on FX [1-2] buttons clicks +DDJERGO.quickEffects = function(channel, control, value, status) { + if (value === 0x7F) { + var deck = control % 2; + const effect = (control - deck - 0x4C)/4; + const toggleState = 1 - engine.getParameter(effectsStrings[deck][effect], "enabled"); + engine.setParameter(effectsStrings[deck][effect], "enabled", toggleState); + //LEDs for ON, FX number button and FX [1-2] + midi.sendShortMsg(0x94 + deck, 0x43, 0x7F*toggleState); + midi.sendShortMsg(0x94 + deck, 0x47 + effect, 0x7F*toggleState); + midi.sendShortMsg(status, control, 0x7F*toggleState); + } +}; + +//callback for pulse mode intensity calculation on every beat +const pulseModeCallback = function(value, group) { + //on beat + if (value === 1) { + //store timestamps + if (group === "[Channel1]") { + timestamps[0] = Date.now(); + } else { + timestamps[1] = Date.now(); + } + //calculate delta time in ms and divide it by the ms between beats + //a 0 delta or a millis delta means maximum beat alignment + //a 0.5 * millis delta means minimal beat alignment + const delta = Math.abs(timestamps[0] - timestamps[1]); + const bpm = engine.getValue(group, "bpm"); + const millis = 1/(bpm/60000); + const match = -1*Math.abs(delta-(millis/2))/(millis/2) + 1; + //send pulse signals to the plates + midi.sendShortMsg(0xBB, 0x14, 0x40-0x40*match); + midi.sendShortMsg(0xBB, 0x15, 0x40-0x40*match); + } +}; + +//callback to turn on/off/blink loop in/out LEDs based on clicks and loop enabled/disabled +const loopLEDsCallback = function(value, group, control) { + //loop in clicked or autoloop + if (control === "loop_in" || engine.getParameter(group, "loop_enabled") === 1) { + loopIn = 1; + } + //loop out clicked or autoloop + if (control === "loop_out" || engine.getParameter(group, "loop_enabled") === 1) { + loopOut = 1; + } + //loop was disabled + if (control === "loop_enabled" && engine.getParameter(group, "loop_enabled") === 0) { + loopIn = 0; + loopOut = 0; + } + const channel = group === "[Channel1]" ? 0 : 1; + //if not looping, LED on, else toggle LED on every beat + //loop in manipulates blink since loop in blinks while waiting for a loop out click + if (loopIn === 0) { + midi.sendShortMsg(0x90+channel, 0x10, 0x7F); + } else if (control === "beat_active" && value === 1) { + midi.sendShortMsg(0x90+channel, 0x10, (1-blink[channel])*0x7F); + blink[channel] = 1 - blink[channel]; + } + //if not looping, LED on, else toggle LED on every beat + if (loopOut === 0) { + midi.sendShortMsg(0x90+channel, 0x11, 0x7F); + } else if (control === "beat_active" && value === 1) { + midi.sendShortMsg(0x90+channel, 0x11, blink[channel]*0x7F); + } +}; + +//this blinks the faders on every beat and varying intensity based on fader position +const volumeLEDsCallback = function(value, group) { + const channel = group === "[Channel1]" ? 0 : 1; + const volume = engine.getParameter(group, "volume"); + //message to set intensity + two on/off messages since it requires them with two different midinos + midi.sendShortMsg(0xB6, 0x13+2*channel, 0x7F*volume); + midi.sendShortMsg(0x9B, 0x74+channel, 0x7F*value); + midi.sendShortMsg(0x9B, 0x78+channel, 0x7F*value); +}; + +//this triggers an LED animation when the filter knob is turned +const filterLEDsCallback = function(value, group) { + const channel = group === "[QuickEffectRack1_[Channel1]]" ? 0 : 1; + midi.sendShortMsg(0xB6, 0x1B+channel, value === 0.5 ? 0x40 : 0x7F*value); +}; + +//this triggers an LED animation when a track is loaded into the deck +const loadingAnimationCallback = function(value, group) { + if (engine.getParameter(group, "play") !== 1 && engine.getParameter(group, "track_loaded") === 1) { + const channel = group === "[Channel1]" ? 0 : 1; + midi.sendShortMsg(0x9B, 0x0C+channel, 0x7F); + } +}; + +//callback connections +engine.makeConnection("[Channel1]", "beat_active", pulseModeCallback); +engine.makeConnection("[Channel2]", "beat_active", pulseModeCallback); +engine.makeConnection("[Channel1]", "beat_active", loopLEDsCallback); +engine.makeConnection("[Channel2]", "beat_active", loopLEDsCallback); +engine.makeConnection("[Channel1]", "loop_in", loopLEDsCallback); +engine.makeConnection("[Channel2]", "loop_in", loopLEDsCallback); +engine.makeConnection("[Channel1]", "loop_out", loopLEDsCallback); +engine.makeConnection("[Channel2]", "loop_out", loopLEDsCallback); +engine.makeConnection("[Channel1]", "loop_enabled", loopLEDsCallback); +engine.makeConnection("[Channel2]", "loop_enabled", loopLEDsCallback); +engine.makeConnection("[Channel1]", "beat_active", volumeLEDsCallback); +engine.makeConnection("[Channel2]", "beat_active", volumeLEDsCallback); +engine.makeConnection("[QuickEffectRack1_[Channel1]]", "super1", filterLEDsCallback); +engine.makeConnection("[QuickEffectRack1_[Channel2]]", "super1", filterLEDsCallback); +engine.makeConnection("[Channel1]", "LoadSelectedTrack", loadingAnimationCallback); +engine.makeConnection("[Channel2]", "LoadSelectedTrack", loadingAnimationCallback); diff --git a/res/controllers/PIONEER-DDJ-ERGO.midi.xml b/res/controllers/PIONEER-DDJ-ERGO.midi.xml new file mode 100644 index 000000000000..fda2b87d5734 --- /dev/null +++ b/res/controllers/PIONEER-DDJ-ERGO.midi.xml @@ -0,0 +1,1925 @@ + + + + PIONEER-DDJ-ERGO + Jesús Soto + https://mixxx.discourse.group/t/pioneer-ergo-mapping/28643 + https://manual.mixxx.org/2.4/en/hardware/controllers/pioneer_ddj_ergo + + + + + + + + [Channel1] + play + Toggles playing or pausing the track deck 1 + 0x90 + 0x0B + + + + + + [Channel1] + cue_default + Cue button deck 1 + 0x90 + 0x0C + + + + + + [Channel1] + loop_in + Loop in deck 1 + 0x90 + 0x10 + + + + + + [Channel1] + loop_out + Loop out deck 1 + 0x90 + 0x11 + + + + + + [Channel1] + DDJERGO.beatloop + Toggle beatloop deck 1 + 0x90 + 0x14 + + + + + + [Channel1] + keylock + Keylock deck 1 + 0x90 + 0x1A + + + + + + [Channel1] + DDJERGO.setTempoRange + Set tempo slider range deck 1 + 0x90 + 0x1B + + + + + + [Channel1] + hotcue_1_activate + Hotcue 1 deck 1 + 0x90 + 0x2E + + + + + + [Channel1] + hotcue_2_activate + Hotcue 2 deck 1 + 0x90 + 0x2F + + + + + + [Channel1] + hotcue_3_activate + Hotcue 3 deck 1 + 0x90 + 0x30 + + + + + + [Channel1] + hotcue_4_activate + Hotcue 4 deck 1 + 0x90 + 0x31 + + + + + + [Channel1] + DDJERGO.wheelTouch + Touch wheel to start scratch deck 1 + 0x90 + 0x36 + + + + + + [Sampler1] + DDJERGO.samplers + Play sampler 1 + 0x90 + 0x3C + + + + + + [Sampler1] + cue_gotoandplay + Stutter sample 1 + 0x90 + 0x3D + + + + + + [Sampler2] + DDJERGO.samplers + Play sampler 2 + 0x90 + 0x3E + + + + + + [Sampler2] + cue_gotoandplay + Stutter sample 2 + 0x90 + 0x3F + + + + + + [Sampler3] + DDJERGO.samplers + Play sampler 3 + 0x90 + 0x40 + + + + + + [Sampler3] + cue_gotoandplay + Stutter sample 3 + 0x90 + 0x41 + + + + + + [Sampler4] + DDJERGO.samplers + Play sampler 4 + 0x90 + 0x42 + + + + + + [Sampler4] + cue_gotoandplay + Stutter sample 4 + 0x90 + 0x43 + + + + + + [Sampler1] + DDJERGO.samplerKnobClick + Play sample slot 1 + 0x90 + 0x45 + + + + + + [Channel1] + start + Jump to start of track + 0x90 + 0x48 + + + + + + [Samplers] + show_samplers + Show samplers + 0x90 + 0x4A + + + + + + [Channel1] + DDJERGO.loopMove + Move loop 1 beat backward deck 1 + 0x90 + 0x4C + + + + + + [Channel1] + DDJERGO.loopMove + Move loop 1 beat forward deck 1 + 0x90 + 0x4D + + + + + + [Channel1] + reloop_toggle + Toggle reloop channel 1 + 0x90 + 0x50 + + + + + + [Channel1] + sync_enabled + Enable sync channel 1 + 0x90 + 0x58 + + + + + + [Channel1] + sync_master + Sets channel 1 as leader clock + 0x90 + 0x5C + + + + + + [Channel1] + hotcue_1_clear + Clear hotcue 1 deck 1 + 0x90 + 0x5F + + + + + + [Channel1] + hotcue_2_clear + Clear hotcue 2 deck 1 + 0x90 + 0x60 + + + + + + [Channel1] + hotcue_3_clear + Clear hotcue 3 deck 1 + 0x90 + 0x61 + + + + + + [Channel1] + hotcue_4_clear + Clear hotcue 4 deck 1 + 0x90 + 0x62 + + + + + + [Channel2] + play + Toggles playing or pausing the track deck 2 + 0x91 + 0x0B + + + + + + [Channel2] + cue_default + Cue button deck 2 + 0x91 + 0x0C + + + + + + [Channel2] + loop_in + Loop in deck 2 + 0x91 + 0x10 + + + + + + [Channel2] + loop_out + Loop out deck 2 + 0x91 + 0x11 + + + + + + [Channel2] + DDJERGO.beatloop + Toggle beatloop deck 2 + 0x91 + 0x14 + + + + + + [Channel2] + keylock + Keylock deck 2 + 0x91 + 0x1A + + + + + + [Channel2] + DDJERGO.setTempoRange + Set tempo slider range deck 2 + 0x91 + 0x1B + + + + + + [Channel2] + hotcue_1_activate + Hotcue 1 deck 2 + 0x91 + 0x2E + + + + + + [Channel2] + hotcue_2_activate + Hotcue 2 deck 2 + 0x91 + 0x2F + + + + + + [Channel2] + hotcue_3_activate + Hotcue 3 deck 2 + 0x91 + 0x30 + + + + + + [Channel2] + hotcue_4_activate + Hotcue 4 deck 2 + 0x91 + 0x31 + + + + + + [Channel2] + DDJERGO.wheelTouch + Touch wheel to start scratch deck 1 + 0x91 + 0x36 + + + + + + [Sampler5] + DDJERGO.samplers + Play sampler 5 + 0x91 + 0x3C + + + + + + [Sampler5] + cue_gotoandplay + Stutter sample 5 + 0x91 + 0x3D + + + + + + [Sampler6] + DDJERGO.samplers + Play sampler 6 + 0x91 + 0x3E + + + + + + [Sampler6] + cue_gotoandplay + Stutter sample 6 + 0x91 + 0x3F + + + + + + [Sampler7] + DDJERGO.samplers + Play sampler 7 + 0x91 + 0x40 + + + + + + [Sampler7] + cue_gotoandplay + Stutter sample 7 + 0x91 + 0x41 + + + + + + [Sampler8] + DDJERGO.samplers + Play sampler 8 + 0x91 + 0x42 + + + + + + [Sampler8] + cue_gotoandplay + Stutter sample 8 + 0x91 + 0x43 + + + + + + [Sampler1] + DDJERGO.samplerKnobClick + Play sample slot 2 + 0x91 + 0x45 + + + + + + [Channel2] + start + Jump to start of track + 0x91 + 0x48 + + + + + + [Samplers] + show_samplers + Show samplers + 0x91 + 0x4A + + + + + + [Channel2] + DDJERGO.loopMove + Move loop 1 beat backward deck 2 + 0x91 + 0x4C + + + + + + [Channel2] + DDJERGO.loopMove + Move loop 1 beat back forward 2 + 0x91 + 0x4D + + + + + + [Channel2] + reloop_toggle + Toggle reloop channel 1 + 0x91 + 0x50 + + + + + + [Channel2] + sync_enabled + Enable sync channel 2 + 0x91 + 0x58 + + + + + + [Channel2] + sync_master + Sets channel 2 as leader clock + 0x91 + 0x5C + + + + + + [Channel2] + hotcue_1_clear + Clear hotcue 1 deck 2 + 0x91 + 0x5F + + + + + + [Channel2] + hotcue_2_clear + Clear hotcue 2 deck 2 + 0x91 + 0x60 + + + + + + [Channel2] + hotcue_3_clear + Clear hotcue 3 deck 2 + 0x91 + 0x61 + + + + + + [Channel2] + hotcue_4_clear + Clear hotcue 4 deck 2 + 0x91 + 0x62 + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsFunction + Turn on effect channel 1 + 0x94 + 0x43 + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsFunction + Select effect 1 channel 1 + 0x94 + 0x47 + + + + + + [EffectRack1_EffectUnit1_Effect2] + DDJERGO.effectsFunction + Select effect 2 channel 1 + 0x94 + 0x48 + + + + + + [EffectRack1_EffectUnit1_Effect3] + DDJERGO.effectsFunction + Select effect 3 channel 1 + 0x94 + 0x49 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsFunction + Turn on effect channel 2 + 0x95 + 0x43 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsFunction + Select effect 1 channel 2 + 0x95 + 0x47 + + + + + + [EffectRack1_EffectUnit2_Effect2] + DDJERGO.effectsFunction + Select effect 2 channel 2 + 0x95 + 0x48 + + + + + + [EffectRack1_EffectUnit2_Effect3] + DDJERGO.effectsFunction + Select effect 3 channel 2 + 0x95 + 0x49 + + + + + + [Library] + MoveFocusForward + Toggle between sidebar and library + 0x96 + 0x41 + + + + + + [Master] + maximize_library + Maximize library + 0x96 + 0x42 + + + + + + [Channel1] + LoadSelectedTrack + Load to deck 1 + 0x96 + 0x46 + + + + + + [Channel2] + LoadSelectedTrack + Load to deck 2 + 0x96 + 0x47 + + + + + + [Channel1] + DDJERGO.quickEffects + Toggle effect 1 + 0x96 + 0x4C + + + + + + [Channel2] + DDJERGO.quickEffects + Toggle effect 1 + 0x96 + 0x4D + + + + + + [Channel1] + DDJERGO.quickEffects + Toggle effect 2 + 0x96 + 0x50 + + + + + + [Channel2] + DDJERGO.quickEffects + Toggle effect 2 + 0x96 + 0x51 + + + + + + [Channel1] + pfl + Toggles headphone cueing deck 1 + 0x96 + 0x54 + + + + + + [Channel2] + pfl + Toggles headphone cueing deck 2 + 0x96 + 0x55 + + + + + + [Library] + show_coverart + Show cover art + 0x96 + 0x65 + + + + + + [Recording] + toggle_recording + Toggle recording + 0x96 + 0x66 + + + + + + [Channel1] + DDJERGO.rate + Speed control deck 1 + 0xB0 + 0x00 + + + + + + + [Channel1] + DDJERGO.autoloopMultiply + Multiply/divide loop deck 1 + 0xB0 + 0x13 + + + + + + [Channel1] + DDJERGO.rate + Speed control deck 1 + 0xB0 + 0x20 + + + + + + + [Channel1] + DDJERGO.nudge + Holds the speed one step higher/lower while active deck 1 + 0xB0 + 0x21 + + + + + + [Channel1] + DDJERGO.wheelTurn + Scratch deck 1 + 0xB0 + 0x22 + + + + + [Channel1] + DDJERGO.nudge + Holds the speed one step higher/lower while active deck 1 + 0xB0 + 0x23 + + + + + [Channel1] + DDJERGO.searchTrack + Search track deck 1 + 0xB0 + 0x27 + + + + + + [Sampler1] + DDJERGO.samplerVolume + Adjust sample volume + 0xB0 + 0x44 + + + + + + [Sampler1] + DDJERGO.rotateSamples + Change sample slot 1 + 0xB0 + 0x49 + + + + + + [Channel1] + DDJERGO.adjustGrid + Move channel 1 loop + 0xB0 + 0x4F + + + + + + [Channel2] + DDJERGO.rate + Speed control deck 2 + 0xB1 + 0x00 + + + + + + + [Channel2] + DDJERGO.autoloopMultiply + Multiply/divide loop deck 1 + 0xB1 + 0x13 + + + + + + [Channel2] + DDJERGO.rate + Speed control deck 2 + 0xB1 + 0x20 + + + + + + + [Channel2] + DDJERGO.nudge + Holds the speed one step higher/lower while active deck 2 + 0xB1 + 0x21 + + + + + + [Channel2] + DDJERGO.wheelTurn + Scratch deck 2 + 0xB1 + 0x22 + + + + + + [Channel2] + DDJERGO.nudge + Holds the speed one step higher/lower while active deck 2 + 0xB1 + 0x23 + + + + + + [Channel2] + DDJERGO.searchTrack + Search track deck 2 + 0xB1 + 0x27 + + + + + + [Sampler1] + DDJERGO.samplerVolume + Adjust sample volume + 0xB1 + 0x44 + + + + + + [Sampler1] + DDJERGO.rotateSamples + Change sample slot 2 + 0xB1 + 0x49 + + + + + + [Channel2] + DDJERGO.adjustGrid + Move channel 2 loop + 0xB1 + 0x4F + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsParams + Select effect channel 1 + 0xB4 + 0x00 + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsParams + Param 1 channel 1 + 0xB4 + 0x02 + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsParams + Param 2 channel 1 + 0xB4 + 0x04 + + + + + + [EffectRack1_EffectUnit1_Effect1] + DDJERGO.effectsParams + Param 3 channel 1 + 0xB4 + 0x06 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsParams + Select effect channel 1 + 0xB5 + 0x00 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsParams + Param 1 channel 1 + 0xB5 + 0x02 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsParams + Param 2 channel 1 + 0xB5 + 0x04 + + + + + + [EffectRack1_EffectUnit2_Effect1] + DDJERGO.effectsParams + Param 3 channel 1 + 0xB5 + 0x06 + + + + + + [Master] + gain + Adjust master volume. + 0xB6 + 0x00 + + + + + + [Master] + headMix + Adjusts the cue/main mix in the headphone output. + 0xB6 + 0x01 + + + + + + [Master] + headGain + Adjusts the headphone output gain. + 0xB6 + 0x02 + + + + + + [Channel1] + pregain + Adjusts the gain of the input + 0xB6 + 0x03 + + + + + + [Channel2] + pregain + Adjusts the gain of the input + 0xB6 + 0x04 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter3 + High EQ deck 1 + 0xB6 + 0x07 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter3 + High EQ deck 2 + 0xB6 + 0x08 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter2 + Mid EQ deck 1 + 0xB6 + 0x0B + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter2 + Mid EQ deck 2 + 0xB6 + 0x0C + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter1 + Low EQ deck 1 + 0xB6 + 0x0F + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter1 + Low EQ deck 2 + 0xB6 + 0x10 + + + + + + [Channel1] + volume + Volume deck 1 + 0xB6 + 0x13 + + + + + + [Auxiliary1] + DDJERGO.micAuxGain + Aux gain + 0xB6 + 0x14 + + + + + + [Channel2] + volume + Volume deck 2 + 0xB6 + 0x15 + + + + + + [QuickEffectRack1_[Channel1]] + super1 + Adjusts the intensity of the filter effect deck 1 + 0xB6 + 0x1B + + + + + + [QuickEffectRack1_[Channel2]] + super1 + Adjusts the intensity of the filter effect deck 2 + 0xB6 + 0x1C + + + + + + [Master] + crossfader + Adjusts the crossfader between players/decks + 0xB6 + 0x1F + + + + + + [Master] + gain + Adjust master volume + 0xB6 + 0x20 + + + + + + [Master] + headMix + Adjusts the cue/main mix in the headphone output. + 0xB6 + 0x21 + + + + + + [Master] + headGain + Adjusts the headphone output gain. + 0xB6 + 0x22 + + + + + + [Channel1] + pregain + Adjusts the gain of the input + 0xB6 + 0x23 + + + + + + [Channel2] + pregain + Adjusts the gain of the input + 0xB6 + 0x24 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter3 + High EQ deck 1 + 0xB6 + 0x27 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter3 + High EQ deck 2 + 0xB6 + 0x28 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter2 + Mid EQ deck 1 + 0xB6 + 0x2B + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter2 + Mid EQ deck 2 + 0xB6 + 0x2C + + + + + + [EqualizerRack1_[Channel1]_Effect1] + parameter1 + Low EQ deck 1 + 0xB6 + 0x2F + + + + + + [EqualizerRack1_[Channel2]_Effect1] + parameter1 + Low EQ deck 2 + 0xB6 + 0x30 + + + + + + [Channel1] + volume + Volume deck 1 + 0xB6 + 0x33 + + + + + + [Channel2] + volume + Volume deck 2 + 0xB6 + 0x35 + + + + + + [Master] + crossfader + Adjusts the crossfader between players/decks + 0xB6 + 0x3F + + + + + + [Library] + DDJERGO.browseLibrary + Move library up and down + 0xB6 + 0x40 + + + + + + [Library] + DDJERGO.browseSidebar + Open and close elements in the sidebar + 0xB6 + 0x64 + + + + + + + + [Channel1] + play_indicator + 0x90 + 0x0B + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + cue_indicator + 0x90 + 0x0C + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + keylock + 0x90 + 0x1A + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_1_enabled + 0x90 + 0x2E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_2_enabled + 0x90 + 0x2F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_3_enabled + 0x90 + 0x30 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_4_enabled + 0x90 + 0x31 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler1] + play + 0x90 + 0x3C + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler1] + play + 0x90 + 0x3D + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler2] + play + 0x90 + 0x3E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler2] + play + 0x90 + 0x3F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler3] + play + 0x90 + 0x40 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler3] + play + 0x90 + 0x41 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler4] + play + 0x90 + 0x42 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler4] + play + 0x90 + 0x43 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + sync_enabled + 0x90 + 0x58 + 1.0 + 0.1 + + + [Channel1] + hotcue_1_enabled + 0x90 + 0x5F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_2_enabled + 0x90 + 0x60 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_3_enabled + 0x90 + 0x61 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + hotcue_4_enabled + 0x90 + 0x62 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + play + 0x90 + 0x6E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + play_indicator + 0x91 + 0x0B + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + cue_indicator + 0x91 + 0x0C + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + keylock + 0x91 + 0x1A + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_1_enabled + 0x91 + 0x2E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_2_enabled + 0x91 + 0x2F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_3_enabled + 0x91 + 0x30 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_4_enabled + 0x91 + 0x31 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler5] + play + 0x91 + 0x3C + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler5] + play + 0x91 + 0x3D + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler6] + play + 0x91 + 0x3E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler6] + play + 0x91 + 0x3F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler7] + play + 0x91 + 0x40 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler7] + play + 0x91 + 0x41 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler8] + play + 0x91 + 0x42 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Sampler8] + play + 0x91 + 0x43 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + sync_enabled + 0x91 + 0x58 + 1.0 + 0.1 + + + [Channel2] + hotcue_1_enabled + 0x91 + 0x5F + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_2_enabled + 0x91 + 0x60 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_3_enabled + 0x91 + 0x61 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + hotcue_4_enabled + 0x91 + 0x62 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + play + 0x91 + 0x6E + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + pfl + 0x96 + 0x54 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel2] + pfl + 0x96 + 0x55 + 0x7F + 0x00 + 1.0 + 0.1 + + + [Channel1] + track_loaded + 0x9B + 0x0C + 0x7F + 1.0 + 0.1 + + + [Channel2] + track_loaded + 0x9B + 0x0D + 0x7F + 0x00 + 1.0 + 0.1 + + + +