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
-
+
+
-
-
-
-
-
-
-
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
+ }
+ }
+};