diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index f8f79c6215e..16c86be2068 100644 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -3,7 +3,7 @@ Pioneer DDJ-200 Dan Giddins, Frank.Breitling at gmx.de - 2-deck USB and Bluetooth MIDI controller. + 2-deck USB and Bluetooth MIDI controller with support for 4-deck mode. https://mixxx.discourse.group/t/pioneer-ddj-200-mapping/18259 pioneer_ddj_200 @@ -12,37 +12,134 @@ + + [Master] + crossfader + Master crossfader + 0xB6 + 0x1F + + + + + + + [Master] + crossfader + Master crossfader + 0xB6 + 0x3F + + + + + + + + [Master] + DDJ200.headmix + Headphones master as headMix knob + 0x96 + 0x63 + + + + + + [Master] + DDJ200.toggleFourDeckMode + Headphones master + shift + 0x96 + 0x78 + + + + + + + [Channel1] + DDJ200.shiftLeft + Deck 1: Shift pressed + 0x90 + 0x3F + + + + [Channel2] - sync_enabled - Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + DDJ200.shiftRight + Deck 2: Shift pressed 0x91 - 0x58 + 0x3F - + + + + + + [Channel1] + DDJ200.pfl + Deck 1: Headphone listen (pfl) button + 0x90 + 0x54 + + + + + + [Channel1] + DDJ200.toggleDeck + Deck 1: Headphone (pfl) + shift + 0x90 + 0x68 + + + + + + + [Channel2] + DDJ200.pfl + Deck 2: Headphone listen (pfl) button + 0x91 + 0x54 + + + + + + [Channel2] + DDJ200.toggleDeck + Deck 2: Headphone (pfl) + shift + 0x91 + 0x68 + + + [Channel1] - sync_enabled + DDJ200.syncEnabled Deck 1: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x90 0x58 - + - [Master] - crossfader - Master crossfader - 0xB6 - 0x3F + [Channel2] + DDJ200.syncEnabled + Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + 0x91 + 0x58 - - + + [Channel2] DDJ200.seek @@ -63,6 +160,7 @@ + [AutoDJ] enabled @@ -83,6 +181,7 @@ + [Channel2] DDJ200.touch @@ -103,17 +202,43 @@ + + - [EqualizerRack1_[Channel2]_Effect1] - parameter2 - Deck 2: Adjust Mid EQ - 0xB1 - 0x2B + [EqualizerRack1_[Channel1]_Effect1] + + DDJ200.eq + Deck 1: Adjust Low EQ + 0xB0 + 0x0F - + + + + [EqualizerRack1_[Channel1]_Effect1] + + DDJ200.eq + Deck 1: Adjust Mid EQ + 0xB0 + 0x0B + + + + + + - [EqualizerRack1_[Channel2]_Effect1] - parameter3 - Deck 2: Adjust High EQ - 0xB1 + [EqualizerRack1_[Channel1]_Effect1] + DDJ200.eq + + Deck 1: Adjust High EQ + 0xB0 0x07 - + + - + + + + [QuickEffectRack1_[Channel1]] + DDJ200.super1 + Super Knob (msb): control linked effect + 0xB6 + 0x17 + + + + + - [Channel2] - bpm_tap - Deck 2: BPM tap button - 0x91 - 0x60 + [EqualizerRack1_[Channel2]_Effect1] + + DDJ200.eq + Deck 2: Adjust Low EQ + 0xB1 + 0x0F - + + + + + + + [EqualizerRack1_[Channel2]_Effect1] + + DDJ200.eq + Deck 2: Adjust Mid EQ + 0xB1 + 0x0B + + + + + + + + [EqualizerRack1_[Channel2]_Effect1] + + DDJ200.eq + Deck 2: Adjust High EQ + 0xB1 + 0x07 + + + + + [QuickEffectRack1_[Channel2]] - super1 + DDJ200.super1 Quick Effect: Quick Effect Super Knob (control linked effect parameters) 0xB6 0x18 - + + + [Channel1] bpm_tap @@ -175,136 +375,171 @@ [Channel2] - volume - Deck 2: Volume Fader - 0xB1 - 0x33 + bpm_tap + Deck 2: BPM tap button + 0x91 + 0x60 - + + [Channel1] - volume + + DDJ200.volumeMSB Deck 1: Volume Fader 0xB0 - 0x33 + 0x13 - + + - [Channel2] - cue_gotoandstop - Deck 2: Go to cue point and stop - 0x91 - 0x48 + [Channel1] + DDJ200.volumeLSB + Deck 1: Volume Fader + 0xB0 + 0x33 - + + - [Channel1] - cue_gotoandstop - Deck 1: Go to cue point and stop - 0x90 - 0x48 + [Channel2] + DDJ200.volumeMSB + Deck 2: Volume Fader + 0xB1 + 0x13 - + + - [EqualizerRack1_[Channel2]_Effect1] - parameter1 - Deck 2: Adjust Low EQ + [Channel2] + DDJ200.volumeLSB + Deck 2: Volume Fader 0xB1 - 0x2F + 0x33 - + + + - [EqualizerRack1_[Channel1]_Effect1] - parameter1 - Deck 1: Adjust Low EQ - 0xB0 - 0x2F + [Channel1] + DDJ200.play + Deck 1: Play button + 0x90 + 0x0B - + [Channel2] - play + DDJ200.play Deck 2: Play button 0x91 0x0B - + + + + + + [Channel1] + + DDJ200.cueDefault + Deck 1: Cue button + 0x90 + 0x0C + + [Channel2] - rate - Deck 2: Playback speed control - 0xB1 - 0x20 + DDJ200.cueDefault + Deck 2: Cue button + 0x91 + 0x0C - - + [Channel1] - play - Deck 1: Play button + DDJ200.cueGotoandstop + Deck 1: Go to cue point and stop 0x90 - 0x0B + 0x48 - + + + + + [Channel2] + DDJ200.cueGotoandstop + Deck 2: Go to cue point and stop + 0x91 + 0x48 + + + [Channel1] - rate + DDJ200.rateMSB Deck 1: Playback speed control 0xB0 - 0x20 + 0x00 + - + - [Channel2] - cue_default - Deck 2: Cue button - 0x91 - 0x0C + [Channel1] + DDJ200.rateLSB + Deck 1: Playback speed control + 0xB0 + 0x20 - + + + - [Channel1] - cue_default - Deck 1: Cue button - 0x90 - 0x0C + [Channel2] + DDJ200.rateMSB + Deck 2: Playback speed control + 0xB1 + 0x00 - + + - [QuickEffectRack1_[Channel1]] - super1 - Quick Effect: Quick Effect Super Knob (control linked effect parameters) - 0xB6 - 0x37 + [Channel2] + DDJ200.rateLSB + Deck 2: Playback speed control + 0xB1 + 0x20 - + + + [Channel2] DDJ200.jog @@ -345,573 +580,361 @@ - - [Master] - crossfader - Master crossfader - 0xB6 - 0x1F - - - - - - - [Master] - DDJ200.headmix - Headphones master button as headMix knob - 0x96 - 0x63 - - - - + + [Channel2] - pfl - Deck 2: Headphone listen (pfl) button + cue_set + Deck 2: Set cue point 0x91 - 0x54 + 0x47 [Channel1] - pfl - Deck 1: Headphone listen (pfl) button + cue_set + Deck 1: Set cue point 0x90 - 0x54 + 0x47 + + - [EqualizerRack1_[Channel2]_Effect1] - parameter2 - Deck 2: Adjust Mid EQ - 0xB1 - 0x0B + [Channel1] + DDJ200.hotcueNActivate + Hotcue 1, Deck 1: Set, preview, jump to + 0x97 + 0x00 - + - [EqualizerRack1_[Channel1]_Effect1] - parameter2 - Deck 1: Adjust Mid EQ - 0xB0 - 0x0B + [Channel1] + DDJ200.hotcueNActivate + Hotcue 2, Deck 1: Set, preview, jump to + 0x97 + 0x01 - + [Channel1] - hotcue_1_activate - Deck 1: Set, preview from or jump to hotcue 1 + DDJ200.hotcueNActivate + Hotcue 3, Deck 1: Set, preview, jump to 0x97 - 0x00 + 0x02 - + [Channel1] - hotcue_2_activate - Deck 1: Set, preview from or jump to hotcue 2 + DDJ200.hotcueNActivate + Hotcue 4, Deck 1: Set, preview, jump to 0x97 - 0x01 + 0x03 - + - [Channel2] - hotcue_1_activate - Deck 2: Set, preview from of jump to hotcue 1 - 0x99 - 0x00 + [Channel1] + DDJ200.hotcueNActivate + Hotcue 5, Deck 1: Set, preview, jump to + 0x97 + 0x04 - + [Channel1] - hotcue_1_clear - Deck 1: Clear hotcue 1 - 0x98 - 0x00 + DDJ200.hotcueNActivate + Hotcue 6, Deck 1: Set, preview, jump to + 0x97 + 0x05 - + [Channel1] - hotcue_3_activate - Deck 1: Set, preview from or jump to hotcue 3 + DDJ200.hotcueNActivate + Hotcue 7, Deck 1: Set, preview, jump to 0x97 - 0x02 + 0x06 - + - [Channel2] - hotcue_1_clear - Deck 2: Clear hotcue 1 - 0x9A - 0x00 + [Channel1] + DDJ200.hotcueNActivate + Hotcue 8, Deck 1: Set, preview, jump to + 0x97 + 0x07 - + + + - [EqualizerRack1_[Channel2]_Effect1] - parameter3 - Deck 2: Adjust High EQ - 0xB1 - 0x27 + [Channel2] + DDJ200.hotcueNActivate + Hotcue 1, Deck 2: Set, preview, jump to + 0x99 + 0x00 - + [Channel2] - hotcue_2_activate - Deck 2: Set, preview from of jump to hotcue 2 + DDJ200.hotcueNActivate + Hotcue 2, Deck 2: Set, preview, jump to 0x99 0x01 - + - [EqualizerRack1_[Channel1]_Effect1] - parameter3 - Deck 1: Adjust High EQ - 0xB0 - 0x27 + [Channel2] + DDJ200.hotcueNActivate + Hotcue 3, Deck 2: Set, preview, jump to + 0x99 + 0x02 - + - [Channel1] - hotcue_2_clear - Deck 1: Clear hotcue 2 - 0x98 - 0x01 + [Channel2] + DDJ200.hotcueNActivate + Hotcue 4, Deck 2: Set, preview, jump to + 0x99 + 0x03 - + [Channel2] - volume - Deck 2: Volume Fader - 0xB1 - 0x13 + DDJ200.hotcueNActivate + Hotcue 5, Deck 2: Set, preview, jump to + 0x99 + 0x04 - + - [Channel1] - hotcue_4_activate - Deck 1: Set, preview from or jump to hotcue 4 - 0x97 - 0x03 + [Channel2] + DDJ200.hotcueNActivate + Hotcue 6, Deck 2: Set, preview, jump to + 0x99 + 0x05 - + - [Channel1] - volume - Deck 1: Volume Fader - 0xB0 - 0x13 + [Channel2] + DDJ200.hotcueNActivate + Hotcue 7, Deck 2: Set, preview, jump to + 0x99 + 0x06 - + [Channel2] - hotcue_2_clear - Deck 2: Clear hotcue 2 - 0x9A - 0x01 + DDJ200.hotcueNActivate + Hotcue 8, Deck 2: Set, preview, jump to + 0x99 + 0x07 - + + - [QuickEffectRack1_[Channel2]] - super1 - Quick Effect: Quick Effect Super Knob (control linked effect parameters) - 0xB6 - 0x38 + [Channel1] + + DDJ200.hotcueNClear + Hotcue 1, Deck 1: Clear + 0x98 + 0x00 - + - [Channel2] - hotcue_3_activate - Deck 2: Set, preview from of jump to hotcue 3 - 0x99 - 0x02 + [Channel1] + DDJ200.hotcueNClear + Hotcue 2, Deck 1: Clear + 0x98 + 0x01 - + [Channel1] - hotcue_3_clear - Deck 1: Clear hotcue 3 + DDJ200.hotcueNClear + Hotcue 3, Deck 1: Clear 0x98 0x02 - + [Channel1] - hotcue_5_activate - Deck 1: Set, preview from or jump to hotcue 5 - 0x97 - 0x04 + DDJ200.hotcueNClear + Hotcue 4, Deck 1: Clear + 0x98 + 0x03 - - - - - [Channel2] - hotcue_3_clear - Deck 2: Clear hotcue 3 - 0x9A - 0x02 - - - - - - [EqualizerRack1_[Channel2]_Effect1] - parameter1 - Deck 2: Adjust Low EQ - 0xB1 - 0x0F - - - - - - [Channel2] - hotcue_4_activate - Deck 2: Set, preview from of jump to hotcue 4 - 0x99 - 0x03 - - - - - - [EqualizerRack1_[Channel1]_Effect1] - parameter1 - Deck 1: Adjust Low EQ - 0xB0 - 0x0F - - + [Channel1] - hotcue_4_clear - Deck 1: Clear hotcue 4 + DDJ200.hotcueNClear + Hotcue 5, Deck 1: Clear 0x98 - 0x03 - - - - - - [Channel1] - hotcue_6_activate - Deck 1: Set, preview from or jump to hotcue 6 - 0x97 - 0x05 - - - - - - [Channel2] - hotcue_4_clear - Deck 2: Clear hotcue 4 - 0x9A - 0x03 - - - - - - [Channel2] - rate - Deck 2: Playback speed control - 0xB1 - 0x00 - - - - - - - [Channel2] - hotcue_5_activate - Deck 2: Set, preview from of jump to hotcue 5 - 0x99 0x04 - - - - - [Channel1] - rate - Deck 1: Playback speed control - 0xB0 - 0x00 - - - + [Channel1] - hotcue_5_clear - Deck 1: Clear hotcue 5 + DDJ200.hotcueNClear + Hotcue 6, Deck 1: Clear 0x98 - 0x04 - - - - - - [Channel1] - hotcue_7_activate - Deck 1: Set, preview from or jump to hotcue 7 - 0x97 - 0x06 - - - - - - [Channel2] - hotcue_5_clear - Deck 2: Clear hotcue 5 - 0x9A - 0x04 - - - - - - [QuickEffectRack1_[Channel1]] - super1 - Quick Effect: Quick Effect Super Knob (control linked effect parameters) - 0xB6 - 0x17 - - - - - - [Channel2] - hotcue_6_activate - Deck 2: Set, preview from of jump to hotcue 6 - 0x99 0x05 - + [Channel1] - hotcue_6_clear - Deck 1: Clear hotcue 6 + DDJ200.hotcueNClear + Hotcue 7, Deck 1: Clear 0x98 - 0x05 + 0x06 - + [Channel1] - hotcue_8_activate - Deck 1: Set, preview from or jump to hotcue 8 - 0x97 + DDJ200.hotcueNClear + Hotcue 8, Deck 1: Clear + 0x98 0x07 - + + [Channel2] - hotcue_6_clear - Deck 2: Clear hotcue 6 + + DDJ200.hotcueNClear + Hotcue 1, Deck 2: Clear 0x9A - 0x05 + 0x00 - + [Channel2] - hotcue_7_activate - Deck 2: Set, preview from of jump to hotcue 7 - 0x99 - 0x06 - - - - - - [Channel1] - hotcue_7_clear - Deck 1: Clear hotcue 7 - 0x98 - 0x06 + DDJ200.hotcueNClear + Hotcue 2, Deck 2: Clear + 0x9A + 0x01 - + [Channel2] - hotcue_7_clear - Deck 2: Clear hotcue 7 + DDJ200.hotcueNClear + Hotcue 3, Deck 2: Clear 0x9A - 0x06 + 0x02 - + [Channel2] - hotcue_8_activate - Deck 2: Set, preview from of jump to hotcue 8 - 0x99 - 0x07 + DDJ200.hotcueNClear + Hotcue 4, Deck 2: Clear + 0x9A + 0x03 - + - [Channel1] - hotcue_8_clear - Deck 1: Clear hotcue 8 - 0x98 - 0x07 + [Channel2] + DDJ200.hotcueNClear + Hotcue 5, Deck 2: Clear + 0x9A + 0x04 - + [Channel2] - cue_set - Deck 2: Set cue point - 0x91 - 0x47 + DDJ200.hotcueNClear + Hotcue 6, Deck 2: Clear + 0x9A + 0x05 - + - [Channel1] - cue_set - Deck 1: Set cue point - 0x90 - 0x47 + [Channel2] + DDJ200.hotcueNClear + Hotcue 7, Deck 2: Clear + 0x9A + 0x06 - + [Channel2] - hotcue_8_clear - Deck 2: Clear hotcue 8 + DDJ200.hotcueNClear + Hotcue 8, Deck 2: Clear 0x9A 0x07 - + + - - [Channel1] - play - Deck 1: Play LED - 0x90 - 0x0B - 0x7F - 0x00 - 0.5 - - - [Channel2] - play - Deck 2: Play LED - 0x91 - 0x0B - 0x7F - 0x00 - 0.5 - - - [Channel1] - sync_enabled - Deck 1: Beat sync LED - 0x90 - 0x58 - 0x7F - 0x00 - 0.5 - - - [Channel2] - sync_enabled - Deck 2: Beat sync LED - 0x91 - 0x58 - 0x7F - 0x00 - 0.5 - - - [Channel1] - cue_default - Deck 1: Cue LED - 0x90 - 0x0C - 0x7F - 0x00 - 0.5 - - - [Channel2] - cue_default - Deck 2: Cue LED - 0x91 - 0x0C - 0x7F - 0x00 - 0.5 - - + diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index a7b662bbd4f..c639c19fa14 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -1,41 +1,137 @@ var DDJ200 = { - jogDisabled: new Array(false, false, false, false, false) + fourDeckMode: false, + vDeckNo: [0, 1, 2], + vDeck: {}, + shiftPressed: {left: false, right: false}, + jogCounter: 0 }; -DDJ200.init = function() {}; +DDJ200.init = function() { + for (var i = 1; i <= 4; i++) { -DDJ200.shutdown = function() {}; + // create associative arrays for 4 virtual decks + this.vDeck[i] = { + syncEnabled: false, + volMSB: 0, + rateMSB: 0, + jogEnabled: true, + }; -DDJ200.scratch = function(channel, control, value, status, group) { + var vgroup = "[Channel" + i + "]"; + + // run onTrackLoad after every track load to set LEDs accordingly + engine.makeConnection(vgroup, "track_loaded", function(ch, vgroup) { + DDJ200.onTrackLoad(ch, vgroup); + }); + + // set Pioneer CDJ cue mode for all decks + engine.setValue(vgroup, "cue_cdj", true); + } + + DDJ200.LEDsOff(); + + // start with focus on library for selecting tracks (delay seems required) + engine.beginTimer(500, function() { + engine.setValue("[Library]", "MoveFocus", 1); + }, true); +}; + +DDJ200.shutdown = function() { + DDJ200.LEDsOff(); +}; + +DDJ200.LEDsOff = function() { // trun off LED buttons: + + for (var i = 0; i <= 1; i++) { + midi.sendShortMsg(0x96 + i, 0x63, 0x00); // set headphone master + midi.sendShortMsg(0x90 + i, 0x54, 0x00); // pfl headphone + midi.sendShortMsg(0x90 + i, 0x58, 0x00); // beat sync + midi.sendShortMsg(0x90 + i, 0x0B, 0x00); // play + midi.sendShortMsg(0x90 + i, 0x0C, 0x00); // cue + for (var j = 0; j <= 8; j++) { + midi.sendShortMsg(0x97 + 2 * i, j, 0x00); // hotcue + } + } +}; + +DDJ200.onTrackLoad = function(channel, vgroup) { + // set LEDs (hotcues, etc.) for the loaded deck + // if controller is switched to this deck + var vDeckNo = script.deckFromGroup(vgroup); + var deckNo = (vDeckNo % 2) ? 1 : 2; + if (vDeckNo === DDJ200.vDeckNo[deckNo]) { + DDJ200.switchLEDs(vDeckNo); + } +}; + +DDJ200.LoadSelectedTrack = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var deckNo = script.deckFromGroup(group); + var vDeckNo = DDJ200.vDeckNo[deckNo]; + var vgroup = "[Channel" + vDeckNo + "]"; + script.triggerControl(vgroup, "LoadSelectedTrack", true); + } +}; + +DDJ200.browseTracks = function(value) { + DDJ200.jogCounter += value - 64; + if (DDJ200.jogCounter > 9) { + engine.setValue("[Library]", "MoveDown", true); + DDJ200.jogCounter = 0; + } else if (DDJ200.jogCounter < -9) { + engine.setValue("[Library]", "MoveUp", true); + DDJ200.jogCounter = 0; + } +}; + +DDJ200.shiftLeft = function() { + // toggle shift left pressed variable + DDJ200.shiftPressed["left"] = ! DDJ200.shiftPressed["left"]; +}; + +DDJ200.shiftRight = function() { + // toggle shift right pressed variable + DDJ200.shiftPressed["right"] = ! DDJ200.shiftPressed["right"]; +}; + +DDJ200.jog = function(channel, control, value, status, group) { // For a control that centers on 0x40 (64): // Convert value down to +1/-1 // Register the movement - engine.scratchTick(script.deckFromGroup(group), value - 64); + if (DDJ200.shiftPressed["left"]) { + DDJ200.browseTracks(value); + } else { + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + if (DDJ200.vDeck[vDeckNo]["jogEnabled"]) { + var vgroup = "[Channel" + vDeckNo + "]"; + engine.setValue(vgroup, "jog", value - 64); + } + } }; -DDJ200.jog = function(channel, control, value, status, group) { +DDJ200.scratch = function(channel, control, value, status, group) { // For a control that centers on 0x40 (64): // Convert value down to +1/-1 // Register the movement - var deckNumber = script.deckFromGroup(group); - if (! DDJ200.jogDisabled[deckNumber]) { - engine.setValue(group, "jog", value - 64); - } + engine.scratchTick(DDJ200.vDeckNo[script.deckFromGroup(group)], + value - 64); }; DDJ200.touch = function(channel, control, value, status, group) { - var deckNumber = script.deckFromGroup(group); + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; if (value) { // enable scratch var alpha = 1.0 / 8; - engine.scratchEnable(deckNumber, 128, 33 + 1 / 3, alpha, alpha / 32); + engine.scratchEnable(vDeckNo, 128, 33 + 1 / 3, alpha, alpha / 32); + // disable jog not to prevent track alignment + DDJ200.vDeck[vDeckNo]["jogEnabled"] = false; } else { - // disable jog to not prevent alignment and enable it after 900 ms - DDJ200.jogDisabled[deckNumber] = true; - engine.beginTimer(900, "DDJ200.jogDisabled["+deckNumber+"] = false;", - true); + // enable jog after 900 ms again + engine.beginTimer(900, function() { + DDJ200.vDeck[vDeckNo]["jogEnabled"] = true; + }, true); // disable scratch - engine.scratchDisable(deckNumber); + engine.scratchDisable(vDeckNo); } }; @@ -46,14 +142,222 @@ DDJ200.seek = function(channel, control, value, status, group) { // of time given a constant turning angle. var duration = engine.getValue(group, "duration"); var newPos = Math.max(0, oldPos + ((value - 64) * 0.2 / duration)); - engine.setValue(group, "playposition", newPos); // Strip search + + var deckNo = script.deckFromGroup(group); + var vgroup = "[Channel" + DDJ200.vDeckNo[deckNo] + "]"; + engine.setValue(vgroup, "playposition", newPos); // Strip search }; DDJ200.headmix = function(channel, control, value) { - if (value) { + // toggle headMix knob between -1 to 1 + if (value) { // do nothing if button is released, i.e. value === 0 var masterMixEnabled = (engine.getValue("[Master]", "headMix") > 0); - // toggle headMix knob between values of -1 and 1 engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 1); midi.sendShortMsg(0x96, 0x63, masterMixEnabled ? 0x7F : 0); // set LED } }; + +DDJ200.toggleFourDeckMode = function(channel, control, value) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + DDJ200.fourDeckMode = !DDJ200.fourDeckMode; + if (DDJ200.fourDeckMode) { + midi.sendShortMsg(0x90, 0x54, 0x00); + midi.sendShortMsg(0x91, 0x54, 0x00); + } else { + DDJ200.vDeckNo[1] = 1; + DDJ200.vDeckNo[2] = 2; + DDJ200.switchLEDs(1); // set LEDs of controller deck + DDJ200.switchLEDs(2); // set LEDs of controller deck + } + } +}; + +DDJ200.play = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + var playing = engine.getValue(vgroup, "play"); + engine.setValue(vgroup, "play", ! playing); + if (engine.getValue(vgroup, "play") === playing) { + engine.setValue(vgroup, "play", !playing); + } + midi.sendShortMsg(status, 0x0B, engine.getValue(vgroup, "play") ? 0x7F : 0); + } +}; + +DDJ200.syncEnabled = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + var syncEnabled = ! engine.getValue(vgroup, "sync_enabled"); + DDJ200.vDeck[vDeckNo]["syncEnabled"] = syncEnabled; + engine.setValue(vgroup, "sync_enabled", syncEnabled); + midi.sendShortMsg(status, control, 0x7F * syncEnabled); // set LED + } +}; + +DDJ200.rateMSB = function(channel, control, value, status, group) { + // store most significant byte value of rate + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + DDJ200.vDeck[vDeckNo]["rateMSB"] = value; +}; + +DDJ200.rateLSB = function(channel, control, value, status, group) { + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + // calculte rate value from its most and least significant bytes + var rateMSB = DDJ200.vDeck[vDeckNo]["rateMSB"]; + var rate = 1 - (((rateMSB << 7) + value) / 0x1FFF); + engine.setValue(vgroup, "rate", rate); +}; + +DDJ200.volumeMSB = function(channel, control, value, status, group) { + // store most significant byte value of volume + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + DDJ200.vDeck[vDeckNo]["volMSB"] = value; +}; + +DDJ200.volumeLSB = function(channel, control, value, status, group) { + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + // calculte volume value from its most and least significant bytes + var volMSB = DDJ200.vDeck[vDeckNo]["volMSB"]; + var vol = ((volMSB << 7) + value) / 0x3FFF; + //var vol = ((volMSB << 7) + value); // use for linear correction + //vol = script.absoluteNonLin(vol, 0, 0.25, 1, 0, 0x3FFF); + engine.setValue(vgroup, "volume", vol); +}; + +DDJ200.eq = function(channel, control, value, status, group) { + var val = script.absoluteNonLin(value, 0, 1, 4); + var eq = (control === 0x0B) ? 2 : 1; + if (control === 0x07) { + eq = 3; + } + var deckNo = group.substring(24, 25); + // var deckNo = group.match("hannel.")[0].substring(6); // more general + // var deckNo = script.deckFromGroup(group); // working after fix + // https://github.com/mixxxdj/mixxx/pull/3178 only + var vDeckNo = DDJ200.vDeckNo[deckNo]; + var vgroup = group.replace("Channel" + deckNo, "Channel" + vDeckNo); + engine.setValue(vgroup, "parameter" + eq, val); +}; + +DDJ200.super1 = function(channel, control, value, status, group) { + var val = script.absoluteNonLin(value, 0, 0.5, 1); + var deckNo = group.substring(26, 27); + //var deckNo = group.match("hannel.")[0].substring(6); // more general + //var deckNo = script.deckFromGroup(group); // working after fix + // https://github.com/mixxxdj/mixxx/pull/3178 only + var vDeckNo = DDJ200.vDeckNo[deckNo]; + var vgroup = group.replace("Channel" + deckNo, "Channel" + vDeckNo); + engine.setValue(vgroup, "super1", val); +}; + +DDJ200.cueDefault = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + if (!DDJ200.vDeck[vDeckNo]["jogEnabled"]) { // if jog top is touched + engine.setValue(vgroup, "cue_set", true); + } else { + engine.setValue(vgroup, "cue_gotoandplay", true); + } + var cueSet = (engine.getValue(vgroup, "cue_point") !== -1); + midi.sendShortMsg(status, 0x0C, 0x7F * cueSet); // set cue LED + midi.sendShortMsg(status, 0x0B, 0x7F * // set play LED + engine.getValue(vgroup, "play")); + } +}; + +DDJ200.cueGotoandstop = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + engine.setValue(vgroup, "cue_gotoandstop", true); + //engine.setValue(vgroup, "start_stop", true); // go to start if prefered + midi.sendShortMsg(status, 0x0B, 0x7F * engine.getValue(vgroup, "play")); + } +}; + +DDJ200.hotcueNActivate = function(channel, control, value, status, group) { + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + var hotcue = "hotcue_" + (control + 1); + engine.setValue(vgroup, hotcue + "_activate", true); + midi.sendShortMsg(status, control, + 0x7F * engine.getValue(vgroup, hotcue + "_enabled")); + var deckNo = script.deckFromGroup(group); + midi.sendShortMsg(0x90 + deckNo - 1, 0x0B, 0x7F * + engine.getValue(vgroup, "play")); // set play LED +}; + +DDJ200.hotcueNClear = function(channel, control, value, status, group) { + var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; + var vgroup = "[Channel" + vDeckNo + "]"; + engine.setValue(vgroup, "hotcue_" + (control + 1) + "_clear", true); + midi.sendShortMsg(status-1, control, 0x00); // set hotcue LEDs +}; + +DDJ200.pfl = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + var deckNo = script.deckFromGroup(group); + var vDeckNo = DDJ200.vDeckNo[deckNo]; + var vgroup = "[Channel" + vDeckNo + "]"; + var pfl = ! engine.getValue(vgroup, "pfl"); + engine.setValue(vgroup, "pfl", pfl); + if (!DDJ200.fourDeckMode) { + midi.sendShortMsg(status, 0x54, 0x7F * pfl); // switch pfl LED + } + } +}; + +DDJ200.switchLEDs = function(vDeckNo) { + // set LEDs of controller deck 1 or 2 according to virtual deck + var d = (vDeckNo % 2) ? 0 : 1; // d = deckNo - 1 + var vgroup = "[Channel" + vDeckNo + "]"; + midi.sendShortMsg(0x90 + d, 0x0B, 0x7F * engine.getValue(vgroup, "play")); + midi.sendShortMsg(0x90 + d, 0x0C, 0x7F * + (engine.getValue(vgroup, "cue_point") !== -1)); + midi.sendShortMsg(0x90 + d, 0x58, 0x7F * engine.getValue(vgroup, + "sync_enabled")); + if (!DDJ200.fourDeckMode) { + midi.sendShortMsg(0x90 + d, 0x54, + 0x7F * engine.getValue(vgroup, "pfl")); + } + + for (var i = 1; i <= 8; i++) { + midi.sendShortMsg(0x97 + 2 * d, i - 1, 0x7F * engine.getValue( + vgroup, "hotcue_" + i + "_enabled")); + } +}; + +DDJ200.toggleDeck = function(channel, control, value, status, group) { + if (value) { // only if button pressed, not releases, i.e. value === 0 + if (DDJ200.shiftPressed["left"]) { + // left shift + pfl 1/2 does not toggle decks but loads track + DDJ200.LoadSelectedTrack(channel, control, value, status, group); + } else if (DDJ200.fourDeckMode) { //right shift + pfl 1/2 toggles + var deckNo = script.deckFromGroup(group); + var vDeckNo; + var led = 0x7F; + if (deckNo === 1) { + // toggle virtual deck of controller deck 1 + DDJ200.vDeckNo[1] = 4 - DDJ200.vDeckNo[1]; + if (DDJ200.vDeckNo[1] === 1) { + led = 0; + } + vDeckNo = DDJ200.vDeckNo[1]; + } else { // deckNo === 2 + // toggle virtual deck of controller deck 2 + DDJ200.vDeckNo[2] = 6 - DDJ200.vDeckNo[2]; + if (DDJ200.vDeckNo[2] === 2) { + led = 0; + } + vDeckNo = DDJ200.vDeckNo[2]; + } + midi.sendShortMsg(status, 0x54, led); // toggle virtual deck LED + DDJ200.switchLEDs(vDeckNo); // set LEDs of controller deck + } + } +};