diff --git a/res/controllers/Hercules P32 DJ.midi.xml b/res/controllers/Hercules P32 DJ.midi.xml
index d9fd7f4b39e4..203ac3aff2c6 100644
--- a/res/controllers/Hercules P32 DJ.midi.xml
+++ b/res/controllers/Hercules P32 DJ.midi.xml
@@ -41,6 +41,78 @@
+
+ [Channel1]
+ P32.leftDeck.leftEncoder.input
+ 0xB1
+ 0x0A
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.leftEncoder.input
+ 0xB4
+ 0x0A
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.leftEncoderPress.input
+ 0x91
+ 0x01
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.leftEncoderPress.input
+ 0x94
+ 0x01
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.rightEncoder.input
+ 0xB1
+ 0x05
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.rightEncoder.input
+ 0xB4
+ 0x05
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.rightEncoderPress.input
+ 0x91
+ 0x02
+
+
+
+
+
+ [Channel1]
+ P32.leftDeck.rightEncoderPress.input
+ 0x94
+ 0x02
+
+
+
+
[Channel1]
P32.leftDeck.loopIn.input
@@ -61,7 +133,7 @@
[Channel1]
- P32.leftDeck.loopTogglePad.input
+ P32.leftDeck.reloop.input
0x91
0x52
@@ -88,7 +160,7 @@
[Channel1]
- P32.leftDeck.loopTogglePad.input
+ P32.leftDeck.reloop.input
0x94
0x52
@@ -485,7 +557,7 @@
[Channel1]
- P32.leftDeck.effectUnit.showParametersButton.input
+ P32.leftDeck.effectUnit.effectFocusButton.input
0x91
0x06
@@ -521,7 +593,7 @@
[Channel1]
- P32.leftDeck.effectUnit.showParametersButton.input
+ P32.leftDeck.effectUnit.effectFocusButton.input
0x94
0x06
@@ -530,279 +602,180 @@
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel1.input
+ P32.leftDeck.play.input
0x91
- 0x40
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel1.input
- 0x94
- 0x40
+ 0x0A
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel2.input
+ P32.leftDeck.cue.input
0x91
- 0x41
+ 0x09
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel2.input
+ P32.leftDeck.cue.input
0x94
- 0x41
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel3.input
- 0x91
- 0x42
+ 0x09
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel3.input
+ P32.leftDeck.play.input
0x94
- 0x42
+ 0x0A
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel4.input
+ P32.leftDeck.sync.input
0x91
- 0x43
+ 0x08
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Channel4.input
+ P32.leftDeck.sync.input
0x94
- 0x43
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Headphone.input
- 0x91
- 0x34
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Master.input
- 0x91
- 0x35
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Microphone.input
- 0x91
- 0x36
+ 0x08
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Auxiliary1.input
+ P32.leftDeck.tempSlow.input
0x91
- 0x37
-
-
-
-
-
- [Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Headphone.input
- 0x94
- 0x34
+ 0x44
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Master.input
+ P32.leftDeck.tempSlow.input
0x94
- 0x35
+ 0x44
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Microphone.input
- 0x94
- 0x36
+ P32.leftDeck.tempFast.input
+ 0x91
+ 0x45
[Channel1]
- P32.leftDeck.effectUnit.enableOnChannelButtons.Auxiliary1.input
+ P32.leftDeck.tempFast.input
0x94
- 0x37
-
-
-
-
-
- [Channel1]
- P32.leftDeck.loopMoveEncoder
- 0xB4
- 0x0A
-
-
-
-
-
- [Channel1]
- P32.leftDeck.play.input
- 0x91
- 0x0A
+ 0x45
[Channel1]
- P32.leftDeck.cue.input
+ P32.leftDeck.alignBeats.input
0x91
- 0x09
-
-
-
-
-
- [Channel1]
- P32.leftDeck.cue.input
- 0x94
- 0x09
+ 0x46
[Channel1]
- P32.leftDeck.play.input
+ P32.leftDeck.alignBeats.input
0x94
- 0x0A
+ 0x46
[Channel1]
- P32.leftDeck.sync.input
+ P32.leftDeck.enableEffectUnitButtons[0].input
0x91
- 0x08
+ 0x40
[Channel1]
- P32.leftDeck.sync.input
+ P32.leftDeck.enableEffectUnitButtons[0].input
0x94
- 0x08
+ 0x40
[Channel1]
- P32.leftDeck.tempSlow.input
+ P32.leftDeck.enableEffectUnitButtons[1].input
0x91
- 0x44
+ 0x41
[Channel1]
- P32.leftDeck.tempSlow.input
+ P32.leftDeck.enableEffectUnitButtons[1].input
0x94
- 0x44
-
-
-
-
-
- [Channel1]
- P32.leftDeck.tempFast.input
- 0x91
- 0x45
+ 0x41
[Channel1]
- P32.leftDeck.tempFast.input
+ P32.leftDeck.enableEffectUnitButtons[2].input
0x94
- 0x45
+ 0x3C
[Channel1]
- P32.leftDeck.alignBeats.input
+ P32.leftDeck.enableEffectUnitButtons[2].input
0x91
- 0x46
-
-
-
-
-
- [Channel1]
- P32.leftDeck.alignBeats.input
- 0x94
- 0x46
+ 0x3C
[Channel1]
- P32.leftDeck.quantize.input
+ P32.leftDeck.enableEffectUnitButtons[3].input
0x91
- 0x47
+ 0x3D
[Channel1]
- P32.leftDeck.quantize.input
+ P32.leftDeck.enableEffectUnitButtons[3].input
0x94
- 0x47
+ 0x3D
@@ -816,15 +789,6 @@
-
- [Channel1]
- P32.leftDeck.tempoEncoder
- 0xB1
- 0x05
-
-
-
-
[Channel1]
P32.leftDeck.eqKnob[3].input
@@ -852,15 +816,6 @@
-
- [Channel1]
- P32.leftDeck.beatJumpEncoder
- 0xB4
- 0x05
-
-
-
-
[Playlist]
P32.browseEncoder
@@ -908,13 +863,22 @@
[Channel1]
- P32.leftDeck.loadTrack
+ P32.leftDeck.loadTrack.input
0x91
0x0F
+
+ [Channel1]
+ P32.leftDeck.loadTrack.input
+ 0x94
+ 0x0F
+
+
+
+
[Channel1]
P32.leftDeck.volume.input
@@ -943,63 +907,63 @@
- [Recording]
- P32.slipButton.input
- 0x90
- 0x03
+ [Channel1]
+ P32.rightDeck.leftEncoder.input
+ 0xB2
+ 0x05
[Channel1]
- P32.leftDeck.tempoEncoderPress
- 0x91
- 0x02
+ P32.rightDeck.leftEncoder.input
+ 0xB5
+ 0x05
[Channel1]
- P32.leftDeck.ejectTrack
- 0x94
- 0x0F
+ P32.rightDeck.leftEncoderPress.input
+ 0x92
+ 0x02
[Channel1]
- P32.leftDeck.volume.input
- 0xB4
- 0x01
+ P32.rightDeck.leftEncoderPress.input
+ 0x95
+ 0x02
[Channel1]
- P32.leftDeck.loopToggleEncoderPress
- 0x91
- 0x01
+ P32.rightDeck.rightEncoder.input
+ 0xB2
+ 0x0A
[Channel1]
- P32.leftDeck.beatJumpEncoderPress
- 0x94
- 0x02
+ P32.rightDeck.rightEncoder.input
+ 0xB5
+ 0x0A
[Channel1]
- P32.leftDeck.loopEncoderManualLoopPress
- 0x94
+ P32.rightDeck.rightEncoderPress.input
+ 0x92
0x01
@@ -1007,18 +971,27 @@
[Channel1]
- P32.leftDeck.loopSizeEncoder.input
- 0xB1
- 0x0A
+ P32.rightDeck.rightEncoderPress.input
+ 0x95
+ 0x01
+
+
+
+
+
+ [Recording]
+ P32.slipButton.input
+ 0x90
+ 0x03
[Channel1]
- P32.rightDeck.loopMoveEncoder
- 0xB5
- 0x0A
+ P32.leftDeck.volume.input
+ 0xB4
+ 0x01
@@ -1072,43 +1045,25 @@
[Channel1]
P32.rightDeck.sync.input
0x95
- 0x08
-
-
-
-
-
- [Channel1]
- P32.rightDeck.shiftButton
- 0x92
- 0x07
-
-
-
-
-
- [Channel1]
- P32.rightDeck.tempoEncoder
- 0xB2
- 0x05
+ 0x08
[Channel1]
- P32.rightDeck.eqKnob[3].input
- 0xB2
- 0x04
+ P32.rightDeck.shiftButton
+ 0x92
+ 0x07
[Channel1]
- P32.rightDeck.beatJumpEncoder
- 0xB5
- 0x05
+ P32.rightDeck.eqKnob[3].input
+ 0xB2
+ 0x04
@@ -1169,7 +1124,7 @@
[Channel1]
- P32.rightDeck.loadTrack
+ P32.rightDeck.loadTrack.input
0x92
0x0F
@@ -1178,34 +1133,7 @@
[Channel1]
- P32.rightDeck.volume.input
- 0xB2
- 0x01
-
-
-
-
-
- [Channel1]
- P32.rightDeck.eqKnob[1].input
- 0xB5
- 0x02
-
-
-
-
-
- [Channel1]
- P32.rightDeck.tempoEncoderPress
- 0x92
- 0x02
-
-
-
-
-
- [Channel1]
- P32.rightDeck.ejectTrack
+ P32.rightDeck.loadTrack.input
0x95
0x0F
@@ -1215,16 +1143,7 @@
[Channel1]
P32.rightDeck.volume.input
- 0xB5
- 0x01
-
-
-
-
-
- [Channel1]
- P32.rightDeck.loopToggleEncoderPress
- 0x92
+ 0xB2
0x01
@@ -1232,8 +1151,8 @@
[Channel1]
- P32.rightDeck.beatJumpEncoderPress
- 0x95
+ P32.rightDeck.eqKnob[1].input
+ 0xB5
0x02
@@ -1241,22 +1160,13 @@
[Channel1]
- P32.rightDeck.loopEncoderManualLoopPress
- 0x95
+ P32.rightDeck.volume.input
+ 0xB5
0x01
-
- [Channel1]
- P32.rightDeck.loopSizeEncoder.input
- 0xB2
- 0x0A
-
-
-
-
[Channel1]
P32.rightDeck.hotcueButton[1].input
@@ -1647,7 +1557,7 @@
[Channel1]
- P32.rightDeck.effectUnit.showParametersButton.input
+ P32.rightDeck.effectUnit.effectFocusButton.input
0x92
0x06
@@ -1683,157 +1593,13 @@
[Channel1]
- P32.rightDeck.effectUnit.showParametersButton.input
+ P32.rightDeck.effectUnit.effectFocusButton.input
0x95
0x06
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Headphone.input
- 0x92
- 0x34
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Master.input
- 0x92
- 0x35
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Microphone.input
- 0x92
- 0x36
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Auxiliary1.input
- 0x92
- 0x37
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Headphone.input
- 0x95
- 0x34
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Master.input
- 0x95
- 0x35
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Microphone.input
- 0x95
- 0x36
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Auxiliary1.input
- 0x95
- 0x37
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel1.input
- 0x92
- 0x40
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel1.input
- 0x95
- 0x40
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel2.input
- 0x92
- 0x41
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel2.input
- 0x95
- 0x41
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel3.input
- 0x92
- 0x42
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel3.input
- 0x95
- 0x42
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel4.input
- 0x92
- 0x43
-
-
-
-
-
- [Channel1]
- P32.rightDeck.effectUnit.enableOnChannelButtons.Channel4.input
- 0x95
- 0x43
-
-
-
-
[Channel1]
P32.leftDeck.samplerButton[1].input
@@ -1872,7 +1638,7 @@
[Channel1]
- P32.leftDeck.samplerButton[5].input
+ P32.leftDeck.samplerButton[9].input
0x91
0x2C
@@ -1881,7 +1647,7 @@
[Channel1]
- P32.leftDeck.samplerButton[6].input
+ P32.leftDeck.samplerButton[10].input
0x91
0x2D
@@ -1890,7 +1656,7 @@
[Channel1]
- P32.leftDeck.samplerButton[7].input
+ P32.leftDeck.samplerButton[11].input
0x91
0x2E
@@ -1899,7 +1665,7 @@
[Channel1]
- P32.leftDeck.samplerButton[8].input
+ P32.leftDeck.samplerButton[12].input
0x91
0x2F
@@ -1908,7 +1674,7 @@
[Channel1]
- P32.leftDeck.samplerButton[9].input
+ P32.leftDeck.samplerButton[17].input
0x91
0x28
@@ -1917,7 +1683,7 @@
[Channel1]
- P32.leftDeck.samplerButton[10].input
+ P32.leftDeck.samplerButton[18].input
0x91
0x29
@@ -1926,7 +1692,7 @@
[Channel1]
- P32.leftDeck.samplerButton[11].input
+ P32.leftDeck.samplerButton[19].input
0x91
0x2A
@@ -1935,7 +1701,7 @@
[Channel1]
- P32.leftDeck.samplerButton[12].input
+ P32.leftDeck.samplerButton[20].input
0x91
0x2B
@@ -1944,7 +1710,7 @@
[Channel1]
- P32.leftDeck.samplerButton[13].input
+ P32.leftDeck.samplerButton[25].input
0x91
0x24
@@ -1953,7 +1719,7 @@
[Channel1]
- P32.leftDeck.samplerButton[14].input
+ P32.leftDeck.samplerButton[26].input
0x91
0x25
@@ -1962,7 +1728,7 @@
[Channel1]
- P32.leftDeck.samplerButton[15].input
+ P32.leftDeck.samplerButton[27].input
0x91
0x26
@@ -1971,7 +1737,7 @@
[Channel1]
- P32.leftDeck.samplerButton[16].input
+ P32.leftDeck.samplerButton[28].input
0x91
0x27
@@ -2016,7 +1782,7 @@
[Channel1]
- P32.leftDeck.samplerButton[5].input
+ P32.leftDeck.samplerButton[9].input
0x94
0x2C
@@ -2025,7 +1791,7 @@
[Channel1]
- P32.leftDeck.samplerButton[6].input
+ P32.leftDeck.samplerButton[10].input
0x94
0x2D
@@ -2034,7 +1800,7 @@
[Channel1]
- P32.leftDeck.samplerButton[7].input
+ P32.leftDeck.samplerButton[11].input
0x94
0x2E
@@ -2043,7 +1809,7 @@
[Channel1]
- P32.leftDeck.samplerButton[8].input
+ P32.leftDeck.samplerButton[12].input
0x94
0x2F
@@ -2052,7 +1818,7 @@
[Channel1]
- P32.leftDeck.samplerButton[9].input
+ P32.leftDeck.samplerButton[17].input
0x94
0x28
@@ -2061,7 +1827,7 @@
[Channel1]
- P32.leftDeck.samplerButton[10].input
+ P32.leftDeck.samplerButton[18].input
0x94
0x29
@@ -2070,7 +1836,7 @@
[Channel1]
- P32.leftDeck.samplerButton[11].input
+ P32.leftDeck.samplerButton[19].input
0x94
0x2A
@@ -2079,7 +1845,7 @@
[Channel1]
- P32.leftDeck.samplerButton[12].input
+ P32.leftDeck.samplerButton[20].input
0x94
0x2B
@@ -2088,7 +1854,7 @@
[Channel1]
- P32.leftDeck.samplerButton[13].input
+ P32.leftDeck.samplerButton[25].input
0x94
0x24
@@ -2097,7 +1863,7 @@
[Channel1]
- P32.leftDeck.samplerButton[14].input
+ P32.leftDeck.samplerButton[26].input
0x94
0x25
@@ -2106,7 +1872,7 @@
[Channel1]
- P32.leftDeck.samplerButton[15].input
+ P32.leftDeck.samplerButton[27].input
0x94
0x26
@@ -2115,7 +1881,7 @@
[Channel1]
- P32.leftDeck.samplerButton[16].input
+ P32.leftDeck.samplerButton[28].input
0x94
0x27
@@ -2124,7 +1890,7 @@
[Channel1]
- P32.rightDeck.samplerButton[17].input
+ P32.rightDeck.samplerButton[5].input
0x92
0x30
@@ -2133,7 +1899,7 @@
[Channel1]
- P32.rightDeck.samplerButton[18].input
+ P32.rightDeck.samplerButton[6].input
0x92
0x31
@@ -2142,7 +1908,7 @@
[Channel1]
- P32.rightDeck.samplerButton[19].input
+ P32.rightDeck.samplerButton[7].input
0x92
0x32
@@ -2151,7 +1917,7 @@
[Channel1]
- P32.rightDeck.samplerButton[20].input
+ P32.rightDeck.samplerButton[8].input
0x92
0x33
@@ -2160,7 +1926,7 @@
[Channel1]
- P32.rightDeck.samplerButton[21].input
+ P32.rightDeck.samplerButton[13].input
0x92
0x2C
@@ -2169,7 +1935,7 @@
[Channel1]
- P32.rightDeck.samplerButton[22].input
+ P32.rightDeck.samplerButton[14].input
0x92
0x2D
@@ -2178,7 +1944,7 @@
[Channel1]
- P32.rightDeck.samplerButton[23].input
+ P32.rightDeck.samplerButton[15].input
0x92
0x2E
@@ -2187,7 +1953,7 @@
[Channel1]
- P32.rightDeck.samplerButton[24].input
+ P32.rightDeck.samplerButton[16].input
0x92
0x2F
@@ -2196,7 +1962,7 @@
[Channel1]
- P32.rightDeck.samplerButton[25].input
+ P32.rightDeck.samplerButton[21].input
0x92
0x28
@@ -2205,7 +1971,7 @@
[Channel1]
- P32.rightDeck.samplerButton[26].input
+ P32.rightDeck.samplerButton[22].input
0x92
0x29
@@ -2214,7 +1980,7 @@
[Channel1]
- P32.rightDeck.samplerButton[27].input
+ P32.rightDeck.samplerButton[23].input
0x92
0x2A
@@ -2223,7 +1989,7 @@
[Channel1]
- P32.rightDeck.samplerButton[28].input
+ P32.rightDeck.samplerButton[24].input
0x92
0x2B
@@ -2268,7 +2034,7 @@
[Channel1]
- P32.rightDeck.samplerButton[17].input
+ P32.rightDeck.samplerButton[5].input
0x95
0x30
@@ -2277,7 +2043,7 @@
[Channel1]
- P32.rightDeck.samplerButton[18].input
+ P32.rightDeck.samplerButton[6].input
0x95
0x31
@@ -2286,7 +2052,7 @@
[Channel1]
- P32.rightDeck.samplerButton[19].input
+ P32.rightDeck.samplerButton[7].input
0x95
0x32
@@ -2295,7 +2061,7 @@
[Channel1]
- P32.rightDeck.samplerButton[20].input
+ P32.rightDeck.samplerButton[8].input
0x95
0x33
@@ -2304,7 +2070,7 @@
[Channel1]
- P32.rightDeck.samplerButton[21].input
+ P32.rightDeck.samplerButton[13].input
0x95
0x2C
@@ -2313,7 +2079,7 @@
[Channel1]
- P32.rightDeck.samplerButton[22].input
+ P32.rightDeck.samplerButton[14].input
0x95
0x2D
@@ -2322,7 +2088,7 @@
[Channel1]
- P32.rightDeck.samplerButton[23].input
+ P32.rightDeck.samplerButton[15].input
0x95
0x2E
@@ -2331,7 +2097,7 @@
[Channel1]
- P32.rightDeck.samplerButton[24].input
+ P32.rightDeck.samplerButton[16].input
0x95
0x2F
@@ -2340,7 +2106,7 @@
[Channel1]
- P32.rightDeck.samplerButton[25].input
+ P32.rightDeck.samplerButton[21].input
0x95
0x28
@@ -2349,7 +2115,7 @@
[Channel1]
- P32.rightDeck.samplerButton[26].input
+ P32.rightDeck.samplerButton[22].input
0x95
0x29
@@ -2358,7 +2124,7 @@
[Channel1]
- P32.rightDeck.samplerButton[27].input
+ P32.rightDeck.samplerButton[23].input
0x95
0x2A
@@ -2367,7 +2133,7 @@
[Channel1]
- P32.rightDeck.samplerButton[28].input
+ P32.rightDeck.samplerButton[24].input
0x95
0x2B
@@ -2430,7 +2196,7 @@
[Channel1]
- P32.rightDeck.loopTogglePad.input
+ P32.rightDeck.reloop.input
0x92
0x52
@@ -2457,7 +2223,7 @@
[Channel1]
- P32.rightDeck.loopTogglePad.input
+ P32.rightDeck.reloop.input
0x95
0x52
@@ -2520,18 +2286,72 @@
[Channel1]
- P32.rightDeck.quantize.input
+ P32.rightDeck.enableEffectUnitButtons[0].input
+ 0x92
+ 0x40
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[0].input
+ 0x95
+ 0x40
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[1].input
+ 0x92
+ 0x41
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[1].input
+ 0x95
+ 0x41
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[2].input
+ 0x92
+ 0x3C
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[2].input
+ 0x95
+ 0x3C
+
+
+
+
+
+ [Channel1]
+ P32.rightDeck.enableEffectUnitButtons[3].input
0x92
- 0x47
+ 0x3D
[Channel1]
- P32.rightDeck.quantize.input
+ P32.rightDeck.enableEffectUnitButtons[3].input
0x95
- 0x47
+ 0x3D
diff --git a/res/controllers/Hercules-P32-scripts.js b/res/controllers/Hercules-P32-scripts.js
index 83973075ab7b..4d79963def23 100644
--- a/res/controllers/Hercules-P32-scripts.js
+++ b/res/controllers/Hercules-P32-scripts.js
@@ -1,8 +1,11 @@
// USER CONFIGURABLE OPTIONS
-// loop size (in beats) when Mixxx starts
-var defaultLoopSize = 8;
-// beat jump size when Mixxx starts
-var defaultBeatJumpSize = 4;
+// The labels on the encoders are mirrored, but the rest of the controller
+// is asymmetrical. If this is confusing for you to use, set this to "false" to swap the
+// mapping of the encoders on the right deck so the whole controller is asymmetrical.
+var mirroredEncoders = true;
+// Set this to "false" to be able to set the loop and beatjump sizes above 64 beats
+// to values that cannot be shown on the controller's LED display.
+var clampLoopAndBeatJumpSize = true;
// Set to "true" to use the dot on the loop size LED display to indicate
// that a loop is active. This restricts loop sizes to 2-32 beats and
// may be helpful if you never use loops less than 2 beats long.
@@ -40,18 +43,6 @@ P32.init = function () {
components.Component.prototype.shiftChannel = true;
components.Button.prototype.sendShifted = true;
- /**
- The P32 has encoders for changing tempo, so the actual tempo getting out of sync with a hardware
- fader and dealing with soft takeover in that situation is not an issue. So, make toggling master
- sync the default unshifted behavior and momentary sync the shifted behavior.
- **/
- components.SyncButton.prototype.unshift = function () {
- this.inKey = 'sync_enabled';
- };
- components.SyncButton.prototype.shift = function () {
- this.inKey = 'beatsync';
- };
-
if (engine.getValue('[Master]', 'num_samplers') < 32) {
engine.setValue('[Master]', 'num_samplers', 32);
}
@@ -69,6 +60,7 @@ P32.shutdown = function () {
midi.sendShortMsg(0x90 + channel, button, 0);
}
}
+ // TODO: ask Hercules if it is possible to clear the loop size LEDs
};
P32.shiftOffset = 3;
@@ -106,21 +98,35 @@ P32.recordButton = new components.Button({
midi: [0x90, 0x02],
group: '[Recording]',
inKey: 'toggle_recording',
- onlyOnPress: false,
outKey: 'status',
sendShifted: false,
});
P32.slipButton = new components.Button({
midi: [0x90, 0x03],
+ pressedToToggleDeck: false,
input: function (channel, control, value, status, group) {
- if (P32.leftDeck.isShifted) {
+ if (P32.leftDeck.isShifted && value === 127) {
+ // PFL button is controlling effect unit assignment to headphones while
+ // shift is pressed, so switch it back to controlling PFL so
+ // reconnecting the output works.
+ P32.leftDeck.pfl.unshift();
P32.leftDeck.toggle();
- } else if (P32.rightDeck.isShifted) {
+ this.pressedToToggleDeck = true;
+ } else if (P32.rightDeck.isShifted && value === 127) {
+ // PFL button is controlling effect unit assignment to headphones while
+ // shift is pressed, so switch it back to controlling PFL so
+ // reconnecting the output works.
+ P32.rightDeck.pfl.unshift();
P32.rightDeck.toggle();
+ this.pressedToToggleDeck = true;
} else {
- for (var i = 1; i <= 4; i++) {
- script.toggleControl('[Channel' + i + ']', 'slip_enabled');
+ if (this.pressedToToggleDeck && value === 0) {
+ this.pressedToToggleDeck = false;
+ } else {
+ for (var i = 1; i <= 4; i++) {
+ script.toggleControl('[Channel' + i + ']', 'slip_enabled');
+ }
}
}
},
@@ -149,8 +155,6 @@ P32.slipButton = new components.Button({
P32.Deck = function (deckNumbers, channel) {
components.Deck.call(this, deckNumbers);
- var loopSize = defaultLoopSize;
- var beatJumpSize = defaultBeatJumpSize;
var theDeck = this;
this.shiftButton = function (channel, control, value, status, group) {
@@ -161,36 +165,219 @@ P32.Deck = function (deckNumbers, channel) {
}
};
- // ===================================== TRANSPORT =========================================
- this.sync = new components.SyncButton([0x90 + channel, 0x08]);
- this.cue = new components.CueButton([0x90 + channel, 0x09]);
- this.play = new components.PlayButton([0x90 + channel, 0x0A]);
+ this.loadTrack = new components.Button({
+ midi: [0x90 + channel, 0x0F],
+ unshift: function () {
+ this.inKey = 'LoadSelectedTrack';
+ },
+ shift: function () {
+ this.inKey = 'eject';
+ },
+ });
- // ===================================== MIXER ==============================================
- this.eqKnob = [];
- for (var k = 1; k <= 3; k++) {
- this.eqKnob[k] = new components.Pot({
- midi: [0xB0 + channel, 0x02 + k],
- group: '[EqualizerRack1_' + this.currentDeck + '_Effect1]',
- inKey: 'parameter' + k,
- });
- }
+ // =============================== ENCODERS =========================================
+ this.loopEncoder = new components.Encoder({
+ // NOTE: these are the MIDI bytes for the digit LEDs, not input from the encoder.
+ midi: [0xB0 + channel, 0x1B],
+ unshift: function () {
+ this.input = function (channel, control, value, status, group) {
+ var loopSize = engine.getValue(this.group, 'beatloop_size');
+ if (loopEnabledDot) {
+ if (value > 64 && loopSize > 2) { // turn left
+ // Unfortunately, there is no way to show 1 with a dot on the
+ // loop size LED.
+ engine.setValue(this.group, 'beatloop_size', loopSize / 2);
+ } else if (value < 64 && loopSize < 32) { // turn right
+ // Mixxx supports loops longer than 32 beats, but there is no way
+ // to show 64 with a dot on the loop size LED.
+ engine.setValue(this.group, 'beatloop_size', loopSize * 2);
+ }
+ } else {
+ if (value > 64 && loopSize > 1/32) { // turn left
+ engine.setValue(this.group, 'beatloop_size', loopSize / 2);
+ } else if (value < 64) { // turn right
+ if (clampLoopAndBeatJumpSize) {
+ if (loopSize * 2 <= 64) {
+ engine.setValue(this.group, 'beatloop_size', loopSize * 2);
+ }
+ } else {
+ engine.setValue(this.group, 'beatloop_size', loopSize * 2);
+ }
+ }
+ }
+ };
+ },
+ shift: function () {
+ this.input = function (channel, control, value, status, group) {
+ var direction = (value > 64) ? 'backward' : 'forward';
+ script.triggerControl(this.group, 'beatjump_1_' + direction);
+ };
+ },
+ connect: function () {
+ this.connections[0] = engine.connectControl(this.group, 'beatloop_size', this.output);
+ if (loopEnabledDot) {
+ this.connections[1] = engine.connectControl(this.group, 'loop_enabled', this.output);
+ }
+ },
+ output: function (value, group, control) {
+ var loopSize = engine.getValue(this.group, 'beatloop_size');
+ var loopSizeLogBase2 = Math.log(loopSize) / Math.log(2);
+ // test if loopSizeLogBase2 is an integer
+ if (Math.floor(loopSizeLogBase2) === loopSizeLogBase2) {
+ if (loopEnabledDot && engine.getValue(this.group, 'loop_enabled') === 1) {
+ this.send(5 - loopSizeLogBase2);
+ } else {
+ this.send(5 + loopSizeLogBase2);
+ }
+ } else {
+ this.send(14); // show two dots
+ }
+ }
+ });
- this.pfl = new components.Button({
- midi: [0x90 + channel, 0x10],
- key: 'pfl',
- sendShifted: false,
+ this.loopEncoderPress = new components.Button({
+ unshift: function () {
+ // Make sure the shifted Controls don't get stuck with a value of 1
+ // if the shift button is released before the encoder button.
+ if (engine.getValue(this.group, 'reloop_andstop') !== 0) {
+ engine.setValue(this.group, 'reloop_andstop', 0);
+ }
+ if (engine.getValue(this.group, 'reloop_toggle') !== 0) {
+ engine.setValue(this.group, 'reloop_toggle', 0);
+ }
+
+ this.input = function (channel, control, value, status, group) {
+ if (value) {
+ if (engine.getValue(this.group, 'loop_enabled') === 1) {
+ engine.setValue(this.group, 'reloop_toggle', 1);
+ } else {
+ engine.setValue(this.group, 'beatloop_activate', 1);
+ }
+ } else {
+ if (engine.getValue(this.group, 'reloop_toggle') !== 1) {
+ engine.setValue(this.group, 'reloop_toggle', 0);
+ } else if (engine.getValue(this.group, 'beatloop_activate') !== 0) {
+ engine.setValue(this.group, 'beatloop_activate', 0);
+ }
+ }
+ };
+ },
+ shift: function () {
+ // Make sure the unshifted Controls don't get stuck with a value of 1
+ // if the shift button is pressed before releasing the encoder button.
+ if (engine.getValue(this.group, 'reloop_toggle') !== 0) {
+ engine.setValue(this.group, 'reloop_toggle', 0);
+ }
+ if (engine.getValue(this.group, 'beatloop_activate') !== 0) {
+ engine.setValue(this.group, 'beatloop_activate', 0);
+ }
+
+ this.input = function (channel, control, value, status, group) {
+ if (engine.getValue(this.group, 'loop_enabled') === 1) {
+ engine.setValue(this.group, 'reloop_andstop', value / 127);
+ } else {
+ engine.setValue(this.group, 'reloop_toggle', value / 127);
+ }
+ };
+ },
});
- this.volume = new components.Pot({
- midi: [0xB0 + channel, 0x01],
- inKey: 'volume',
+ this.showBeatjumpSize = function () {
+ var beatjumpSize = engine.getValue(this.currentDeck, 'beatjump_size');
+ var beatjumpSizeLogBase2 = Math.log(beatjumpSize) / Math.log(2);
+ // test if beatjumpSizeLogBase2 is an integer
+ if (Math.floor(beatjumpSizeLogBase2) === beatjumpSizeLogBase2) {
+ midi.sendShortMsg(0xB0 + channel, 0x1B,
+ 5 + Math.log(beatjumpSize) / Math.log(2));
+ } else {
+ midi.sendShortMsg(0xB0 + channel, 0x1B, 14); // show two dots
+ }
+ };
+
+ this.tempoAndBeatjumpEncoder = new components.Encoder({
+ unshift: function () {
+ this.input = function (channel, control, value, status, group) {
+ var direction = (value > 64) ? -1 : 1;
+ engine.setValue(this.group, 'rate',
+ engine.getValue(this.group, 'rate') + (0.01 * direction));
+ };
+ },
+ shift: function () {
+ this.input = function (channel, control, value, status, group) {
+ var beatJumpSize = engine.getValue(this.group, 'beatjump_size');
+ if (theDeck.beatJumpEncoderPressed) {
+ if (value > 64 && beatJumpSize > 1/32) { // turn left
+ beatJumpSize /= 2;
+ } else if (value < 64) { // turn right
+ if (clampLoopAndBeatJumpSize && beatJumpSize >= 64) {
+ return;
+ }
+ beatJumpSize *= 2;
+ }
+ engine.setValue(this.group, 'beatjump_size', beatJumpSize);
+ theDeck.showBeatjumpSize();
+ } else {
+ var direction = (value > 64) ? 'backward' : 'forward';
+ script.triggerControl(this.group, 'beatjump_' + direction);
+ }
+ };
+ },
});
- // ==================================== PAD GRID ============================================
- // The slicer layer is handled by this.effectUnit.enableOnChannelButtons, set up under the
- // EFFECTS section.
+ this.tempoAndBeatjumpEncoderPress = new components.Button({
+ unshift: function () {
+ theDeck.loopEncoder.trigger();
+ this.input = function (channel, control, value, status, group) {
+ if (value === 127) {
+ engine.setValue(this.group, 'rate', 0);
+ }
+ };
+ },
+ shift: function () {
+ this.input = function (channel, control, value, status, group) {
+ if (value === 127) {
+ theDeck.beatJumpEncoderPressed = true;
+ theDeck.showBeatjumpSize();
+ } else {
+ theDeck.beatJumpEncoderPressed = false;
+ theDeck.loopEncoder.trigger();
+ }
+ };
+ },
+ });
+ if (mirroredEncoders) {
+ if (channel == 1) { // left deck
+ this.leftEncoder = this.loopEncoder;
+ this.leftEncoderPress = this.loopEncoderPress;
+ this.rightEncoder = this.tempoAndBeatjumpEncoder;
+ this.rightEncoderPress = this.tempoAndBeatjumpEncoderPress;
+ } else if (channel == 2) { // right deck
+ this.leftEncoder = this.tempoAndBeatjumpEncoder;
+ this.leftEncoderPress = this.tempoAndBeatjumpEncoderPress;
+ this.rightEncoder = this.loopEncoder;
+ this.rightEncoderPress = this.loopEncoderPress;
+ }
+ } else {
+ this.leftEncoder = this.loopEncoder;
+ this.leftEncoderPress = this.loopEncoderPress;
+ this.rightEncoder = this.tempoAndBeatjumpEncoder;
+ this.rightEncoderPress = this.tempoAndBeatjumpEncoderPress;
+ }
+
+ // ================================= EFFECTS =====================================
+ this.effectUnit = new components.EffectUnit(deckNumbers);
+ this.effectUnit.knobs[1].midi = [0xB0 + channel, 0x06];
+ this.effectUnit.knobs[2].midi = [0xB0 + channel, 0x07];
+ this.effectUnit.knobs[3].midi = [0xB0 + channel, 0x08];
+ this.effectUnit.dryWetKnob.midi = [0xB0 + channel, 0x09];
+ this.effectUnit.enableButtons[1].midi = [0x90 + channel, 0x03];
+ this.effectUnit.enableButtons[2].midi = [0x90 + channel, 0x04];
+ this.effectUnit.enableButtons[3].midi = [0x90 + channel, 0x05];
+ this.effectUnit.effectFocusButton.midi = [0x90 + channel, 0x06];
+ this.effectUnit.init();
+
+ // ================================ PAD GRID ====================================
this.hotcueButton = [];
this.samplerButton = [];
for (var i = 1; i <= 16; i++) {
@@ -200,13 +387,18 @@ P32.Deck = function (deckNumbers, channel) {
number: i,
on: P32.padColors.red
});
- var samplerNumber = i + (channel - 1) * 16;
+
+ var row = Math.ceil(i/4);
+ var column = ((i-1) % 4) + 1;
+ var padGrid = channel - 1;
+ var samplerNumber = (8 * (row-1)) + (column) + (padGrid * 4);
this.samplerButton[samplerNumber] = new components.SamplerButton({
midi: [0x90 + channel, P32.PadNumToMIDIControl(i, 0)],
number: samplerNumber,
- on: P32.padColors.red,
- off: P32.padColors.off,
- playing: P32.padColors.blue
+ empty: P32.padColors.off,
+ loaded: P32.padColors.red,
+ playing: P32.padColors.blue,
+ looping: P32.padColors.purple,
});
if (samplerCrossfaderAssign) {
engine.setValue('[Sampler' + samplerNumber + ']',
@@ -216,212 +408,103 @@ P32.Deck = function (deckNumbers, channel) {
}
}
+ // LOOP layer
this.loopIn = new components.Button({
midi: [0x90 + channel, 0x50],
- inKey: 'loop_in',
+ key: 'loop_in',
+ on: P32.padColors.red,
+ off: P32.padColors.purple,
});
this.loopOut = new components.Button({
midi: [0x90 + channel, 0x51],
- inKey: 'loop_out',
+ key: 'loop_out',
+ on: P32.padColors.red,
+ off: P32.padColors.purple,
});
- this.loopTogglePad = new components.LoopToggleButton({
+ this.reloop = new components.Button({
midi: [0x90 + channel, 0x52],
+ unshift: function () {
+ this.inKey = 'reloop_toggle';
+ },
+ shift: function () {
+ this.inKey = 'reloop_andstop';
+ },
on: P32.padColors.red,
off: P32.padColors.blue,
+ outKey: 'loop_enabled',
});
- this.loopIn.send(P32.padColors.purple);
- this.loopOut.send(P32.padColors.purple);
this.tempSlow = new components.Button({
midi: [0x90 + channel, 0x44],
- inKey: 'rate_temp_down',
- onlyOnPress: false,
+ key: 'rate_temp_down',
+ on: P32.padColors.red,
+ off: P32.padColors.purple,
});
this.tempFast = new components.Button({
midi: [0x90 + channel, 0x45],
- inKey: 'rate_temp_down',
- onlyOnPress: false,
+ key: 'rate_temp_up',
+ on: P32.padColors.red,
+ off: P32.padColors.purple,
});
this.alignBeats = new components.Button({
midi: [0x90 + channel, 0x46],
- inKey: 'beats_translate_curpos',
- });
- this.quantize = new components.Button({
- midi: [0x90 + channel, 0x47],
- key: 'quantize',
+ key: 'beats_translate_curpos',
on: P32.padColors.red,
off: P32.padColors.blue,
});
- this.tempSlow.send(P32.padColors.purple);
- this.tempFast.send(P32.padColors.purple);
- this.alignBeats.send(P32.padColors.blue);
-
- // =================================== ENCODERS ==============================================
- this.loopSizeEncoder = new components.Encoder({
- midi: [0xB0 + channel, 0x1B], // Note: these are the MIDI bytes for the LED readout, not
- // input from the encoder.
- input: function (channel, control, value, status, group) {
- if (loopEnabledDot) {
- if (value > 64 && loopSize > 2) { // turn left
- /**
- Unfortunately, there is no way to show 1 with a dot on the
- loop size LED.
- **/
- loopSize /= 2;
- engine.setValue(this.group, 'loop_halve', 1);
- engine.setValue(this.group, 'loop_halve', 0);
- } else if (value < 64 && loopSize < 32) { // turn right
- /**
- Mixxx supports loops longer than 32 beats, but there is no way
- to show 64 with a dot on the loop size LED.
- **/
- loopSize *= 2;
- engine.setValue(this.group, 'loop_double', 1);
- engine.setValue(this.group, 'loop_double', 0);
- }
- } else {
- if (value > 64 && loopSize > 1/32) { // turn left
- /**
- Mixxx supports loops shorter than 1/32 beats, but there is no
- way to set the loop size LED less than 1/32 (even though it
- should be able to show 1/64)
- **/
- loopSize /= 2;
- engine.setValue(this.group, 'loop_halve', 1);
- engine.setValue(this.group, 'loop_halve', 0);
- } else if (value < 64 && loopSize < 64) { // turn right
- /**
- Mixxx supports loops longer than 64 beats, but the loop size LED
- only has 2 digits, so it couldn't show 128
- **/
- loopSize *= 2;
- engine.setValue(this.group, 'loop_double', 1);
- engine.setValue(this.group, 'loop_double', 0);
- }
- }
- this.trigger();
- },
- outKey: 'loop_enabled',
- output: function (value, group, control) {
- if (loopEnabledDot && value) {
- this.send(5 - Math.log(loopSize) / Math.log(2));
- } else {
- this.send(5 + Math.log(loopSize) / Math.log(2));
- }
- }
- });
- this.loopMoveEncoder = function (channel, control, value, status, group) {
- var direction = (value > 64) ? -1 : 1;
- if (loopSize < 1) {
- engine.setValue(this.currentDeck, 'loop_move', loopSize * direction);
- } else {
- engine.setValue(this.currentDeck, 'loop_move', 1 * direction);
+ // SLICER layer
+ this.enableEffectUnitButtons = [0x40, 0x41, 0x3C, 0x3D].map(
+ function (midiByte, index) {
+ return new components.EffectAssignmentButton({
+ midi: [0x90 + channel, midiByte],
+ effectUnit: index + 1,
+ group: this.currentDeck,
+ on: P32.padColors.blue,
+ off: P32.padColors.red,
+ });
}
- };
+ , this);
- this.loopToggleEncoderPress = function (channel, control, value, status, group) {
- if (value) {
- if (engine.getValue(this.currentDeck, 'loop_enabled')) {
- engine.setValue(this.currentDeck, 'reloop_exit', 1);
- } else {
- engine.setValue(this.currentDeck, 'beatloop_' + loopSize + '_activate', 1);
- }
- } else {
- if (loopSize <= 1 && engine.getValue(this.currentDeck, 'loop_enabled')) {
- engine.setValue(this.currentDeck, 'reloop_exit', 1);
- }
- }
- };
-
- this.loopEncoderManualLoopPress = function (channel, control, value, status, group) {
- if (value) {
- engine.setValue(this.currentDeck, 'loop_in', 1);
- } else {
- engine.setValue(this.currentDeck, 'loop_out', 1);
- }
- };
-
- this.tempoEncoder = function (channel, control, value, status, group) {
- var direction = (value > 64) ? -1 : 1;
- engine.setValue(this.currentDeck, 'rate', engine.getValue(this.currentDeck, 'rate') + (0.01 * direction));
- };
-
- this.tempoEncoderPress = function (channel, control, value, status, group) {
- if (value) {
- engine.setValue(this.currentDeck, 'rate', 0);
- }
- };
-
- this.beatJumpEncoder = function (channel, control, value, status, group) {
- var direction = (value > 64) ? -1 : 1;
- if (this.beatJumpEncoderPressed) {
- if (value > 64 && beatJumpSize > 1/32) { // turn left
- beatJumpSize /= 2;
- } else if (value < 64 && beatJumpSize < 64) { // turn right
- beatJumpSize *= 2;
- }
- // The firmware will only change the numeric LED readout when sent messages
- // on the unshifted channel.
- midi.sendShortMsg(0xB0 + channel - P32.shiftOffset, 0x1B, 5 + Math.log(beatJumpSize) / Math.log(2));
- } else {
- engine.setValue(this.currentDeck, 'beatjump', direction * beatJumpSize);
- }
- };
+ // ============================= TRANSPORT ==================================
+ this.sync = new components.SyncButton([0x90 + channel, 0x08]);
+ this.cue = new components.CueButton([0x90 + channel, 0x09]);
+ this.play = new components.PlayButton([0x90 + channel, 0x0A]);
- this.beatJumpEncoderPress = function (channel, control, value, status, group) {
- // The firmware will only change the numeric LED readout when sent messages
- // on the unshifted channel.
- if (value === 127) {
- this.beatJumpEncoderPressed = true;
- midi.sendShortMsg(0xB0 + channel - P32.shiftOffset, 0x1B, 5 + Math.log(beatJumpSize) / Math.log(2));
- } else {
- this.beatJumpEncoderPressed = false;
- midi.sendShortMsg(0xB0 + channel - P32.shiftOffset, 0x1B, 5 + Math.log(loopSize) / Math.log(2));
- }
- };
+ // =============================== MIXER ====================================
+ this.eqKnob = [];
+ for (var k = 1; k <= 3; k++) {
+ this.eqKnob[k] = new components.Pot({
+ midi: [0xB0 + channel, 0x02 + k],
+ group: '[EqualizerRack1_' + this.currentDeck + '_Effect1]',
+ inKey: 'parameter' + k,
+ });
+ }
- this.loadTrack = function (channel, control, value, status, group) {
- if (value === 127) {
- engine.setValue(this.currentDeck, 'LoadSelectedTrack', 1);
- }
- };
+ this.pfl = new components.Button({
+ midi: [0x90 + channel, 0x10],
+ sendShifted: false,
+ type: components.Button.prototype.types.toggle,
+ unshift: function () {
+ this.group = theDeck.currentDeck;
+ this.inKey = 'pfl';
+ },
+ outKey: 'pfl',
+ shift: function () {
+ this.group = '[EffectRack1_EffectUnit' + theDeck.effectUnit.currentUnitNumber + ']';
+ this.inKey = 'group_[Headphone]_enable';
+ },
+ });
- this.ejectTrack = function (channel, control, value, status, group) {
- if (value === 127) {
- engine.setValue(this.currentDeck, 'eject', 1);
- engine.beginTimer(250, 'engine.setValue("'+this.currentDeck+'", "eject", 0)', true);
- }
- };
+ this.volume = new components.Pot({
+ midi: [0xB0 + channel, 0x01],
+ inKey: 'volume',
+ });
this.reconnectComponents(function (component) {
if (component.group === undefined) {
component.group = this.currentDeck;
}
});
-
- // ==================================== EFFECTS ==============================================
- this.effectUnit = new components.EffectUnit(deckNumbers[0]);
- this.effectUnit.knobs[1].midi = [0xB0 + channel, 0x06];
- this.effectUnit.knobs[2].midi = [0xB0 + channel, 0x07];
- this.effectUnit.knobs[3].midi = [0xB0 + channel, 0x08];
- this.effectUnit.dryWetKnob.midi = [0xB0 + channel, 0x09];
- this.effectUnit.enableButtons[1].midi = [0x90 + channel, 0x03];
- this.effectUnit.enableButtons[2].midi = [0x90 + channel, 0x04];
- this.effectUnit.enableButtons[3].midi = [0x90 + channel, 0x05];
- this.effectUnit.showParametersButton.midi = [0x90 + channel, 0x06];
- this.effectUnit.enableOnChannelButtons.Channel1.midi = [0x90 + channel, 0x40];
- this.effectUnit.enableOnChannelButtons.Channel2.midi = [0x90 + channel, 0x41];
- this.effectUnit.enableOnChannelButtons.Channel3.midi = [0x90 + channel, 0x42];
- this.effectUnit.enableOnChannelButtons.Channel4.midi = [0x90 + channel, 0x43];
- this.effectUnit.enableOnChannelButtons.Headphone.midi = [0x90 + channel, 0x34];
- this.effectUnit.enableOnChannelButtons.Master.midi = [0x90 + channel, 0x35];
- this.effectUnit.enableOnChannelButtons.Microphone.midi = [0x90 + channel, 0x36];
- this.effectUnit.enableOnChannelButtons.Auxiliary1.midi = [0x90 + channel, 0x37];
- this.effectUnit.enableOnChannelButtons.forEachComponent(function (button) {
- button.on = P32.padColors.red;
- button.off = P32.padColors.blue;
- });
- this.effectUnit.init();
};
P32.Deck.prototype = new components.Deck();
diff --git a/res/controllers/common-controller-scripts.js b/res/controllers/common-controller-scripts.js
index cce9e53641aa..816ebb9bc9ed 100644
--- a/res/controllers/common-controller-scripts.js
+++ b/res/controllers/common-controller-scripts.js
@@ -126,6 +126,25 @@ script.toggleControl = function (group, control) {
engine.setValue(group, control, !(engine.getValue(group, control)));
}
+/* -------- ------------------------------------------------------
+ script.toggleControl
+ Purpose: Triggers an engine value and resets it back to 0 after a delay
+ This is helpful for mapping encoder turns to controls that are
+ represented by buttons in skins so the skin button lights up
+ briefly but does not stay lit.
+ Input: Group and control names, delay in milliseconds (optional)
+ Output: none
+ -------- ------------------------------------------------------ */
+script.triggerControl = function (group, control, delay) {
+ if (typeof delay !== 'number') {
+ delay = 200;
+ }
+ engine.setValue(group, control, 1);
+ engine.beginTimer(delay, function () {
+ engine.setValue(group, control, 0);
+ }, true);
+}
+
/* -------- ------------------------------------------------------
script.absoluteLin
Purpose: Maps an absolute linear control value to a linear Mixxx control
diff --git a/res/controllers/midi-components-0.0.js b/res/controllers/midi-components-0.0.js
index 1215948e267d..1105a5b72a56 100644
--- a/res/controllers/midi-components-0.0.js
+++ b/res/controllers/midi-components-0.0.js
@@ -320,22 +320,35 @@
} else {
engine.setValue(this.group, 'eject', 1);
}
+ } else {
+ if (engine.getValue(this.group, 'play') === 0) {
+ engine.setValue(this.group, 'eject', 0);
+ }
}
};
},
output: function (value, group, control) {
if (engine.getValue(this.group, 'track_loaded') === 1) {
- if (this.playing === undefined) {
+ if (this.loaded === undefined) {
this.send(this.on);
} else {
if (engine.getValue(this.group, 'play') === 1) {
- this.send(this.on);
+ if (this.looping !== undefined &&
+ engine.getValue(this.group, 'repeat') === 1) {
+ this.send(this.looping);
+ } else {
+ this.send(this.playing);
+ }
} else {
- this.send(this.playing);
+ this.send(this.loaded);
}
}
} else {
- this.send(this.off);
+ if (this.empty === undefined) {
+ this.send(this.off);
+ } else {
+ this.send(this.empty);
+ }
}
},
connect: function() {
@@ -343,6 +356,9 @@
if (this.playing !== undefined) {
this.connections[1] = engine.connectControl(this.group, 'play', this.output);
}
+ if (this.looping !== undefined) {
+ this.connections[2] = engine.connectControl(this.group, 'repeat', this.output);
+ }
},
outKey: null, // hack to get Component constructor to call connect()
});
@@ -460,12 +476,22 @@
isShifted: false,
shift: function () {
this.forEachComponent(function (component) {
+ // Controls for push type Buttons depend on getting reset to 0 when the
+ // Button is released for correct behavior. If there is a skin button
+ // that lights up with the inKey, the skin button would stay lit if the
+ // inKey does not get reset to 0. So, if a push type Button is held down
+ // when shift is pressed, when the Button is released, the MIDI signal
+ // for the Button release will be processed when the Button is in the
+ // shifted state, and the unshifted inKey would not get reset to 0.
+ // To work around this, reset push Buttons' inKey to 0 when the shift
+ // button is pressed.
if (typeof component.shift === 'function') {
if (component instanceof Button
&& (component.type === Button.prototype.types.push
|| component.type === undefined)
- && component.inKey !== undefined
- && component.input === Button.prototype.input) {
+ && component.input === Button.prototype.input
+ && typeof component.inKey === 'string'
+ && typeof component.group === 'string') {
if (engine.getValue(component.group, component.inKey) !== 0) {
engine.setValue(component.group, component.inKey, 0);
}
@@ -478,12 +504,14 @@
},
unshift: function () {
this.forEachComponent(function (component) {
+ // Refer to comment in ComponentContainer.shift() above for explanation
if (typeof component.unshift === 'function') {
if (component instanceof Button
&& (component.type === Button.prototype.types.push
|| component.type === undefined)
- && component.inKey !== undefined
- && component.input === Button.prototype.input) {
+ && component.input === Button.prototype.input
+ && typeof component.inKey === 'string'
+ && typeof component.group === 'string') {
if (engine.getValue(component.group, component.inKey) !== 0) {
engine.setValue(component.group, component.inKey, 0);
}