From 220e2ba951fbf1d15fbf7df5b6676b35bf315bfa Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 23 Sep 2025 21:43:31 +0000 Subject: [PATCH 01/70] Pioneer DDJ-200: fix for hotcue issues, rewrite fix for issues with hotcue buttons. Complete rewrite, code cleanup --- res/controllers/Pioneer DDJ-200.midi.xml | 1858 ++++++++++---------- res/controllers/Pioneer-DDJ-200-scripts.js | 852 +++++---- 2 files changed, 1379 insertions(+), 1331 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 16c86be2068e..d0900a107f4a 100644 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -1,959 +1,903 @@ - + - - Pioneer DDJ-200 - Dan Giddins, Frank.Breitling at gmx.de - 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 - - - - - - - - [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] - DDJ200.shiftRight - Deck 2: Shift pressed - 0x91 - 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] - DDJ200.syncEnabled - Deck 1: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync - 0x90 - 0x58 - - - - - - [Channel2] - DDJ200.syncEnabled - Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync - 0x91 - 0x58 - - - - - - - [Channel2] - DDJ200.seek - Deck 2: Seek - 0xB1 - 0x29 - - - - - - [Channel1] - DDJ200.seek - Deck 1: Seek - 0xB0 - 0x29 - - - - - - - [AutoDJ] - enabled - Toggle Auto DJ On/Off - 0x96 - 0x59 - - - - - - [AutoDJ] - fade_now - Trigger the transition to the next track - 0x96 - 0x5A - - - - - - - [Channel2] - DDJ200.touch - Deck 2: Touch - 0x91 - 0x36 - - - - - - [Channel1] - DDJ200.touch - Deck 1: Touch - 0x90 - 0x36 - - - - - - - - [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_[Channel1]_Effect1] - DDJ200.eq - - Deck 1: Adjust High EQ - 0xB0 - 0x07 - - - - - - - - - [QuickEffectRack1_[Channel1]] - DDJ200.super1 - Super Knob (msb): control linked effect - 0xB6 - 0x17 - - - - - - - - - [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]] - DDJ200.super1 - Quick Effect: Quick Effect Super Knob (control linked effect parameters) - 0xB6 - 0x18 - - - - - - - - [Channel1] - bpm_tap - Deck 1: BPM tap button - 0x90 - 0x60 - - - - - - [Channel2] - bpm_tap - Deck 2: BPM tap button - 0x91 - 0x60 - - - - - - - [Channel1] - - DDJ200.volumeMSB - Deck 1: Volume Fader - 0xB0 - 0x13 - - - - - - - [Channel1] - DDJ200.volumeLSB - Deck 1: Volume Fader - 0xB0 - 0x33 - - - - - - - [Channel2] - DDJ200.volumeMSB - Deck 2: Volume Fader - 0xB1 - 0x13 - - - - - - - [Channel2] - DDJ200.volumeLSB - Deck 2: Volume Fader - 0xB1 - 0x33 - - - - - - - - [Channel1] - DDJ200.play - Deck 1: Play button - 0x90 - 0x0B - - - - - - [Channel2] - DDJ200.play - Deck 2: Play button - 0x91 - 0x0B - - - - - - - [Channel1] - - DDJ200.cueDefault - Deck 1: Cue button - 0x90 - 0x0C - - - - - - [Channel2] - DDJ200.cueDefault - Deck 2: Cue button - 0x91 - 0x0C - - - - - - [Channel1] - DDJ200.cueGotoandstop - Deck 1: Go to cue point and stop - 0x90 - 0x48 - - - - - - [Channel2] - DDJ200.cueGotoandstop - Deck 2: Go to cue point and stop - 0x91 - 0x48 - - - - - - - [Channel1] - DDJ200.rateMSB - Deck 1: Playback speed control - 0xB0 - 0x00 - - - - - - - - [Channel1] - DDJ200.rateLSB - Deck 1: Playback speed control - 0xB0 - 0x20 - - - - - - - - [Channel2] - DDJ200.rateMSB - Deck 2: Playback speed control - 0xB1 - 0x00 - - - - - - - [Channel2] - DDJ200.rateLSB - Deck 2: Playback speed control - 0xB1 - 0x20 - - - - - - - - [Channel2] - DDJ200.jog - Deck 2: Jog - 0xB1 - 0x21 - - - - - - [Channel1] - DDJ200.jog - Deck 1: Jog - 0xB0 - 0x21 - - - - - - [Channel2] - DDJ200.scratch - Deck 2: Scratch - 0xB1 - 0x22 - - - - - - [Channel1] - DDJ200.scratch - Deck 1: Scratch - 0xB0 - 0x22 - - - - - - - - [Channel2] - cue_set - Deck 2: Set cue point - 0x91 - 0x47 - - - - - - [Channel1] - cue_set - Deck 1: Set cue point - 0x90 - 0x47 - - - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 1, Deck 1: Set, preview, jump to - 0x97 - 0x00 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 2, Deck 1: Set, preview, jump to - 0x97 - 0x01 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 3, Deck 1: Set, preview, jump to - 0x97 - 0x02 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 4, Deck 1: Set, preview, jump to - 0x97 - 0x03 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 5, Deck 1: Set, preview, jump to - 0x97 - 0x04 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 6, Deck 1: Set, preview, jump to - 0x97 - 0x05 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 7, Deck 1: Set, preview, jump to - 0x97 - 0x06 - - - - - - [Channel1] - DDJ200.hotcueNActivate - Hotcue 8, Deck 1: Set, preview, jump to - 0x97 - 0x07 - - - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 1, Deck 2: Set, preview, jump to - 0x99 - 0x00 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 2, Deck 2: Set, preview, jump to - 0x99 - 0x01 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 3, Deck 2: Set, preview, jump to - 0x99 - 0x02 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 4, Deck 2: Set, preview, jump to - 0x99 - 0x03 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 5, Deck 2: Set, preview, jump to - 0x99 - 0x04 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 6, Deck 2: Set, preview, jump to - 0x99 - 0x05 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 7, Deck 2: Set, preview, jump to - 0x99 - 0x06 - - - - - - [Channel2] - DDJ200.hotcueNActivate - Hotcue 8, Deck 2: Set, preview, jump to - 0x99 - 0x07 - - - - - - - [Channel1] - - DDJ200.hotcueNClear - Hotcue 1, Deck 1: Clear - 0x98 - 0x00 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 2, Deck 1: Clear - 0x98 - 0x01 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 3, Deck 1: Clear - 0x98 - 0x02 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 4, Deck 1: Clear - 0x98 - 0x03 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 5, Deck 1: Clear - 0x98 - 0x04 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 6, Deck 1: Clear - 0x98 - 0x05 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 7, Deck 1: Clear - 0x98 - 0x06 - - - - - - [Channel1] - DDJ200.hotcueNClear - Hotcue 8, Deck 1: Clear - 0x98 - 0x07 - - - - - - - [Channel2] - - DDJ200.hotcueNClear - Hotcue 1, Deck 2: Clear - 0x9A - 0x00 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 2, Deck 2: Clear - 0x9A - 0x01 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 3, Deck 2: Clear - 0x9A - 0x02 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 4, Deck 2: Clear - 0x9A - 0x03 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 5, Deck 2: Clear - 0x9A - 0x04 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 6, Deck 2: Clear - 0x9A - 0x05 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 7, Deck 2: Clear - 0x9A - 0x06 - - - - - - [Channel2] - DDJ200.hotcueNClear - Hotcue 8, Deck 2: Clear - 0x9A - 0x07 - - - - - - - - - - - + + Pioneer DDJ-200 + Rene (mixxx at absorb.it), Dan Giddins, Frank.Breitling at gmx.de, Geovanni Pacheco + 2-deck USB and Bluetooth MIDI controller with support for 4-deck mode. + https://mixxx.discourse.group/t/new-mapping-for-pioneer-ddj-200/31164 + pioneer_ddj_200 + + + + + + + + + [Channel1] + DDJ200.shiftButton.input + Deck 1: Shift pressed + 0x90 + 0x3F + + + + + + [Channel2] + DDJ200.shiftButton.input + Deck 2: Shift pressed + 0x91 + 0x3F + + + + + + [Master] + crossfader + Master crossfader + 0xB6 + 0x1F + + + + + + + [Master] + crossfader + Master crossfader + 0xB6 + 0x3F + + + + + + + [Master] + DDJ200.headMixButton.input + Headphones master as headMix knob + 0x96 + 0x63 + + + + + + [Master] + DDJ200.headMixButton.shiftedInput + Headphones master + shift + 0x96 + 0x78 + + + + + + [Channel1] + DDJ200.leftDeck.pflButton.input + Deck 1: Headphone listen (pfl) button + 0x90 + 0x54 + + + + + + [Channel1] + DDJ200.leftDeck.loadTrack.input + Deck 1: Headphone (pfl) + shift + 0x90 + 0x68 + + + + + + [Channel2] + DDJ200.rightDeck.pflButton.input + Deck 2: Headphone listen (pfl) button + 0x91 + 0x54 + + + + + + [Channel2] + DDJ200.rightDeck.loadTrack.input + Deck 2: Headphone (pfl) + shift + 0x91 + 0x68 + + + + + + [Channel1] + DDJ200.leftDeck.syncButton.input + Deck 1: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + 0x90 + 0x58 + + + + + + [Channel2] + DDJ200.rightDeck.syncButton.input + Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + 0x91 + 0x58 + + + + + + [Channel1] + DDJ200.leftDeck.syncButton.inputLongPress + Deck 1: Long Press to enable permanent sync + 0x90 + 0x5C + + + + + + [Channel2] + DDJ200.rightDeck.syncButton.inputLongPress + Deck 2: Long Press to enable permanent sync + 0x91 + 0x5C + + + + + + [Channel1] + DDJ200.leftDeck.syncButton.shiftedInput + Deck 1: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + 0x90 + 0x60 + + + + + + [Channel2] + DDJ200.rightDeck.syncButton.shiftedInput + Deck 2: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync + 0x91 + 0x60 + + + + + + [Channel1] + DDJ200.leftDeck.jogWheel.inputSeek + Deck 1: Seek + 0xB0 + 0x29 + + + + + + [Channel2] + DDJ200.rightDeck.jogWheel.inputSeek + Deck 2: Seek + 0xB1 + 0x29 + + + + + + [AutoDJ] + DDJ200.transFxButton.input + Change Pad mode + 0x96 + 0x59 + + + + + + [AutoDJ] + DDJ200.transFxButton.input + Change Pad mode + 0x96 + 0x5A + + + + + + [Channel1] + DDJ200.leftDeck.jogWheel.inputTouch + Deck 1: Touch + 0x90 + 0x36 + + + + + + [Channel2] + DDJ200.rightDeck.jogWheel.inputTouch + Deck 2: Touch + 0x91 + 0x36 + + + + + + [EqualizerRack1_[Channel1]_Effect1] + DDJ200.leftDeck.eqKnob[0].input + Deck 1: Adjust Low EQ + 0xB0 + 0x0F + + + + + + [EqualizerRack1_[Channel1]_Effect1] + DDJ200.leftDeck.eqKnob[1].input + Deck 1: Adjust Mid EQ + 0xB0 + 0x0B + + + + + + [EqualizerRack1_[Channel1]_Effect1] + DDJ200.leftDeck.eqKnob[2].input + Deck 1: Adjust High EQ + 0xB0 + 0x07 + + + + + + [QuickEffectRack1_[Channel1]] + DDJ200.leftDeck.super1.input + Super Knob (msb): control linked effect + 0xB6 + 0x17 + + + + + + [EqualizerRack1_[Channel2]_Effect1] + DDJ200.rightDeck.eqKnob[0].input + Deck 2: Adjust Low EQ + 0xB1 + 0x0F + + + + + + [EqualizerRack1_[Channel2]_Effect1] + DDJ200.rightDeck.eqKnob[1].input + Deck 2: Adjust Mid EQ + 0xB1 + 0x0B + + + + + + [EqualizerRack1_[Channel2]_Effect1] + DDJ200.rightDeck.eqKnob[2].input + Deck 2: Adjust High EQ + 0xB1 + 0x07 + + + + + + [QuickEffectRack1_[Channel2]] + DDJ200.rightDeck.super1.input + Quick Effect: Quick Effect Super Knob (control linked effect parameters) + 0xB6 + 0x18 + + + + + + [Channel1] + DDJ200.leftDeck.volume.inputMSB + Deck 1: Volume Fader + 0xB0 + 0x13 + + + + + + [Channel1] + DDJ200.leftDeck.volume.inputLSB + Deck 1: Volume Fader + 0xB0 + 0x33 + + + + + + [Channel2] + DDJ200.rightDeck.volume.inputMSB + Deck 2: Volume Fader + 0xB1 + 0x13 + + + + + + [Channel2] + DDJ200.rightDeck.volume.inputLSB + Deck 2: Volume Fader + 0xB1 + 0x33 + + + + + + [Channel1] + DDJ200.leftDeck.playButton.input + Deck 1: Play button + 0x90 + 0x0B + + + + + + [Channel2] + DDJ200.rightDeck.playButton.input + Deck 2: Play button + 0x91 + 0x0B + + + + + + [Channel1] + DDJ200.leftDeck.playButton.inputFaderStart + Deck 1: Shift and Fader start + 0x90 + 0x66 + + + + + + [Channel2] + DDJ200.rightDeck.playButton.inputFaderStart + Deck 2: Shift and Fader start + 0x91 + 0x66 + + + + + + [Channel1] + DDJ200.leftDeck.cueButton.input + Deck 1: Cue button + 0x90 + 0x0C + + + + + + [Channel2] + DDJ200.rightDeck.cueButton.input + Deck 2: Cue button + 0x91 + 0x0C + + + + + + [Channel1] + DDJ200.leftDeck.cueButton.inputFaderStop + Deck 1: Shift and Fader stop + 0x90 + 0x52 + + + + + + [Channel2] + DDJ200.rightDeck.cueButton.inputFaderStop + Deck 2: Shift and Fader stop + 0x91 + 0x52 + + + + + + [Channel1] + DDJ200.leftDeck.cueButton.input + Deck 1: Go to cue point and stop + 0x90 + 0x48 + + + + + + [Channel2] + DDJ200.rightDeck.cueButton.input + Deck 2: Go to cue point and stop + 0x91 + 0x48 + + + + + + [Channel1] + DDJ200.leftDeck.rate.inputMSB + Deck 1: Playback speed control + 0xB0 + 0x00 + + + + + + + [Channel1] + DDJ200.leftDeck.rate.inputLSB + Deck 1: Playback speed control + 0xB0 + 0x20 + + + + + + + [Channel2] + DDJ200.rightDeck.rate.inputMSB + Deck 2: Playback speed control + 0xB1 + 0x00 + + + + + + [Channel2] + DDJ200.rightDeck.rate.inputLSB + Deck 2: Playback speed control + 0xB1 + 0x20 + + + + + + [Channel1] + DDJ200.leftDeck.jogWheel.inputWheel + Deck 1: Jog + 0xB0 + 0x21 + + + + + + [Channel2] + DDJ200.rightDeck.jogWheel.inputWheel + Deck 2: Jog + 0xB1 + 0x21 + + + + + + [Channel2] + DDJ200.rightDeck.jogWheel.inputWheel + Deck 2: Scratch + 0xB1 + 0x22 + + + + + + [Channel1] + DDJ200.leftDeck.jogWheel.inputWheel + Deck 1: Scratch + 0xB0 + 0x22 + + + + + + [Channel2] + DDJ200.rightDeck.jogWheel.inputWheel + Deck 2: Scratch + 0xB1 + 0x23 + + + + + + [Channel1] + DDJ200.leftDeck.jogWheel.inputWheel + Deck 1: Scratch + 0xB0 + 0x23 + + + + + + [Channel1] + DDJ200.leftDeck.playButton.input + Deck 1: Shift Play + 0x90 + 0x47 + + + + + + [Channel2] + DDJ200.rightDeck.playButton.input + Deck 2: Shift Play + 0x91 + 0x47 + + + + + + + [Channel1] + DDJ200.leftDeck.pads[0].input + Hotcue 1, Deck 1: Set, preview, jump to + 0x97 + 0x00 + + + + + + [Channel1] + DDJ200.leftDeck.pads[1].input + Hotcue 2, Deck 1: Set, preview, jump to + 0x97 + 0x01 + + + + + + [Channel1] + DDJ200.leftDeck.pads[2].input + Hotcue 3, Deck 1: Set, preview, jump to + 0x97 + 0x02 + + + + + + [Channel1] + DDJ200.leftDeck.pads[3].input + Hotcue 4, Deck 1: Set, preview, jump to + 0x97 + 0x03 + + + + + + [Channel1] + DDJ200.leftDeck.pads[4].input + Hotcue 5, Deck 1: Set, preview, jump to + 0x97 + 0x04 + + + + + + [Channel1] + DDJ200.leftDeck.pads[5].input + Hotcue 6, Deck 1: Set, preview, jump to + 0x97 + 0x05 + + + + + + [Channel1] + DDJ200.leftDeck.pads[6].input + Hotcue 7, Deck 1: Set, preview, jump to + 0x97 + 0x06 + + + + + + [Channel1] + DDJ200.leftDeck.pads[7].input + Hotcue 8, Deck 1: Set, preview, jump to + 0x97 + 0x07 + + + + + + [Channel2] + DDJ200.rightDeck.pads[0].input + Hotcue 1, Deck 2: Set, preview, jump to + 0x99 + 0x00 + + + + + + [Channel2] + DDJ200.rightDeck.pads[1].input + Hotcue 2, Deck 2: Set, preview, jump to + 0x99 + 0x01 + + + + + + [Channel2] + DDJ200.rightDeck.pads[2].input + Hotcue 3, Deck 2: Set, preview, jump to + 0x99 + 0x02 + + + + + + [Channel2] + DDJ200.rightDeck.pads[3].input + Hotcue 4, Deck 2: Set, preview, jump to + 0x99 + 0x03 + + + + + + [Channel2] + DDJ200.rightDeck.pads[4].input + Hotcue 5, Deck 2: Set, preview, jump to + 0x99 + 0x04 + + + + + + [Channel2] + DDJ200.rightDeck.pads[5].input + Hotcue 6, Deck 2: Set, preview, jump to + 0x99 + 0x05 + + + + + + [Channel2] + DDJ200.rightDeck.pads[6].input + Hotcue 7, Deck 2: Set, preview, jump to + 0x99 + 0x06 + + + + + + [Channel2] + DDJ200.rightDeck.pads[7].input + Hotcue 8, Deck 2: Set, preview, jump to + 0x99 + 0x07 + + + + + + [Channel1] + DDJ200.leftDeck.pads[0].shiftedInput + Hotcue 1, Deck 1: Clear + 0x98 + 0x00 + + + + + + [Channel1] + DDJ200.leftDeck.pads[1].shiftedInput + Hotcue 2, Deck 1: Clear + 0x98 + 0x01 + + + + + + [Channel1] + DDJ200.leftDeck.pads[2].shiftedInput + Hotcue 3, Deck 1: Clear + 0x98 + 0x02 + + + + + + [Channel1] + DDJ200.leftDeck.pads[3].shiftedInput + Hotcue 4, Deck 1: Clear + 0x98 + 0x03 + + + + + + [Channel1] + DDJ200.leftDeck.pads[4].shiftedInput + Hotcue 5, Deck 1: Clear + 0x98 + 0x04 + + + + + + [Channel1] + DDJ200.leftDeck.pads[5].shiftedInput + Hotcue 6, Deck 1: Clear + 0x98 + 0x05 + + + + + + [Channel1] + DDJ200.leftDeck.pads[6].shiftedInput + Hotcue 7, Deck 1: Clear + 0x98 + 0x06 + + + + + + [Channel1] + DDJ200.leftDeck.pads[7].shiftedInput + Hotcue 8, Deck 1: Clear + 0x98 + 0x07 + + + + + + [Channel2] + DDJ200.rightDeck.pads[0].shiftedInput + Hotcue 1, Deck 2: Clear + 0x9A + 0x00 + + + + + + [Channel2] + DDJ200.rightDeck.pads[1].shiftedInput + Hotcue 2, Deck 2: Clear + 0x9A + 0x01 + + + + + + [Channel2] + DDJ200.rightDeck.pads[2].shiftedInput + Hotcue 3, Deck 2: Clear + 0x9A + 0x02 + + + + + + [Channel2] + DDJ200.rightDeck.pads[3].shiftedInput + Hotcue 4, Deck 2: Clear + 0x9A + 0x03 + + + + + + [Channel2] + DDJ200.rightDeck.pads[4].shiftedInput + Hotcue 5, Deck 2: Clear + 0x9A + 0x04 + + + + + + [Channel2] + DDJ200.rightDeck.pads[5].shiftedInput + Hotcue 6, Deck 2: Clear + 0x9A + 0x05 + + + + + + [Channel2] + DDJ200.rightDeck.pads[6].shiftedInput + Hotcue 7, Deck 2: Clear + 0x9A + 0x06 + + + + + + [Channel2] + DDJ200.rightDeck.pads[7].shiftedInput + 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 5c9c3928ea86..6edc852d1129 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -1,65 +1,69 @@ -var DDJ200 = { - fourDeckMode: false, - vDeckNo: [0, 1, 2], - vDeck: {}, - shiftPressed: {left: false, right: false}, - jogCounter: 0 -}; +/* + +DDJ-200 Midi Overview: +Deck n = 0/1: Midi in Midi out + (to PC) (from PC) + Jog (Platter) rotate Vinyl mode on Bn 22 hh - result = value - 64 + Vinyl mode off Bn 23 hh - result = value - 64 + shift Bn 29 hh - result = value - 64 + Jog (Platter) touch 9n 36 hh - OFF=0x00, ON=0x7F + shift 9n 67 hh - OFF=0x00, ON=0x7F + Jog (Side) rotate normal/shift Bn 21 hh - result = value - 64 + Beat Sync press 9n 58 hh [midi in] OFF=0x00, ON=0x7F + long press 9n 5C hh - OFF=0x00, ON=0x7F + press shift 9n 60 hh [midi in] OFF=0x00, ON=0x7F + Tempo slide normal/shift Bn 00/20 xx - MSB / LSB + Play/Pause press 9n 0B hh [midi in] OFF=0x00, ON=0x7F + press shift 9n 47 hh [midi in] OFF=0x00, ON=0x7F + Cue press 9n 0C hh [midi in] OFF=0x00, ON=0x7F + press shift 9n 48 hh [midi in] OFF=0x00, ON=0x7F + Shift press 9n 3F hh - OFF=0x00, ON=0x7F + EQ Hi rotate Bn 07/27 xx - MSB / LSB + EQ Mid rotate Bn 0B/2B xx - MSB / LSB + EQ Low rotate Bn 0F/2F xx - MSB / LSB + Color Fx CH1 rotate B6 17/37 xx - MSB / LSB + Color Fx CH2 rotate B6 18/38 xx - MSB / LSB + Master Cue press 96 63 hh [midi in] OFF=0x00, ON=0x7F + press shift 96 78 hh [midi in] OFF=0x00, ON=0x7F + Cue (Headpho) press 9n 54 hh [midi in] OFF=0x00, ON=0x7F + press shift 9n 68 hh [midi in] OFF=0x00, ON=0x7F + Ch Fader slide Bn 13/33 xx - MSB / LSB + Crossfader slide B6 1F/3F xx - MSB / LSB + both above zero->notzero shift 9n 66 hh [midi in] OFF=0x00, ON=0x7F (PLAY message for fader start) + notzero->zero shift 9n 52 hh [midi in] OFF=0x00, ON=0x7F (CUE message for fader start) + TransitionFX press 96 59 hh [midi in] OFF=0x00, ON=0x7F + press shift 96 5A hh [midi in] OFF=0x00, ON=0x7F + + Deck1 PAD p=7, Deck1 SHIFT PAD p=8, Deck2 PAD p=9, Deck2 SHIFT PAD p=A + PAD 1 press 9p 00 hh [midi in] OFF=0x00, ON=0x7F + PAD 2 press 9p 01 hh [midi in] OFF=0x00, ON=0x7F + PAD 3 press 9p 02 hh [midi in] OFF=0x00, ON=0x7F + PAD 4 press 9p 03 hh [midi in] OFF=0x00, ON=0x7F + PAD 5 press 9p 04 hh [midi in] OFF=0x00, ON=0x7F + PAD 6 press 9p 05 hh [midi in] OFF=0x00, ON=0x7F + PAD 7 press 9p 06 hh [midi in] OFF=0x00, ON=0x7F + PAD 8 press 9p 07 hh [midi in] OFF=0x00, ON=0x7F +*/ + +var DDJ200 = { }; DDJ200.init = function() { - for (var i = 1; i <= 4; i++) { - - // create associative arrays for 4 virtual decks - this.vDeck[i] = { - syncEnabled: false, - volMSB: 0, - rateMSB: 0, - jogEnabled: true, - }; - - var vgroup = "[Channel" + i + "]"; - - // run updateDeckLeds after every track load to set LEDs accordingly - engine.makeConnection(vgroup, "track_loaded", function(ch, vgroup) { - DDJ200.updateDeckLeds(vgroup); - }); - - // run switchPlayLED after play/pause track to set LEDs accordingly - engine.makeConnection(vgroup, "play", function(ch, vgroup) { - var vDeckNo = script.deckFromGroup(vgroup); - var d = (vDeckNo % 2) ? 0 : 1; - DDJ200.switchPlayLED(d, ch); - }); - - // run switchSyncLED after sync toggle to set LEDs accordingly - engine.makeConnection(vgroup, "sync_enabled", function(ch, vgroup) { - var vDeckNo = script.deckFromGroup(vgroup); - var d = (vDeckNo % 2) ? 0 : 1; - DDJ200.switchSyncLED(d, ch); - }); - - // listen to changes on hotcues - for (var j = 1; j <= 8; j++) { - // run switchPadLED after every hotcue update - engine.makeConnection(vgroup, "hotcue_" + j + "_enabled", function(ch, vgroup, control) { - var pad = Number(control.split("_")[1]); - var vDeckNo = script.deckFromGroup(vgroup); - var d = (vDeckNo % 2) ? 0 : 1; // d = deckNo - 1 - DDJ200.switchPadLED(d, pad, ch); - }); - } - - // set Pioneer CDJ cue mode for all decks - engine.setValue(vgroup, "cue_cdj", true); - } + DDJ200.leftDeck = new DDJ200.Deck([1, 3], 1); + DDJ200.rightDeck = new DDJ200.Deck([2, 4], 2); DDJ200.LEDsOff(); // start with focus on library for selecting tracks (delay seems required) - engine.beginTimer(500, () => { + engine.beginTimer(500, function() { engine.setValue("[Library]", "MoveFocus", 1); }, true); + engine.setValue("[Channel3]", "volume", 0); + engine.setValue("[Channel4]", "volume", 0); + for (let i = 1; i <= 8; i++) { + engine.setValue(`[Sampler${i}]`, "pregain", 0.2); + }; + // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); }; @@ -69,338 +73,438 @@ DDJ200.shutdown = function() { }; DDJ200.LEDsOff = function() { // turn off LED buttons: - - for (var i = 0; i <= 1; i++) { + for (let 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++) { + for (let j = 0; j <= 8; j++) { midi.sendShortMsg(0x97 + 2 * i, j, 0x00); // hotcue - } - } -}; - -DDJ200.updateDeckLeds = function(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 - 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.scratch = 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(DDJ200.vDeckNo[script.deckFromGroup(group)], - value - 64); -}; - -DDJ200.touch = function(channel, control, value, status, group) { - var vDeckNo = DDJ200.vDeckNo[script.deckFromGroup(group)]; - if (value) { - // enable scratch - var alpha = 1.0 / 8; - engine.scratchEnable(vDeckNo, 128, 33 + 1 / 3, alpha, alpha / 32); - // disable jog not to prevent track alignment - DDJ200.vDeck[vDeckNo].jogEnabled = false; - } else { - // enable jog after 900 ms again - engine.beginTimer(900, () => { - DDJ200.vDeck[vDeckNo].jogEnabled = true; - }, true); - // disable scratch - engine.scratchDisable(vDeckNo); - } -}; - -DDJ200.seek = function(channel, control, value, status, group) { - var oldPos = engine.getValue(group, "playposition"); - // Since ‘playposition’ is normalized to unity, we need to scale by - // song duration in order for the jog wheel to cover the same amount - // of time given a constant turning angle. - var duration = engine.getValue(group, "duration"); - var newPos = Math.max(0, oldPos + ((value - 64) * 0.2 / duration)); - - var deckNo = script.deckFromGroup(group); - var vgroup = "[Channel" + DDJ200.vDeckNo[deckNo] + "]"; - engine.setValue(vgroup, "playposition", newPos); // Strip search -}; - -DDJ200.headmix = function(channel, control, 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); - engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 1); - midi.sendShortMsg(0x96, 0x63, masterMixEnabled ? 0 : 0x7F); // 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 + "]"; - // calculate 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 + "]"; - // calculate 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); +DDJ200.padLEDsOff = function() { // turn off LED buttons: + for (let 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 (let j = 0; j <= 8; j++) { + midi.sendShortMsg(0x97 + 2 * i, j, 0x00); // hotcue + }; + }; +}; + +DDJ200.padModes = ["Hotcue", "Loop", "Effect", "Jump"]; +DDJ200.padModeIndex = 0; +DDJ200.transFxButton = new components.Button({ + blinkConnection: undefined, + input: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + if (DDJ200.padModeIndex === (DDJ200.padModes.length - 1)) { + DDJ200.padModeIndex = 0; + } else { + if (DDJ200.leftDeck.shiftPressed || DDJ200.rightDeck.shiftPressed) { + DDJ200.padModeIndex = DDJ200.padModes.length - 1; + } else { + DDJ200.padModeIndex = (DDJ200.padModeIndex + 1) % (DDJ200.padModes.length - 1); + }; + }; + DDJ200.leftDeck.pads.forEach(function(e) { + e.updateOutKey(); + }); + DDJ200.rightDeck.pads.forEach(function(e) { + e.updateOutKey(); + }); + this.output(); + }; + }, + output: function(_value, _g, _control) { + if (this.blinkConnection) { + this.blinkConnection.disconnect(); + this.blinkConnection = undefined; + }; + switch (DDJ200.padModes[DDJ200.padModeIndex]) { + case "Hotcue": + midi.sendShortMsg(0x96, 0x59, 0x00); + midi.sendShortMsg(0x96, 0x5A, 0x00); + break; + case "Loop": + midi.sendShortMsg(0x96, 0x59, 0x7F); + midi.sendShortMsg(0x96, 0x5A, 0x7F); + break; + case "Effect": + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + midi.sendShortMsg(0x96, 0x59, 0x7F * value); + midi.sendShortMsg(0x96, 0x5A, 0x7F * value); + }); + break; + case "Jump": + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + midi.sendShortMsg(0x96, 0x59, 0x7F * value); + midi.sendShortMsg(0x96, 0x5A, 0x7F * value); + for (let midiChannel = 0; midiChannel < 4; midiChannel++) { + for (let i = 0; i < 8; i++) { + midi.sendShortMsg(0x97 + midiChannel, i, 0x7F * value); + }; + }; + }); + break; + }; + }, +}); + +DDJ200.headMixButton = new components.Button({ + midi: [0x96, 0x63], + key: "headMix", + type: components.Button.prototype.types.toggle, + input: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + const masterMixEnabled = (engine.getValue("[Master]", "headMix") >= 0); + engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 0); + this.send(masterMixEnabled?0:0x7F); // set LED + }; + }, + shiftedInput: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); + if (!engine.getValue("[Skin]", "show_4decks")) { + DDJ200.leftDeck.setCurrentDeck("[Channel1]"); + DDJ200.rightDeck.setCurrentDeck("[Channel2]"); + if (DDJ200.leftDeck.syncButton.blinkConnection) { + DDJ200.leftDeck.syncButton.blinkConnection.disconnect(); + }; + if (DDJ200.rightDeck.syncButton.blinkConnection) { + DDJ200.rightDeck.syncButton.blinkConnection.disconnect(); + }; + }; + }; + }, +}); + +DDJ200.shiftButton = new components.Button({ + input: function(_channel, _control, value, status, _g) { + DDJ200.leftDeck.shiftPressed = value && (status === 0x90); + DDJ200.rightDeck.shiftPressed = value && (status === 0x91); + if (value) { + DDJ200.leftDeck.shift(); + DDJ200.rightDeck.shift(); } 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 preferred - midi.sendShortMsg(status, 0x0B, 0x7F * engine.getValue(vgroup, "play")); - } -}; - -DDJ200.hotcueNActivate = 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 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) { - 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, "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 + "]"; - DDJ200.switchPlayLED(d, engine.getValue(vgroup, "play")); - midi.sendShortMsg(0x90 + d, 0x0C, 0x7F * - (engine.getValue(vgroup, "cue_point") !== -1)); - DDJ200.switchSyncLED(d, 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++) { - var isButtonEnabled = engine.getValue(vgroup, "hotcue_" + i + "_enabled"); - DDJ200.switchPadLED(d, i, isButtonEnabled); - } -}; + DDJ200.leftDeck.unshift(); + DDJ200.rightDeck.unshift(); + }; + DDJ200.leftDeck.reconnectComponents(); + DDJ200.rightDeck.reconnectComponents(); + }, +}); + +DDJ200.Deck = function(deckNumbers, midiChannel) { + components.Deck.call(this, deckNumbers); + const theDeck = this; + + // set Pioneer CDJ cue mode for all decks + engine.setValue(this.currentDeck, "cue_cdj", true); + + this.jogWheel = new components.JogWheelBasic({ + wheelResolution: 128, // how many ticks per revolution the jogwheel has + alpha: 1/8, // alpha-filter + beta: 1/8/32, + rpm: 33 + 1/3, + inValueScale: function(value) { + return value - 64; + }, + inKey: "jog", + jogCounter: 0, + inputSeek: function(_channel, _control, value, _status, group) { + if (DDJ200.leftDeck.shiftPressed) { + this.jogCounter += this.inValueScale(value); + if (this.jogCounter > 9) { + engine.setValue("[Library]", "MoveDown", true); + this.jogCounter = 0; + } else if (this.jogCounter < -9) { + engine.setValue("[Library]", "MoveUp", true); + this.jogCounter = 0; + }; + } else { + const oldPos = engine.getValue(group, "playposition"); + // Since ‘playposition’ is normalized to unity, we need to scale by + // song duration in order for the jog wheel to cover the same amount + // of time given a constant turning angle. + const duration = engine.getValue(group, "duration"); + const newPos = Math.max(0, oldPos + (this.inValueScale(value) * 0.2 / duration)); + + engine.setValue(group, "playposition", newPos); // Strip search + }; + }, + }); + + this.syncButton = new components.Button({ + midi: [0x8F + midiChannel, 0x58], + key: "sync_enabled", + input: function(_channel, _control, value, _status, _g) { + if (value) { + if (engine.getValue(this.group, "sync_enabled") === 0) { + engine.setValue(this.group, "beatsync", 1); + } else { + engine.setValue(this.group, "sync_enabled", 0); + }; + }; + }, + inputLongPress: function(_channel, _control, value, _status, _g) { + if (value) { + engine.setValue(this.group, "sync_enabled", 1); + }; + }, + shiftedInput: function(_channel, _control, value, _status, _g) { + if (value) { + if (engine.getValue("[Skin]", "show_4decks")) { + theDeck.toggle(); + if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + midi.sendShortMsg(0x8F + midiChannel, 0x58, 0x7F * value); + }); + } else if (this.blinkConnection) { + this.blinkConnection.disconnect(); + }; + } else { + const currentRange = engine.getValue(this.group, "rateRange"); + engine.setValue(this.group, "rateRange", (currentRange>0.9)?0.1:currentRange+0.1); + }; + }; + }, + }); + + this.playButton = new components.PlayButton({ + outKey: "play_indicator", + shift: function() { + this.inKey = "reverse"; + this.midi = [0x8F + midiChannel, 0x47]; + }, + inputFaderStart: function(channel, control, value, status, _g) { + this.inKey = "play"; + this.input(channel, control, value, status, _g); + this.inKey = "reverse"; + }, + unshift: function() { + this.inKey = "play"; + this.midi = [0x8F + midiChannel, 0x0B]; + }, + }); + + this.cueButton = new components.CueButton({ + outKey: "cue_indicator", + shift: function() { + this.inKey = "cue_gotoandstop"; + this.midi = [0x8F + midiChannel, 0x48]; + }, + inputFaderStop: function(channel, control, value, status, _g) { + this.inKey = "cue_set"; + this.input(channel, control, value, status, _g); + this.inKey = "cue_gotoandstop"; + this.input(channel, control, value, status, _g); + }, + unshift: function() { + this.inKey = "cue_default"; + this.midi = [0x8F + midiChannel, 0x0C]; + }, + }); + + this.pads = []; + for (let i = 0; i < 8; i++) { + this.pads[i] = new components.HotcueButton({ + number: i + 1, + input: function(channel, control, value, status, g) { + this[`input${DDJ200.padModes[DDJ200.padModeIndex]}`](channel, control, value, status, g); + }, + shiftedInput: function(channel, control, value, status, g) { + this[`inputShift${DDJ200.padModes[DDJ200.padModeIndex]}`](channel, control, value, status, g); + }, + output: function(value, g, control) { + this[`output${DDJ200.padModes[DDJ200.padModeIndex]}`](value, g, control); + }, + midiNormal: [0x97 + (midiChannel - 1)*2, 0x00 + i], + midiShift: [0x98 + (midiChannel - 1)*2, 0x00 + i], + shift: function() { + this.midi = this.midiShift; + }, + unshift: function() { + this.midi = this.midiNormal; + }, + outKey: this[`outKey${DDJ200.padModes[DDJ200.padModeIndex]}`], + connect: function() { + if (DDJ200.padModes[DDJ200.padModeIndex] !== "effect") { + components.HotcueButton.prototype.connect.call(this); + } else { + this.outKeyEffectConnect(); + }; + }, + updateOutKey: function() { + this.outKey = this[`outKey${ DDJ200.padModes[DDJ200.padModeIndex]}`]; + this.disconnect(); + this.connect(); + this.trigger(); + }, + + /* ----------- PADs in Hotcue Mode ----------- */ + inputHotcue: function(_channel, _control, value, _status, _g) { + engine.setValue(this.group, `hotcue_${this.number}_activate`, value); + }, + inputShiftHotcue: function(_channel, _control, value, _status, _g) { + if (value) { + engine.setValue(this.group, `hotcue_${this.number}_clear`, value); + }; + }, + outKeyHotcue: `hotcue_${i + 1}_status`, + outputHotcue: function(value, _g, _control) { + this.send(this.outValueScale(value)); + }, + + /* ----------- PADs in Loop Mode ----------- */ + _inputLoop: function(channel, _control, value, _status, mode) { + if (value) { // only if button pressed + const loopSize = (Math.pow(2, this.number) * 0.25); + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === loopSize); + engine.setValue(this.group, "beatloop_size", loopSize); + for (let j = 0; j <= 8; j++) { + midi.sendShortMsg(0x90 + channel, j, 0x00); // hotcue + }; + this.send(this.outValueScale(value)); + if (matchingLoopSize || !loopEnabled) { + engine.setValue(this.group, mode, true); + }; + }; + }, + inputLoop: function(channel, control, value, status, _g) { + const thisDeck = (channel === 7)?DDJ200.leftDeck.currentDeck:DDJ200.rightDeck.currentDeck; + if (!engine.getValue(thisDeck, "track_loaded")) { return; } + this._inputLoop(channel, control, value, status, "beatloop_activate"); + }, + inputShiftLoop: function(channel, control, value, status, _g) { + const thisDeck = (channel === 8)?DDJ200.leftDeck.currentDeck:DDJ200.rightDeck.currentDeck; + if (!engine.getValue(thisDeck, "track_loaded")) { return; } + this._inputLoop(channel, control, value, status, "beatlooproll_activate"); + }, + outKeyLoop: "loop_enabled", + outputLoop: function(value, _g, _control) { + const loopSize = (Math.pow(2, this.number) * 0.25); + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === loopSize); + value = matchingLoopSize?loopEnabled:0; + this.send(this.outValueScale(value)); + }, + + /* ----------- PADs in Effect Mode ----------- */ + inputEffect: function(_channel, control, value, _status, _g) { + if (control < 4) { + const sampler = `[Sampler${control + 1 +(this.deckFromGroup(this.group)-1)*4}]`; + if (engine.getValue(sampler, "play")) { + engine.setValue(sampler, "stop", value); + } else { + engine.setValue(sampler, "cue_gotoandplay", value); + }; + } else if (control < 7) { + const effect = `[EffectRack1_EffectUnit${this.deckFromGroup(this.group)}_Effect${control - 3}]`; + engine.setValue(effect, "enabled", value); + } else { + if (value) { + bpm.tapButton(this.deckFromGroup(this.group)); + }; + this.send(this.outValueScale(value)); + }; + }, + inputShiftEffect: function(channel, control, value, status, _g) { + this.inputEffect(channel, control, value, status, _g); + }, + deckFromGroup: function(group) { + const deckGroup = script.deckFromGroup(group); + return (((deckGroup - 1) % 2) + 1); + }, + outKeyEffectConnect: function() { + const control = this.number - 1; + if (control < 4) { + const sampler = `[Sampler${control + 1 + (this.deckFromGroup(this.group)-1) * 4}]`; + this.connections[0] = engine.makeConnection(sampler, "play", this.output.bind(this)); + } else if (control < 7) { + const effect = `[EffectRack1_EffectUnit${this.deckFromGroup(this.group)}_Effect${control - 3}]`; + this.connections[0] = engine.makeConnection(effect, "enabled", this.output.bind(this)); + } else { + this.connections[0] = undefined; + }; + }, + outKeyEffect: undefined, + outputEffect: function(value, _g, _control) { + this.send(this.outValueScale(value)); + }, + + /* ----------- PADs in BeatJump Mode ----------- */ + inputJump: function(_channel, control, value, _status, _g) { + if (value) { // only if button pressed + engine.setValue(this.group, "beatjump_size", Math.pow(2, control+2)); + engine.setValue(this.group, "beatjump_forward", true); + }; + }, + inputShiftJump: function(_channel, control, value, _status, _g) { + if (value) { // only if button pressed + engine.setValue(this.group, "beatjump_size", Math.pow(2, control+2)); + engine.setValue(this.group, "beatjump_backward", true); + }; + }, + outKeyJump: `hotcue_${i + 1}_status`, + outputJump: function(_value, _g, _control) { + this.send(this.outValueScale(0)); + }, + }); + }; + this.pads.forEach(function(e) { e.updateOutKey(); }); + + this.pflButton = new components.Button({ + midi: [0x8F + midiChannel, 0x54], + key: "pfl", + type: components.Button.prototype.types.toggle, + }); + + this.loadTrack = new components.Button({ + midi: [0x8F + midiChannel, 0x68], + type: components.Button.prototype.types.toggle, + input: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + script.triggerControl(this.group, "LoadSelectedTrack", true); + }; + }, + }); + + this.volume = new components.Pot({ + inKey: "volume", + }); + + this.rate = new components.Pot({ + inKey: "rate", + invert: 1, + }); + + this.eqKnob = []; + for (let i = 0; i < 3; i++) { + this.eqKnob[i] = new components.Pot({ + group: `[EqualizerRack1_${this.currentDeck}_Effect1]`, + inKey: `parameter${i+1}`, + }); + }; -DDJ200.switchPlayLED = function(deck, enabled) { - midi.sendShortMsg(0x90 + deck, 0x0B, 0x7F * enabled); -}; + this.super1 = new components.Pot({ + group: `[QuickEffectRack1_${this.currentDeck}]`, + inKey: "super1", + }); -DDJ200.switchSyncLED = function(deck, enabled) { - midi.sendShortMsg(0x90 + deck, 0x58, 0x7F * enabled); -}; + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = this.currentDeck; + }; + }); -DDJ200.switchPadLED = function(deck, pad, enabled) { - midi.sendShortMsg(0x97 + 2 * deck, pad - 1, 0x7F * 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 - } - } -}; +DDJ200.Deck.prototype = new components.Deck(); From 07b2adb02cc974f977d37894c3062b6b930ca704 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 17:27:27 +0000 Subject: [PATCH 02/70] Pioneer DDJ-200: added eslint excemption --- res/controllers/Pioneer-DDJ-200-scripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 6edc852d1129..cc5d643c3a6a 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -45,6 +45,7 @@ Deck n = 0/1: Midi in Midi out PAD 8 press 9p 07 hh [midi in] OFF=0x00, ON=0x7F */ +// eslint-disable-next-line no-var var DDJ200 = { }; DDJ200.init = function() { From 849423c82c24bd736599d6ac7e94c16da86aacdb Mon Sep 17 00:00:00 2001 From: Rene Date: Wed, 24 Sep 2025 18:28:22 +0000 Subject: [PATCH 03/70] Pioneer DDJ-200: removed volume/gain changes removed volume and gain changes, they don't belong into the mapping Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer-DDJ-200-scripts.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index cc5d643c3a6a..76c5df5b40d9 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -59,11 +59,6 @@ DDJ200.init = function() { engine.setValue("[Library]", "MoveFocus", 1); }, true); - engine.setValue("[Channel3]", "volume", 0); - engine.setValue("[Channel4]", "volume", 0); - for (let i = 1; i <= 8; i++) { - engine.setValue(`[Sampler${i}]`, "pregain", 0.2); - }; // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); From 25673a5af2f92041e394b2cc81bf6d851e5c6927 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 18:47:07 +0000 Subject: [PATCH 04/70] Pioneer DDJ-200: don't override user options user can choose this in GUI, don't override it --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 76c5df5b40d9..e1e3ec44c870 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -201,9 +201,6 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { components.Deck.call(this, deckNumbers); const theDeck = this; - // set Pioneer CDJ cue mode for all decks - engine.setValue(this.currentDeck, "cue_cdj", true); - this.jogWheel = new components.JogWheelBasic({ wheelResolution: 128, // how many ticks per revolution the jogwheel has alpha: 1/8, // alpha-filter From c62d61003bbdf358ccd5a91b6a1c62af14a49569 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 19:48:05 +0000 Subject: [PATCH 05/70] Pioneer DDJ-200: shutdown will switch off all LEDs there is no need for any additional function --- res/controllers/Pioneer-DDJ-200-scripts.js | 31 ++-------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index e1e3ec44c870..ff580a022bfa 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -52,8 +52,6 @@ DDJ200.init = function() { DDJ200.leftDeck = new DDJ200.Deck([1, 3], 1); DDJ200.rightDeck = new DDJ200.Deck([2, 4], 2); - DDJ200.LEDsOff(); - // start with focus on library for selecting tracks (delay seems required) engine.beginTimer(500, function() { engine.setValue("[Library]", "MoveFocus", 1); @@ -65,33 +63,8 @@ DDJ200.init = function() { }; DDJ200.shutdown = function() { - DDJ200.LEDsOff(); -}; - -DDJ200.LEDsOff = function() { // turn off LED buttons: - for (let 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 (let j = 0; j <= 8; j++) { - midi.sendShortMsg(0x97 + 2 * i, j, 0x00); // hotcue - }; - }; -}; - -DDJ200.padLEDsOff = function() { // turn off LED buttons: - for (let 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 (let j = 0; j <= 8; j++) { - midi.sendShortMsg(0x97 + 2 * i, j, 0x00); // hotcue - }; - }; + DDJ200.leftDeck.shutdown(); + DDJ200.rightDeck.shutdown(); }; DDJ200.padModes = ["Hotcue", "Loop", "Effect", "Jump"]; From 43739b8dc733aa6f24f75cec52e1437013d7d673 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 20:21:18 +0000 Subject: [PATCH 06/70] Pioneer DDJ-200: moved Button initializations into init initializing buttons before init might result in trouble, moved them into the init function --- res/controllers/Pioneer-DDJ-200-scripts.js | 207 +++++++++++---------- 1 file changed, 105 insertions(+), 102 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index ff580a022bfa..bbc5134563ca 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -48,6 +48,9 @@ Deck n = 0/1: Midi in Midi out // eslint-disable-next-line no-var var DDJ200 = { }; +DDJ200.padModes = ["Hotcue", "Loop", "Effect", "Jump"]; +DDJ200.padModeIndex = 0; + DDJ200.init = function() { DDJ200.leftDeck = new DDJ200.Deck([1, 3], 1); DDJ200.rightDeck = new DDJ200.Deck([2, 4], 2); @@ -60,115 +63,115 @@ DDJ200.init = function() { // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); -}; -DDJ200.shutdown = function() { - DDJ200.leftDeck.shutdown(); - DDJ200.rightDeck.shutdown(); -}; + DDJ200.headMixButton = new components.Button({ + midi: [0x96, 0x63], + key: "headMix", + type: components.Button.prototype.types.toggle, + input: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + const masterMixEnabled = (engine.getValue("[Master]", "headMix") >= 0); + engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 0); + this.send(masterMixEnabled?0:0x7F); // set LED + }; + }, + shiftedInput: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); + if (!engine.getValue("[Skin]", "show_4decks")) { + DDJ200.leftDeck.setCurrentDeck("[Channel1]"); + DDJ200.rightDeck.setCurrentDeck("[Channel2]"); + if (DDJ200.leftDeck.syncButton.blinkConnection) { + DDJ200.leftDeck.syncButton.blinkConnection.disconnect(); + }; + if (DDJ200.rightDeck.syncButton.blinkConnection) { + DDJ200.rightDeck.syncButton.blinkConnection.disconnect(); + }; + }; + }; + }, + }); -DDJ200.padModes = ["Hotcue", "Loop", "Effect", "Jump"]; -DDJ200.padModeIndex = 0; -DDJ200.transFxButton = new components.Button({ - blinkConnection: undefined, - input: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed - if (DDJ200.padModeIndex === (DDJ200.padModes.length - 1)) { - DDJ200.padModeIndex = 0; - } else { - if (DDJ200.leftDeck.shiftPressed || DDJ200.rightDeck.shiftPressed) { - DDJ200.padModeIndex = DDJ200.padModes.length - 1; + DDJ200.transFxButton = new components.Button({ + blinkConnection: undefined, + input: function(_channel, _control, value, _status, _g) { + if (value) { // only if button pressed + if (DDJ200.padModeIndex === (DDJ200.padModes.length - 1)) { + DDJ200.padModeIndex = 0; } else { - DDJ200.padModeIndex = (DDJ200.padModeIndex + 1) % (DDJ200.padModes.length - 1); + if (DDJ200.leftDeck.shiftPressed || DDJ200.rightDeck.shiftPressed) { + DDJ200.padModeIndex = DDJ200.padModes.length - 1; + } else { + DDJ200.padModeIndex = (DDJ200.padModeIndex + 1) % (DDJ200.padModes.length - 1); + }; }; + DDJ200.leftDeck.pads.forEach(function(e) { + e.updateOutKey(); + }); + DDJ200.rightDeck.pads.forEach(function(e) { + e.updateOutKey(); + }); + this.output(); }; - DDJ200.leftDeck.pads.forEach(function(e) { - e.updateOutKey(); - }); - DDJ200.rightDeck.pads.forEach(function(e) { - e.updateOutKey(); - }); - this.output(); - }; - }, - output: function(_value, _g, _control) { - if (this.blinkConnection) { - this.blinkConnection.disconnect(); - this.blinkConnection = undefined; - }; - switch (DDJ200.padModes[DDJ200.padModeIndex]) { - case "Hotcue": - midi.sendShortMsg(0x96, 0x59, 0x00); - midi.sendShortMsg(0x96, 0x5A, 0x00); - break; - case "Loop": - midi.sendShortMsg(0x96, 0x59, 0x7F); - midi.sendShortMsg(0x96, 0x5A, 0x7F); - break; - case "Effect": - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - midi.sendShortMsg(0x96, 0x59, 0x7F * value); - midi.sendShortMsg(0x96, 0x5A, 0x7F * value); - }); - break; - case "Jump": - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - midi.sendShortMsg(0x96, 0x59, 0x7F * value); - midi.sendShortMsg(0x96, 0x5A, 0x7F * value); - for (let midiChannel = 0; midiChannel < 4; midiChannel++) { - for (let i = 0; i < 8; i++) { - midi.sendShortMsg(0x97 + midiChannel, i, 0x7F * value); + }, + output: function(_value, _g, _control) { + if (this.blinkConnection) { + this.blinkConnection.disconnect(); + this.blinkConnection = undefined; + }; + switch (DDJ200.padModes[DDJ200.padModeIndex]) { + case "Hotcue": + midi.sendShortMsg(0x96, 0x59, 0x00); + midi.sendShortMsg(0x96, 0x5A, 0x00); + break; + case "Loop": + midi.sendShortMsg(0x96, 0x59, 0x7F); + midi.sendShortMsg(0x96, 0x5A, 0x7F); + break; + case "Effect": + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + midi.sendShortMsg(0x96, 0x59, 0x7F * value); + midi.sendShortMsg(0x96, 0x5A, 0x7F * value); + }); + break; + case "Jump": + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + midi.sendShortMsg(0x96, 0x59, 0x7F * value); + midi.sendShortMsg(0x96, 0x5A, 0x7F * value); + for (let midiChannel = 0; midiChannel < 4; midiChannel++) { + for (let i = 0; i < 8; i++) { + midi.sendShortMsg(0x97 + midiChannel, i, 0x7F * value); + }; }; - }; - }); - break; - }; - }, -}); - -DDJ200.headMixButton = new components.Button({ - midi: [0x96, 0x63], - key: "headMix", - type: components.Button.prototype.types.toggle, - input: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed - const masterMixEnabled = (engine.getValue("[Master]", "headMix") >= 0); - engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 0); - this.send(masterMixEnabled?0:0x7F); // set LED - }; - }, - shiftedInput: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed - engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); - if (!engine.getValue("[Skin]", "show_4decks")) { - DDJ200.leftDeck.setCurrentDeck("[Channel1]"); - DDJ200.rightDeck.setCurrentDeck("[Channel2]"); - if (DDJ200.leftDeck.syncButton.blinkConnection) { - DDJ200.leftDeck.syncButton.blinkConnection.disconnect(); - }; - if (DDJ200.rightDeck.syncButton.blinkConnection) { - DDJ200.rightDeck.syncButton.blinkConnection.disconnect(); - }; + }); + break; }; - }; - }, -}); - -DDJ200.shiftButton = new components.Button({ - input: function(_channel, _control, value, status, _g) { - DDJ200.leftDeck.shiftPressed = value && (status === 0x90); - DDJ200.rightDeck.shiftPressed = value && (status === 0x91); - if (value) { - DDJ200.leftDeck.shift(); - DDJ200.rightDeck.shift(); - } else { - DDJ200.leftDeck.unshift(); - DDJ200.rightDeck.unshift(); - }; - DDJ200.leftDeck.reconnectComponents(); - DDJ200.rightDeck.reconnectComponents(); - }, -}); + }, + }); + + DDJ200.shiftButton = new components.Button({ + input: function(_channel, _control, value, status, _g) { + DDJ200.leftDeck.shiftPressed = value && (status === 0x90); + DDJ200.rightDeck.shiftPressed = value && (status === 0x91); + if (value) { + DDJ200.leftDeck.shift(); + DDJ200.rightDeck.shift(); + } else { + DDJ200.leftDeck.unshift(); + DDJ200.rightDeck.unshift(); + }; + DDJ200.leftDeck.reconnectComponents(); + DDJ200.rightDeck.reconnectComponents(); + }, + }); + + +}; + +DDJ200.shutdown = function() { + DDJ200.leftDeck.shutdown(); + DDJ200.rightDeck.shutdown(); +}; DDJ200.Deck = function(deckNumbers, midiChannel) { components.Deck.call(this, deckNumbers); From 02fbd3a7639fe890699c7d471134dfa9dfca9ac9 Mon Sep 17 00:00:00 2001 From: Rene Date: Wed, 24 Sep 2025 20:31:33 +0000 Subject: [PATCH 07/70] Pioneer DDJ-200: use inKey for loading tracks use inKey instead of separate input function Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer-DDJ-200-scripts.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index bbc5134563ca..21b43bacddbe 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -438,12 +438,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { this.loadTrack = new components.Button({ midi: [0x8F + midiChannel, 0x68], - type: components.Button.prototype.types.toggle, - input: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed - script.triggerControl(this.group, "LoadSelectedTrack", true); - }; - }, + inKey: "LoadSelectedTrack", }); this.volume = new components.Pot({ From 48d5f15051456fa7ed3bcacd2db47ebc49a8ed49 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 20:35:08 +0000 Subject: [PATCH 08/70] Pioneer DDJ-200: disconnect outKey before change first disconnect, than change the outKey --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 21b43bacddbe..2ad230656e53 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -311,8 +311,8 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }; }, updateOutKey: function() { - this.outKey = this[`outKey${ DDJ200.padModes[DDJ200.padModeIndex]}`]; this.disconnect(); + this.outKey = this[`outKey${ DDJ200.padModes[DDJ200.padModeIndex]}`]; this.connect(); this.trigger(); }, From dbaa9bdb2794d79b54148afa4af5f3c63edf95f8 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 23:20:47 +0000 Subject: [PATCH 09/70] Pioneer DDJ-200: cleanup shift button behaviour simplified shift button behaviour and added buttons to related decks --- res/controllers/Pioneer DDJ-200.midi.xml | 4 +- res/controllers/Pioneer-DDJ-200-scripts.js | 48 +++++++++------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index d0900a107f4a..2e8c5eaa2cdb 100644 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -15,7 +15,7 @@ [Channel1] - DDJ200.shiftButton.input + DDJ200.leftDeck.shiftButton.input Deck 1: Shift pressed 0x90 0x3F @@ -25,7 +25,7 @@ [Channel2] - DDJ200.shiftButton.input + DDJ200.rightDeck.shiftButton.input Deck 2: Shift pressed 0x91 0x3F diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 2ad230656e53..de34f5ba13a9 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -99,7 +99,7 @@ DDJ200.init = function() { if (DDJ200.padModeIndex === (DDJ200.padModes.length - 1)) { DDJ200.padModeIndex = 0; } else { - if (DDJ200.leftDeck.shiftPressed || DDJ200.rightDeck.shiftPressed) { + if (DDJ200.leftDeck.shiftButton.pressed || DDJ200.rightDeck.shiftButton.pressed) { DDJ200.padModeIndex = DDJ200.padModes.length - 1; } else { DDJ200.padModeIndex = (DDJ200.padModeIndex + 1) % (DDJ200.padModes.length - 1); @@ -148,24 +148,6 @@ DDJ200.init = function() { }; }, }); - - DDJ200.shiftButton = new components.Button({ - input: function(_channel, _control, value, status, _g) { - DDJ200.leftDeck.shiftPressed = value && (status === 0x90); - DDJ200.rightDeck.shiftPressed = value && (status === 0x91); - if (value) { - DDJ200.leftDeck.shift(); - DDJ200.rightDeck.shift(); - } else { - DDJ200.leftDeck.unshift(); - DDJ200.rightDeck.unshift(); - }; - DDJ200.leftDeck.reconnectComponents(); - DDJ200.rightDeck.reconnectComponents(); - }, - }); - - }; DDJ200.shutdown = function() { @@ -188,7 +170,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { inKey: "jog", jogCounter: 0, inputSeek: function(_channel, _control, value, _status, group) { - if (DDJ200.leftDeck.shiftPressed) { + if (DDJ200.leftDeck.shiftButton.pressed) { this.jogCounter += this.inValueScale(value); if (this.jogCounter > 9) { engine.setValue("[Library]", "MoveDown", true); @@ -210,6 +192,20 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }, }); + this.shiftButton = new components.Button({ + pressed: 0, + input: function(_channel, _control, value, _status, _g) { + this.pressed = value; + if (value) { + DDJ200.leftDeck.shift(); + DDJ200.rightDeck.shift(); + } else { + DDJ200.leftDeck.unshift(); + DDJ200.rightDeck.unshift(); + }; + }, + }); + this.syncButton = new components.Button({ midi: [0x8F + midiChannel, 0x58], key: "sync_enabled", @@ -294,14 +290,10 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { output: function(value, g, control) { this[`output${DDJ200.padModes[DDJ200.padModeIndex]}`](value, g, control); }, - midiNormal: [0x97 + (midiChannel - 1)*2, 0x00 + i], - midiShift: [0x98 + (midiChannel - 1)*2, 0x00 + i], - shift: function() { - this.midi = this.midiShift; - }, - unshift: function() { - this.midi = this.midiNormal; - }, + midi: [0x97 + (midiChannel - 1)*2, 0x00 + i], + sendShifted: true, + shiftChannel: 1, + shiftOffset: 1, outKey: this[`outKey${DDJ200.padModes[DDJ200.padModeIndex]}`], connect: function() { if (DDJ200.padModes[DDJ200.padModeIndex] !== "effect") { From d83e43b7c247ebb421d78e1e25741c83ca714507 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 24 Sep 2025 23:22:07 +0000 Subject: [PATCH 10/70] Pioneer DDJ-200: play and cue btn cleanup cleanup of play and cue btn implementation --- res/controllers/Pioneer-DDJ-200-scripts.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index de34f5ba13a9..8a3ce79a77dc 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -243,27 +243,31 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }); this.playButton = new components.PlayButton({ + midi: [0x8F + midiChannel, 0x0B], + sendShifted: true, + shiftControl: 1, + shiftOffset: 0x3C, outKey: "play_indicator", shift: function() { this.inKey = "reverse"; - this.midi = [0x8F + midiChannel, 0x47]; }, inputFaderStart: function(channel, control, value, status, _g) { this.inKey = "play"; this.input(channel, control, value, status, _g); - this.inKey = "reverse"; }, unshift: function() { this.inKey = "play"; - this.midi = [0x8F + midiChannel, 0x0B]; }, }); this.cueButton = new components.CueButton({ + midi: [0x8F + midiChannel, 0x0C], + sendShifted: true, + shiftControl: 1, + shiftOffset: 0x3C, outKey: "cue_indicator", shift: function() { this.inKey = "cue_gotoandstop"; - this.midi = [0x8F + midiChannel, 0x48]; }, inputFaderStop: function(channel, control, value, status, _g) { this.inKey = "cue_set"; @@ -273,7 +277,6 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }, unshift: function() { this.inKey = "cue_default"; - this.midi = [0x8F + midiChannel, 0x0C]; }, }); From f7f1a35fb51837a6273c88117edc8ef02df50cf7 Mon Sep 17 00:00:00 2001 From: rene Date: Thu, 25 Sep 2025 18:13:07 +0000 Subject: [PATCH 11/70] Pioneer DDJ-200: use components-js implementations use component-js implementations where possible --- res/controllers/Pioneer-DDJ-200-scripts.js | 25 ++++------------------ 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 8a3ce79a77dc..8818e40ee200 100644 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -209,18 +209,14 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { this.syncButton = new components.Button({ midi: [0x8F + midiChannel, 0x58], key: "sync_enabled", - input: function(_channel, _control, value, _status, _g) { + inputLongPress: function(_channel, _control, value, _status, _g) { if (value) { if (engine.getValue(this.group, "sync_enabled") === 0) { engine.setValue(this.group, "beatsync", 1); + engine.setValue(this.group, "sync_enabled", 1); } else { engine.setValue(this.group, "sync_enabled", 0); - }; - }; - }, - inputLongPress: function(_channel, _control, value, _status, _g) { - if (value) { - engine.setValue(this.group, "sync_enabled", 1); + } }; }, shiftedInput: function(_channel, _control, value, _status, _g) { @@ -247,17 +243,11 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { sendShifted: true, shiftControl: 1, shiftOffset: 0x3C, - outKey: "play_indicator", - shift: function() { - this.inKey = "reverse"; - }, inputFaderStart: function(channel, control, value, status, _g) { + // will trigger "reverse" if not handled separately this.inKey = "play"; this.input(channel, control, value, status, _g); }, - unshift: function() { - this.inKey = "play"; - }, }); this.cueButton = new components.CueButton({ @@ -265,19 +255,12 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { sendShifted: true, shiftControl: 1, shiftOffset: 0x3C, - outKey: "cue_indicator", - shift: function() { - this.inKey = "cue_gotoandstop"; - }, inputFaderStop: function(channel, control, value, status, _g) { this.inKey = "cue_set"; this.input(channel, control, value, status, _g); this.inKey = "cue_gotoandstop"; this.input(channel, control, value, status, _g); }, - unshift: function() { - this.inKey = "cue_default"; - }, }); this.pads = []; From 6d70155bfba20eb2064ee0190f1e939e6da31060 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 27 Sep 2025 22:02:13 +0000 Subject: [PATCH 12/70] Pioneer DDJ-200: rewrote to use componentContainers Now using componentConatiners similar to Numark NS6II implementation. --- res/controllers/Pioneer DDJ-200.midi.xml | 208 +++++--- res/controllers/Pioneer-DDJ-200-scripts.js | 588 ++++++++++++--------- 2 files changed, 465 insertions(+), 331 deletions(-) mode change 100644 => 100755 res/controllers/Pioneer DDJ-200.midi.xml mode change 100644 => 100755 res/controllers/Pioneer-DDJ-200-scripts.js diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml old mode 100644 new mode 100755 index d0900a107f4a..d476fd1e12ae --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -7,6 +7,48 @@ https://mixxx.discourse.group/t/new-mapping-for-pioneer-ddj-200/31164 pioneer_ddj_200 + + + + @@ -15,7 +57,7 @@ [Channel1] - DDJ200.shiftButton.input + DDJ200.Decks.left.shiftButton.input Deck 1: Shift pressed 0x90 0x3F @@ -25,7 +67,7 @@ [Channel2] - DDJ200.shiftButton.input + DDJ200.Decks.right.shiftButton.input Deck 2: Shift pressed 0x91 0x3F @@ -77,7 +119,7 @@ [Channel1] - DDJ200.leftDeck.pflButton.input + DDJ200.Decks.left.pflButton.input Deck 1: Headphone listen (pfl) button 0x90 0x54 @@ -87,7 +129,7 @@ [Channel1] - DDJ200.leftDeck.loadTrack.input + DDJ200.Decks.left.loadTrack.input Deck 1: Headphone (pfl) + shift 0x90 0x68 @@ -97,7 +139,7 @@ [Channel2] - DDJ200.rightDeck.pflButton.input + DDJ200.Decks.right.pflButton.input Deck 2: Headphone listen (pfl) button 0x91 0x54 @@ -107,7 +149,7 @@ [Channel2] - DDJ200.rightDeck.loadTrack.input + DDJ200.Decks.right.loadTrack.input Deck 2: Headphone (pfl) + shift 0x91 0x68 @@ -117,7 +159,7 @@ [Channel1] - DDJ200.leftDeck.syncButton.input + DDJ200.Decks.left.syncButton.input Deck 1: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x90 0x58 @@ -127,7 +169,7 @@ [Channel2] - DDJ200.rightDeck.syncButton.input + DDJ200.Decks.right.syncButton.input Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x91 0x58 @@ -137,7 +179,7 @@ [Channel1] - DDJ200.leftDeck.syncButton.inputLongPress + DDJ200.Decks.left.syncButton.inputLongPress Deck 1: Long Press to enable permanent sync 0x90 0x5C @@ -147,7 +189,7 @@ [Channel2] - DDJ200.rightDeck.syncButton.inputLongPress + DDJ200.Decks.right.syncButton.inputLongPress Deck 2: Long Press to enable permanent sync 0x91 0x5C @@ -157,7 +199,7 @@ [Channel1] - DDJ200.leftDeck.syncButton.shiftedInput + DDJ200.Decks.left.syncButton.shiftedInput Deck 1: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x90 0x60 @@ -167,7 +209,7 @@ [Channel2] - DDJ200.rightDeck.syncButton.shiftedInput + DDJ200.Decks.right.syncButton.shiftedInput Deck 2: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x91 0x60 @@ -177,7 +219,7 @@ [Channel1] - DDJ200.leftDeck.jogWheel.inputSeek + DDJ200.Decks.left.jogWheel.inputSeek Deck 1: Seek 0xB0 0x29 @@ -187,7 +229,7 @@ [Channel2] - DDJ200.rightDeck.jogWheel.inputSeek + DDJ200.Decks.right.jogWheel.inputSeek Deck 2: Seek 0xB1 0x29 @@ -207,7 +249,7 @@ [AutoDJ] - DDJ200.transFxButton.input + DDJ200.transFxButton.shiftedInput Change Pad mode 0x96 0x5A @@ -217,7 +259,7 @@ [Channel1] - DDJ200.leftDeck.jogWheel.inputTouch + DDJ200.Decks.left.jogWheel.inputTouch Deck 1: Touch 0x90 0x36 @@ -227,7 +269,7 @@ [Channel2] - DDJ200.rightDeck.jogWheel.inputTouch + DDJ200.Decks.right.jogWheel.inputTouch Deck 2: Touch 0x91 0x36 @@ -237,7 +279,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.leftDeck.eqKnob[0].input + DDJ200.Decks.left.eqKnob[0].input Deck 1: Adjust Low EQ 0xB0 0x0F @@ -247,7 +289,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.leftDeck.eqKnob[1].input + DDJ200.Decks.left.eqKnob[1].input Deck 1: Adjust Mid EQ 0xB0 0x0B @@ -257,7 +299,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.leftDeck.eqKnob[2].input + DDJ200.Decks.left.eqKnob[2].input Deck 1: Adjust High EQ 0xB0 0x07 @@ -267,7 +309,7 @@ [QuickEffectRack1_[Channel1]] - DDJ200.leftDeck.super1.input + DDJ200.Decks.left.super1.input Super Knob (msb): control linked effect 0xB6 0x17 @@ -277,7 +319,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.rightDeck.eqKnob[0].input + DDJ200.Decks.right.eqKnob[0].input Deck 2: Adjust Low EQ 0xB1 0x0F @@ -287,7 +329,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.rightDeck.eqKnob[1].input + DDJ200.Decks.right.eqKnob[1].input Deck 2: Adjust Mid EQ 0xB1 0x0B @@ -297,7 +339,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.rightDeck.eqKnob[2].input + DDJ200.Decks.right.eqKnob[2].input Deck 2: Adjust High EQ 0xB1 0x07 @@ -307,7 +349,7 @@ [QuickEffectRack1_[Channel2]] - DDJ200.rightDeck.super1.input + DDJ200.Decks.right.super1.input Quick Effect: Quick Effect Super Knob (control linked effect parameters) 0xB6 0x18 @@ -317,7 +359,7 @@ [Channel1] - DDJ200.leftDeck.volume.inputMSB + DDJ200.Decks.left.volume.inputMSB Deck 1: Volume Fader 0xB0 0x13 @@ -327,7 +369,7 @@ [Channel1] - DDJ200.leftDeck.volume.inputLSB + DDJ200.Decks.left.volume.inputLSB Deck 1: Volume Fader 0xB0 0x33 @@ -337,7 +379,7 @@ [Channel2] - DDJ200.rightDeck.volume.inputMSB + DDJ200.Decks.right.volume.inputMSB Deck 2: Volume Fader 0xB1 0x13 @@ -347,7 +389,7 @@ [Channel2] - DDJ200.rightDeck.volume.inputLSB + DDJ200.Decks.right.volume.inputLSB Deck 2: Volume Fader 0xB1 0x33 @@ -357,7 +399,7 @@ [Channel1] - DDJ200.leftDeck.playButton.input + DDJ200.Decks.left.playButton.input Deck 1: Play button 0x90 0x0B @@ -367,7 +409,7 @@ [Channel2] - DDJ200.rightDeck.playButton.input + DDJ200.Decks.right.playButton.input Deck 2: Play button 0x91 0x0B @@ -377,7 +419,7 @@ [Channel1] - DDJ200.leftDeck.playButton.inputFaderStart + DDJ200.Decks.left.playButton.inputFaderStart Deck 1: Shift and Fader start 0x90 0x66 @@ -387,7 +429,7 @@ [Channel2] - DDJ200.rightDeck.playButton.inputFaderStart + DDJ200.Decks.right.playButton.inputFaderStart Deck 2: Shift and Fader start 0x91 0x66 @@ -397,7 +439,7 @@ [Channel1] - DDJ200.leftDeck.cueButton.input + DDJ200.Decks.left.cueButton.input Deck 1: Cue button 0x90 0x0C @@ -407,7 +449,7 @@ [Channel2] - DDJ200.rightDeck.cueButton.input + DDJ200.Decks.right.cueButton.input Deck 2: Cue button 0x91 0x0C @@ -417,7 +459,7 @@ [Channel1] - DDJ200.leftDeck.cueButton.inputFaderStop + DDJ200.Decks.left.cueButton.inputFaderStop Deck 1: Shift and Fader stop 0x90 0x52 @@ -427,7 +469,7 @@ [Channel2] - DDJ200.rightDeck.cueButton.inputFaderStop + DDJ200.Decks.right.cueButton.inputFaderStop Deck 2: Shift and Fader stop 0x91 0x52 @@ -437,7 +479,7 @@ [Channel1] - DDJ200.leftDeck.cueButton.input + DDJ200.Decks.left.cueButton.input Deck 1: Go to cue point and stop 0x90 0x48 @@ -447,7 +489,7 @@ [Channel2] - DDJ200.rightDeck.cueButton.input + DDJ200.Decks.right.cueButton.input Deck 2: Go to cue point and stop 0x91 0x48 @@ -457,7 +499,7 @@ [Channel1] - DDJ200.leftDeck.rate.inputMSB + DDJ200.Decks.left.rate.inputMSB Deck 1: Playback speed control 0xB0 0x00 @@ -468,7 +510,7 @@ [Channel1] - DDJ200.leftDeck.rate.inputLSB + DDJ200.Decks.left.rate.inputLSB Deck 1: Playback speed control 0xB0 0x20 @@ -479,7 +521,7 @@ [Channel2] - DDJ200.rightDeck.rate.inputMSB + DDJ200.Decks.right.rate.inputMSB Deck 2: Playback speed control 0xB1 0x00 @@ -489,7 +531,7 @@ [Channel2] - DDJ200.rightDeck.rate.inputLSB + DDJ200.Decks.right.rate.inputLSB Deck 2: Playback speed control 0xB1 0x20 @@ -499,7 +541,7 @@ [Channel1] - DDJ200.leftDeck.jogWheel.inputWheel + DDJ200.Decks.left.jogWheel.inputWheel Deck 1: Jog 0xB0 0x21 @@ -509,7 +551,7 @@ [Channel2] - DDJ200.rightDeck.jogWheel.inputWheel + DDJ200.Decks.right.jogWheel.inputWheel Deck 2: Jog 0xB1 0x21 @@ -519,7 +561,7 @@ [Channel2] - DDJ200.rightDeck.jogWheel.inputWheel + DDJ200.Decks.right.jogWheel.inputWheel Deck 2: Scratch 0xB1 0x22 @@ -529,7 +571,7 @@ [Channel1] - DDJ200.leftDeck.jogWheel.inputWheel + DDJ200.Decks.left.jogWheel.inputWheel Deck 1: Scratch 0xB0 0x22 @@ -539,7 +581,7 @@ [Channel2] - DDJ200.rightDeck.jogWheel.inputWheel + DDJ200.Decks.right.jogWheel.inputWheel Deck 2: Scratch 0xB1 0x23 @@ -549,7 +591,7 @@ [Channel1] - DDJ200.leftDeck.jogWheel.inputWheel + DDJ200.Decks.left.jogWheel.inputWheel Deck 1: Scratch 0xB0 0x23 @@ -559,7 +601,7 @@ [Channel1] - DDJ200.leftDeck.playButton.input + DDJ200.Decks.left.playButton.input Deck 1: Shift Play 0x90 0x47 @@ -569,7 +611,7 @@ [Channel2] - DDJ200.rightDeck.playButton.input + DDJ200.Decks.right.playButton.input Deck 2: Shift Play 0x91 0x47 @@ -580,7 +622,7 @@ [Channel1] - DDJ200.leftDeck.pads[0].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 1: Set, preview, jump to 0x97 0x00 @@ -590,7 +632,7 @@ [Channel1] - DDJ200.leftDeck.pads[1].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 1: Set, preview, jump to 0x97 0x01 @@ -600,7 +642,7 @@ [Channel1] - DDJ200.leftDeck.pads[2].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 1: Set, preview, jump to 0x97 0x02 @@ -610,7 +652,7 @@ [Channel1] - DDJ200.leftDeck.pads[3].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 1: Set, preview, jump to 0x97 0x03 @@ -620,7 +662,7 @@ [Channel1] - DDJ200.leftDeck.pads[4].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 1: Set, preview, jump to 0x97 0x04 @@ -630,7 +672,7 @@ [Channel1] - DDJ200.leftDeck.pads[5].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 1: Set, preview, jump to 0x97 0x05 @@ -640,7 +682,7 @@ [Channel1] - DDJ200.leftDeck.pads[6].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 1: Set, preview, jump to 0x97 0x06 @@ -650,7 +692,7 @@ [Channel1] - DDJ200.leftDeck.pads[7].input + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 1: Set, preview, jump to 0x97 0x07 @@ -660,7 +702,7 @@ [Channel2] - DDJ200.rightDeck.pads[0].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 2: Set, preview, jump to 0x99 0x00 @@ -670,7 +712,7 @@ [Channel2] - DDJ200.rightDeck.pads[1].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 2: Set, preview, jump to 0x99 0x01 @@ -680,7 +722,7 @@ [Channel2] - DDJ200.rightDeck.pads[2].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 2: Set, preview, jump to 0x99 0x02 @@ -690,7 +732,7 @@ [Channel2] - DDJ200.rightDeck.pads[3].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 2: Set, preview, jump to 0x99 0x03 @@ -700,7 +742,7 @@ [Channel2] - DDJ200.rightDeck.pads[4].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 2: Set, preview, jump to 0x99 0x04 @@ -710,7 +752,7 @@ [Channel2] - DDJ200.rightDeck.pads[5].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 2: Set, preview, jump to 0x99 0x05 @@ -720,7 +762,7 @@ [Channel2] - DDJ200.rightDeck.pads[6].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 2: Set, preview, jump to 0x99 0x06 @@ -730,7 +772,7 @@ [Channel2] - DDJ200.rightDeck.pads[7].input + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 2: Set, preview, jump to 0x99 0x07 @@ -740,7 +782,7 @@ [Channel1] - DDJ200.leftDeck.pads[0].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 1: Clear 0x98 0x00 @@ -750,7 +792,7 @@ [Channel1] - DDJ200.leftDeck.pads[1].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 1: Clear 0x98 0x01 @@ -760,7 +802,7 @@ [Channel1] - DDJ200.leftDeck.pads[2].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 1: Clear 0x98 0x02 @@ -770,7 +812,7 @@ [Channel1] - DDJ200.leftDeck.pads[3].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 1: Clear 0x98 0x03 @@ -780,7 +822,7 @@ [Channel1] - DDJ200.leftDeck.pads[4].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 1: Clear 0x98 0x04 @@ -790,7 +832,7 @@ [Channel1] - DDJ200.leftDeck.pads[5].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 1: Clear 0x98 0x05 @@ -800,7 +842,7 @@ [Channel1] - DDJ200.leftDeck.pads[6].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 1: Clear 0x98 0x06 @@ -810,7 +852,7 @@ [Channel1] - DDJ200.leftDeck.pads[7].shiftedInput + DDJ200.Decks.left.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 1: Clear 0x98 0x07 @@ -820,7 +862,7 @@ [Channel2] - DDJ200.rightDeck.pads[0].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 2: Clear 0x9A 0x00 @@ -830,7 +872,7 @@ [Channel2] - DDJ200.rightDeck.pads[1].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 2: Clear 0x9A 0x01 @@ -840,7 +882,7 @@ [Channel2] - DDJ200.rightDeck.pads[2].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 2: Clear 0x9A 0x02 @@ -850,7 +892,7 @@ [Channel2] - DDJ200.rightDeck.pads[3].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 2: Clear 0x9A 0x03 @@ -860,7 +902,7 @@ [Channel2] - DDJ200.rightDeck.pads[4].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 2: Clear 0x9A 0x04 @@ -870,7 +912,7 @@ [Channel2] - DDJ200.rightDeck.pads[5].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 2: Clear 0x9A 0x05 @@ -880,7 +922,7 @@ [Channel2] - DDJ200.rightDeck.pads[6].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 2: Clear 0x9A 0x06 @@ -890,7 +932,7 @@ [Channel2] - DDJ200.rightDeck.pads[7].shiftedInput + DDJ200.Decks.right.padUnit.choosenPadInstance.pads[7].input 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 old mode 100644 new mode 100755 index 2ad230656e53..896304686e3b --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -45,150 +45,371 @@ Deck n = 0/1: Midi in Midi out PAD 8 press 9p 07 hh [midi in] OFF=0x00, ON=0x7F */ +/* + Disabling Demo Mode according to the user manual: + 1 - Disconnect the USB cable / power supply + 2 - Hold both the [SHIFT] and [PLAY/PAUSE] buttons and connect USB cable / power supply + 3 - Use performance pads to change the settings + Pad 1 - Demo mode is switched off + Pad 2 - Demo mode starts when you don’t use the unit for 1 minute + Pad 3 - Demo mode starts when you don’t use the unit for 5 minutes + Pad 4 - Demo mode starts when you don’t use the unit for 10 minutes + While saving bottom row of Performance Pads is flashing. Wait till it stops. + 4 - Disconnect the USB cable / power supply +*/ + // eslint-disable-next-line no-var var DDJ200 = { }; -DDJ200.padModes = ["Hotcue", "Loop", "Effect", "Jump"]; -DDJ200.padModeIndex = 0; +components.Component.prototype.shiftOffset = 1; +components.Component.prototype.shiftChannel = true; +components.Component.prototype.sendShifted = true; -DDJ200.init = function() { - DDJ200.leftDeck = new DDJ200.Deck([1, 3], 1); - DDJ200.rightDeck = new DDJ200.Deck([2, 4], 2); +DDJ200.PadMode = function(options) { + components.ComponentContainer.call(this, options); - // start with focus on library for selecting tracks (delay seems required) - engine.beginTimer(500, function() { - engine.setValue("[Library]", "MoveFocus", 1); - }, true); + this.constructPads = constructPad => { + this.pads = this.pads.map((_, padIndex) => constructPad(padIndex)); + }; + // this is a workaround for components, forEachComponent only iterates + // over ownProperties, so these have to constructed by the constructor here + // instead of being merged by the ComponentContainer constructor + this.pads = Array(8).fill(undefined); +}; +DDJ200.PadMode.prototype = new components.ComponentContainer(); + +DDJ200.Pad = function(pos, deckOffset, options) { + options.midi = [0x97 + deckOffset, pos]; + options.number = pos + 1; + components.HotcueButton.call(this, options); +}; +DDJ200.Pad.prototype = new components.HotcueButton({}); +DDJ200.PadModeContainers = {}; - // query the controller for current control positions on startup - midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); +DDJ200.PadModeContainers.Hotcue = function(deckOffset) { + DDJ200.PadMode.call(this); + + this.constructPads(i => + new DDJ200.Pad(i, deckOffset, { }) + ); +}; +DDJ200.PadModeContainers.Hotcue.prototype = new DDJ200.PadMode({ + indicatorStyle: 0x00, +}); + +DDJ200.PadModeContainers.Loop = function(deckOffset) { + DDJ200.PadMode.call(this); + + const theContainer = this; + this.currentBaseLoopSize = parseInt(engine.getSetting("defaultLoopRootSize")); + + this.constructPads(i => + new DDJ200.Pad(i, deckOffset, { + unshift: function() { + this.inKey = "beatloop_activate"; + }, + shift: function() { + this.inKey = "beatlooproll_activate"; + }, + loopSize: Math.pow(2, theContainer.currentBaseLoopSize + i), + input: function(channel, _control, value, _status, _mode) { + if (value) { + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); + engine.setValue(this.group, "beatloop_size", this.loopSize); // this should trigger output and switch all buttons off + if (matchingLoopSize || !loopEnabled) { + engine.setValue(this.group, this.inKey, true); + }; + } else { + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + this.send(loopEnabled?0x7F:0x00); + }; + }, + outKey: "beatloop_size", + outValueScale: function(value) { + if (value) { + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); + return matchingLoopSize?loopEnabled*0x7F:0x00; + } + return 0x00; + }, + }) + ); +}; +DDJ200.PadModeContainers.Loop.prototype = new DDJ200.PadMode({ + indicatorStyle: 0x7F, +}); + +DDJ200.PadModeContainers.Effect = function(deckOffset) { + DDJ200.PadMode.call(this); + + this.constructPads(i => { + if (i < 4) { + return new components.SamplerButton({ + midi: [0x97 + deckOffset, i], + number: deckOffset * 2 + i + 1, + }); + } else if (i < 7) { + return new DDJ200.Pad(i, deckOffset, { + midi: [0x97 + deckOffset, i], + effect: `[EffectRack1_EffectUnit${ deckOffset / 2 + 1 }_Effect${ i - 3 }]`, + input: function(_channel, _control, value, _status, _g) { + engine.setValue(this.effect, "enabled", value); + this.send(this.outValueScale(value)); + }, + outValueScale: function(_value) { + return engine.getValue(this.effect, "loaded")?0x7F:0x00; + } + }); + } else { + return new components.Button({ + midi: [0x97 + deckOffset, i], + input: function(_channel, _control, value, _status, _g) { + if (value) { + bpm.tapButton(script.deckFromGroup(this.group)); + }; + this.send(this.outValueScale(value)); + }, + trigger: function(_value) { + this.send(0x00); + }, + }); + }; + }); +}; +DDJ200.PadModeContainers.Effect.prototype = new DDJ200.PadMode({ + indicatorStyle: "indicator_500ms", +}); + +DDJ200.PadModeContainers.Jump = function(deckOffset) { + DDJ200.PadMode.call(this); + + const theContainer = this; + this.currentBaseBeatJumpSize = parseInt(engine.getSetting("defaultBeatJumpRootSize")); - DDJ200.headMixButton = new components.Button({ + this.constructPads(i => + new components.Button({ + midi: [0x97 + deckOffset, i], + unshift: function() { + this.inKey = "beatjump_forward"; + }, + shift: function() { + this.inKey = "beatjump_backward"; + }, + beatJumpSize: Math.pow(2, theContainer.currentBaseBeatJumpSize + i), + input: function(channel, control, value, _status, _g) { + if (value) { + engine.setValue(this.group, "beatjump_size", this.beatJumpSize); + engine.setValue(this.group, this.inKey, true); + }; + this.send(this.outValueScale(value)); + }, + trigger: function(_value) { + this.send(0x00); + } + }) + ); +}; +DDJ200.PadModeContainers.Jump.prototype = new DDJ200.PadMode({ + indicatorStyle: "indicator_250ms", +}); + +DDJ200.DoubleRingBuffer = class { + constructor(indexableUnshifted, indexableShifted) { + this.indexableUnshifted = indexableUnshifted; + this.indexableShifted = indexableShifted; + this.indexable = this.indexableUnshifted; + this.index = 0; + this.isShifted = false; + }; + shift() { + this.indexable = this.indexableShifted; + this.index = 0; + this.isShifted = true; + }; + unshift() { + this.indexable = this.indexableUnshifted; + this.index = 0; + this.isShifted = false; + }; + current() { + return this.indexable[this.index]; + }; + next() { + this.index = script.posMod(this.index + 1, this.indexable.length); + return this.current(); + }; +}; + +DDJ200.PadModeContainers.ModeSelector = function(group) { + const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); + + const updateSelectorLeds = () => { + this.forEachComponent(c => c.trigger()); + }; + + const setPads = newPadInstance => { + if (newPadInstance === this.choosenPadInstance) { + return; + } + + this.choosenPadInstance.forEachComponent(function(component) { + component.disconnect(); + }); + this.choosenPadInstance = newPadInstance; + updateSelectorLeds(); + this.choosenPadInstance.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = group; + } + }); + }; + + this.input = () => { + if (this.padInstancesBuffer.isShifted) { + this.padInstancesBuffer.unshift(); + setPads(this.padInstancesBuffer.current()); + } else { + setPads(this.padInstancesBuffer.next()); + } + }; + + this.shiftedInput = () => { + if (!this.padInstancesBuffer.isShifted) { + this.padInstancesBuffer.shift(); + setPads(this.padInstancesBuffer.current()); + } else { + setPads(this.padInstancesBuffer.next()); + } + }; + + this.startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); + this.loopInstance = new DDJ200.PadModeContainers.Loop(deckOffset); + this.effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset); + this.jumpInstance = new DDJ200.PadModeContainers.Jump(deckOffset); + + this.padInstancesBuffer = new DDJ200.DoubleRingBuffer( + [this.startupModeInstance, this.loopInstance, this.effectInstance], + [this.jumpInstance] + ); + + this.choosenPadInstance = new DDJ200.PadMode(); + setPads(this.startupModeInstance); +}; +DDJ200.PadModeContainers.ModeSelector.prototype = new components.ComponentContainer(); + +DDJ200.init = function() { + this.Decks = { + left: new DDJ200.Deck([1, 3], 1), + right: new DDJ200.Deck([2, 4], 2), + }; + + this.headMixButton = new components.Button({ midi: [0x96, 0x63], key: "headMix", type: components.Button.prototype.types.toggle, input: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed + if (value) { const masterMixEnabled = (engine.getValue("[Master]", "headMix") >= 0); engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 0); this.send(masterMixEnabled?0:0x7F); // set LED }; }, shiftedInput: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed + if (value) { engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); if (!engine.getValue("[Skin]", "show_4decks")) { - DDJ200.leftDeck.setCurrentDeck("[Channel1]"); - DDJ200.rightDeck.setCurrentDeck("[Channel2]"); - if (DDJ200.leftDeck.syncButton.blinkConnection) { - DDJ200.leftDeck.syncButton.blinkConnection.disconnect(); - }; - if (DDJ200.rightDeck.syncButton.blinkConnection) { - DDJ200.rightDeck.syncButton.blinkConnection.disconnect(); - }; + DDJ200.Decks.left.setCurrentDeck("[Channel1]"); + DDJ200.Decks.right.setCurrentDeck("[Channel2]"); + Object.values(DDJ200.Decks).forEach(deck => { + if (deck.syncButton.blinkConnection) { + deck.syncButton.blinkConnection.disconnect(); + }; + }); }; }; }, }); - DDJ200.transFxButton = new components.Button({ - blinkConnection: undefined, + this.transFxButton = new components.Button({ + midi: [0x96, 0x59], + shiftChannel: false, + shiftControl: true, + shiftOffset: 1, + input: function(_channel, _control, value, _status, _g) { - if (value) { // only if button pressed - if (DDJ200.padModeIndex === (DDJ200.padModes.length - 1)) { - DDJ200.padModeIndex = 0; - } else { - if (DDJ200.leftDeck.shiftPressed || DDJ200.rightDeck.shiftPressed) { - DDJ200.padModeIndex = DDJ200.padModes.length - 1; - } else { - DDJ200.padModeIndex = (DDJ200.padModeIndex + 1) % (DDJ200.padModes.length - 1); - }; - }; - DDJ200.leftDeck.pads.forEach(function(e) { - e.updateOutKey(); - }); - DDJ200.rightDeck.pads.forEach(function(e) { - e.updateOutKey(); + if (value) { + Object.values(DDJ200.Decks).forEach(deck => { + deck.padUnit.input(); }); - this.output(); + this.output(value); }; }, - output: function(_value, _g, _control) { - if (this.blinkConnection) { - this.blinkConnection.disconnect(); - this.blinkConnection = undefined; - }; - switch (DDJ200.padModes[DDJ200.padModeIndex]) { - case "Hotcue": - midi.sendShortMsg(0x96, 0x59, 0x00); - midi.sendShortMsg(0x96, 0x5A, 0x00); - break; - case "Loop": - midi.sendShortMsg(0x96, 0x59, 0x7F); - midi.sendShortMsg(0x96, 0x5A, 0x7F); - break; - case "Effect": - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - midi.sendShortMsg(0x96, 0x59, 0x7F * value); - midi.sendShortMsg(0x96, 0x5A, 0x7F * value); - }); - break; - case "Jump": - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - midi.sendShortMsg(0x96, 0x59, 0x7F * value); - midi.sendShortMsg(0x96, 0x5A, 0x7F * value); - for (let midiChannel = 0; midiChannel < 4; midiChannel++) { - for (let i = 0; i < 8; i++) { - midi.sendShortMsg(0x97 + midiChannel, i, 0x7F * value); - }; - }; + shiftedInput: function(_channel, _control, value, _status, _g) { + if (value) { + Object.values(DDJ200.Decks).forEach(deck => { + deck.padUnit.shiftedInput(); }); - break; + this.output(value); }; }, - }); - - DDJ200.shiftButton = new components.Button({ - input: function(_channel, _control, value, status, _g) { - DDJ200.leftDeck.shiftPressed = value && (status === 0x90); - DDJ200.rightDeck.shiftPressed = value && (status === 0x91); - if (value) { - DDJ200.leftDeck.shift(); - DDJ200.rightDeck.shift(); + blinkConnection: undefined, + output: function(active) { + if (!active) { + this.send(0x00); } else { - DDJ200.leftDeck.unshift(); - DDJ200.rightDeck.unshift(); + if (this.blinkConnection) { + this.blinkConnection.disconnect(); + }; + // use left Deck as reference for current padInstance + const indicatorValue = DDJ200.Decks.left.padUnit.choosenPadInstance.indicatorStyle; + if (indicatorValue === "indicator_250ms" || indicatorValue === "indicator_500ms") { + this.blinkConnection = engine.makeConnection("[App]", indicatorValue, function(value, _group, _control) { + DDJ200.transFxButton.send(0x7F * value); + }); + } else { + this.send(indicatorValue); + }; }; - DDJ200.leftDeck.reconnectComponents(); - DDJ200.rightDeck.reconnectComponents(); }, }); + this.shutdown = function() { + DDJ200.headMixButton.shutdown(); + DDJ200.transFxButton.shutdown(); + Object.values(DDJ200.Decks).forEach(deck => { + deck.shutdown(); + }); + engine.setValue("[Channel3]", "volume", 0); + engine.setValue("[Channel4]", "volume", 0); + }; + this.shutdown(); -}; + // query the controller for current control positions on startup + midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); + // start with focus on library for selecting tracks (delay seems required) -DDJ200.shutdown = function() { - DDJ200.leftDeck.shutdown(); - DDJ200.rightDeck.shutdown(); + engine.beginTimer(500, function() { + engine.setValue("[Library]", "MoveFocus", 1); + }, true); }; DDJ200.Deck = function(deckNumbers, midiChannel) { components.Deck.call(this, deckNumbers); const theDeck = this; + this.padUnit = new DDJ200.PadModeContainers.ModeSelector(this.currentDeck); this.jogWheel = new components.JogWheelBasic({ - wheelResolution: 128, // how many ticks per revolution the jogwheel has - alpha: 1/8, // alpha-filter - beta: 1/8/32, - rpm: 33 + 1/3, + wheelResolution: 128, // how many ticks per revolution the jogwheel has + alpha: 1/8, // alpha-filter inValueScale: function(value) { return value - 64; }, - inKey: "jog", jogCounter: 0, inputSeek: function(_channel, _control, value, _status, group) { - if (DDJ200.leftDeck.shiftPressed) { + if (DDJ200.Decks.left.shiftButton.pressed) { this.jogCounter += this.inValueScale(value); if (this.jogCounter > 9) { engine.setValue("[Library]", "MoveDown", true); @@ -210,9 +431,26 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }, }); + this.shiftButton = new components.Button({ + pressed: 0, + input: function(_channel, _control, value, _status, _g) { + this.pressed = value; + Object.values(DDJ200.Decks).forEach(deck => { + if (value) { + deck.shift(); + } else { + deck.unshift(); + }; + }); + }, + }); + this.syncButton = new components.Button({ midi: [0x8F + midiChannel, 0x58], key: "sync_enabled", + shiftChannel: false, + shiftControl: true, + shiftOffset: 8, input: function(_channel, _control, value, _status, _g) { if (value) { if (engine.getValue(this.group, "sync_enabled") === 0) { @@ -233,7 +471,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { theDeck.toggle(); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - midi.sendShortMsg(0x8F + midiChannel, 0x58, 0x7F * value); + theDeck.syncButton.send(0x7F * value); }); } else if (this.blinkConnection) { this.blinkConnection.disconnect(); @@ -247,27 +485,31 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }); this.playButton = new components.PlayButton({ + midi: [0x8F + midiChannel, 0x0B], + shiftChannel: false, + shiftControl: true, + shiftOffset: 0x3C, outKey: "play_indicator", shift: function() { this.inKey = "reverse"; - this.midi = [0x8F + midiChannel, 0x47]; }, inputFaderStart: function(channel, control, value, status, _g) { this.inKey = "play"; this.input(channel, control, value, status, _g); - this.inKey = "reverse"; }, unshift: function() { this.inKey = "play"; - this.midi = [0x8F + midiChannel, 0x0B]; }, }); this.cueButton = new components.CueButton({ + midi: [0x8F + midiChannel, 0x0C], + shiftChannel: false, + shiftControl: true, + shiftOffset: 0x3C, outKey: "cue_indicator", shift: function() { this.inKey = "cue_gotoandstop"; - this.midi = [0x8F + midiChannel, 0x48]; }, inputFaderStop: function(channel, control, value, status, _g) { this.inKey = "cue_set"; @@ -277,159 +519,9 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }, unshift: function() { this.inKey = "cue_default"; - this.midi = [0x8F + midiChannel, 0x0C]; }, }); - this.pads = []; - for (let i = 0; i < 8; i++) { - this.pads[i] = new components.HotcueButton({ - number: i + 1, - input: function(channel, control, value, status, g) { - this[`input${DDJ200.padModes[DDJ200.padModeIndex]}`](channel, control, value, status, g); - }, - shiftedInput: function(channel, control, value, status, g) { - this[`inputShift${DDJ200.padModes[DDJ200.padModeIndex]}`](channel, control, value, status, g); - }, - output: function(value, g, control) { - this[`output${DDJ200.padModes[DDJ200.padModeIndex]}`](value, g, control); - }, - midiNormal: [0x97 + (midiChannel - 1)*2, 0x00 + i], - midiShift: [0x98 + (midiChannel - 1)*2, 0x00 + i], - shift: function() { - this.midi = this.midiShift; - }, - unshift: function() { - this.midi = this.midiNormal; - }, - outKey: this[`outKey${DDJ200.padModes[DDJ200.padModeIndex]}`], - connect: function() { - if (DDJ200.padModes[DDJ200.padModeIndex] !== "effect") { - components.HotcueButton.prototype.connect.call(this); - } else { - this.outKeyEffectConnect(); - }; - }, - updateOutKey: function() { - this.disconnect(); - this.outKey = this[`outKey${ DDJ200.padModes[DDJ200.padModeIndex]}`]; - this.connect(); - this.trigger(); - }, - - /* ----------- PADs in Hotcue Mode ----------- */ - inputHotcue: function(_channel, _control, value, _status, _g) { - engine.setValue(this.group, `hotcue_${this.number}_activate`, value); - }, - inputShiftHotcue: function(_channel, _control, value, _status, _g) { - if (value) { - engine.setValue(this.group, `hotcue_${this.number}_clear`, value); - }; - }, - outKeyHotcue: `hotcue_${i + 1}_status`, - outputHotcue: function(value, _g, _control) { - this.send(this.outValueScale(value)); - }, - - /* ----------- PADs in Loop Mode ----------- */ - _inputLoop: function(channel, _control, value, _status, mode) { - if (value) { // only if button pressed - const loopSize = (Math.pow(2, this.number) * 0.25); - const loopEnabled = engine.getValue(this.group, "loop_enabled"); - const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === loopSize); - engine.setValue(this.group, "beatloop_size", loopSize); - for (let j = 0; j <= 8; j++) { - midi.sendShortMsg(0x90 + channel, j, 0x00); // hotcue - }; - this.send(this.outValueScale(value)); - if (matchingLoopSize || !loopEnabled) { - engine.setValue(this.group, mode, true); - }; - }; - }, - inputLoop: function(channel, control, value, status, _g) { - const thisDeck = (channel === 7)?DDJ200.leftDeck.currentDeck:DDJ200.rightDeck.currentDeck; - if (!engine.getValue(thisDeck, "track_loaded")) { return; } - this._inputLoop(channel, control, value, status, "beatloop_activate"); - }, - inputShiftLoop: function(channel, control, value, status, _g) { - const thisDeck = (channel === 8)?DDJ200.leftDeck.currentDeck:DDJ200.rightDeck.currentDeck; - if (!engine.getValue(thisDeck, "track_loaded")) { return; } - this._inputLoop(channel, control, value, status, "beatlooproll_activate"); - }, - outKeyLoop: "loop_enabled", - outputLoop: function(value, _g, _control) { - const loopSize = (Math.pow(2, this.number) * 0.25); - const loopEnabled = engine.getValue(this.group, "loop_enabled"); - const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === loopSize); - value = matchingLoopSize?loopEnabled:0; - this.send(this.outValueScale(value)); - }, - - /* ----------- PADs in Effect Mode ----------- */ - inputEffect: function(_channel, control, value, _status, _g) { - if (control < 4) { - const sampler = `[Sampler${control + 1 +(this.deckFromGroup(this.group)-1)*4}]`; - if (engine.getValue(sampler, "play")) { - engine.setValue(sampler, "stop", value); - } else { - engine.setValue(sampler, "cue_gotoandplay", value); - }; - } else if (control < 7) { - const effect = `[EffectRack1_EffectUnit${this.deckFromGroup(this.group)}_Effect${control - 3}]`; - engine.setValue(effect, "enabled", value); - } else { - if (value) { - bpm.tapButton(this.deckFromGroup(this.group)); - }; - this.send(this.outValueScale(value)); - }; - }, - inputShiftEffect: function(channel, control, value, status, _g) { - this.inputEffect(channel, control, value, status, _g); - }, - deckFromGroup: function(group) { - const deckGroup = script.deckFromGroup(group); - return (((deckGroup - 1) % 2) + 1); - }, - outKeyEffectConnect: function() { - const control = this.number - 1; - if (control < 4) { - const sampler = `[Sampler${control + 1 + (this.deckFromGroup(this.group)-1) * 4}]`; - this.connections[0] = engine.makeConnection(sampler, "play", this.output.bind(this)); - } else if (control < 7) { - const effect = `[EffectRack1_EffectUnit${this.deckFromGroup(this.group)}_Effect${control - 3}]`; - this.connections[0] = engine.makeConnection(effect, "enabled", this.output.bind(this)); - } else { - this.connections[0] = undefined; - }; - }, - outKeyEffect: undefined, - outputEffect: function(value, _g, _control) { - this.send(this.outValueScale(value)); - }, - - /* ----------- PADs in BeatJump Mode ----------- */ - inputJump: function(_channel, control, value, _status, _g) { - if (value) { // only if button pressed - engine.setValue(this.group, "beatjump_size", Math.pow(2, control+2)); - engine.setValue(this.group, "beatjump_forward", true); - }; - }, - inputShiftJump: function(_channel, control, value, _status, _g) { - if (value) { // only if button pressed - engine.setValue(this.group, "beatjump_size", Math.pow(2, control+2)); - engine.setValue(this.group, "beatjump_backward", true); - }; - }, - outKeyJump: `hotcue_${i + 1}_status`, - outputJump: function(_value, _g, _control) { - this.send(this.outValueScale(0)); - }, - }); - }; - this.pads.forEach(function(e) { e.updateOutKey(); }); - this.pflButton = new components.Button({ midi: [0x8F + midiChannel, 0x54], key: "pfl", From 63122528a53b1e781660fc2fac271d3fcb1c3d32 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 27 Sep 2025 22:12:54 +0000 Subject: [PATCH 13/70] Pioneer DDJ-200: use all 4 effectunits change effectunit when changing the Decks --- res/controllers/Pioneer-DDJ-200-scripts.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 896304686e3b..d2cb388edf6b 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -154,13 +154,14 @@ DDJ200.PadModeContainers.Effect = function(deckOffset) { } else if (i < 7) { return new DDJ200.Pad(i, deckOffset, { midi: [0x97 + deckOffset, i], - effect: `[EffectRack1_EffectUnit${ deckOffset / 2 + 1 }_Effect${ i - 3 }]`, input: function(_channel, _control, value, _status, _g) { - engine.setValue(this.effect, "enabled", value); + const effect = `[EffectRack1_EffectUnit${ script.deckFromGroup(this.group) }_Effect${ i - 3 }]`; + engine.setValue(effect, "enabled", value); this.send(this.outValueScale(value)); }, outValueScale: function(_value) { - return engine.getValue(this.effect, "loaded")?0x7F:0x00; + const effect = `[EffectRack1_EffectUnit${ script.deckFromGroup(this.group) }_Effect${ i - 3 }]`; + return engine.getValue(effect, "loaded")?0x7F:0x00; } }); } else { From 3fb79b81914776b666008af8e4c285f72edd1dc8 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 27 Sep 2025 22:43:10 +0000 Subject: [PATCH 14/70] Pioneer DDJ-200: fix for jogWheel was broken with last commit, fixed --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index d2cb388edf6b..0d64308b30c9 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -405,9 +405,12 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { this.jogWheel = new components.JogWheelBasic({ wheelResolution: 128, // how many ticks per revolution the jogwheel has alpha: 1/8, // alpha-filter + beta: 1/8/32, + rpm: 33 + 1/3, inValueScale: function(value) { return value - 64; }, + inKey: "jog", jogCounter: 0, inputSeek: function(_channel, _control, value, _status, group) { if (DDJ200.Decks.left.shiftButton.pressed) { From c0b564387e5bc54b7d536bb12b496d2d803e0fb9 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 17:14:42 +0000 Subject: [PATCH 15/70] Pioneer DDJ-200: final cleanup of play and cue buttons --- res/controllers/Pioneer-DDJ-200-scripts.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 0d64308b30c9..c2e9ef1c8c7e 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -493,17 +493,10 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { shiftChannel: false, shiftControl: true, shiftOffset: 0x3C, - outKey: "play_indicator", - shift: function() { - this.inKey = "reverse"; - }, inputFaderStart: function(channel, control, value, status, _g) { this.inKey = "play"; this.input(channel, control, value, status, _g); }, - unshift: function() { - this.inKey = "play"; - }, }); this.cueButton = new components.CueButton({ @@ -512,18 +505,12 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { shiftControl: true, shiftOffset: 0x3C, outKey: "cue_indicator", - shift: function() { - this.inKey = "cue_gotoandstop"; - }, inputFaderStop: function(channel, control, value, status, _g) { this.inKey = "cue_set"; this.input(channel, control, value, status, _g); this.inKey = "cue_gotoandstop"; this.input(channel, control, value, status, _g); }, - unshift: function() { - this.inKey = "cue_default"; - }, }); this.pflButton = new components.Button({ From 21ef65b1c3949c7f5eee11b1c8c786f6b41ed1ce Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 17:37:32 +0000 Subject: [PATCH 16/70] Pioneer DDJ-200: cleanup TransFXButton and RingBuffer Simplified handling of Pad-Mode switching and Buffer --- res/controllers/Pioneer-DDJ-200-scripts.js | 82 +++++++--------------- 1 file changed, 27 insertions(+), 55 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index c2e9ef1c8c7e..eac938526b37 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -219,28 +219,19 @@ DDJ200.PadModeContainers.Jump.prototype = new DDJ200.PadMode({ DDJ200.DoubleRingBuffer = class { constructor(indexableUnshifted, indexableShifted) { - this.indexableUnshifted = indexableUnshifted; - this.indexableShifted = indexableShifted; - this.indexable = this.indexableUnshifted; + this.indexable = [indexableUnshifted, indexableShifted]; this.index = 0; this.isShifted = false; }; - shift() { - this.indexable = this.indexableShifted; + swapIndexable() { + this.isShifted = !this.isShifted; this.index = 0; - this.isShifted = true; - }; - unshift() { - this.indexable = this.indexableUnshifted; - this.index = 0; - this.isShifted = false; - }; + } current() { - return this.indexable[this.index]; + return this.indexable[this.isShifted?1:0][this.index]; }; next() { - this.index = script.posMod(this.index + 1, this.indexable.length); - return this.current(); + this.index = script.posMod(this.index + 1, this.indexable[this.isShifted?1:0].length); }; }; @@ -268,22 +259,13 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { }); }; - this.input = () => { - if (this.padInstancesBuffer.isShifted) { - this.padInstancesBuffer.unshift(); - setPads(this.padInstancesBuffer.current()); - } else { - setPads(this.padInstancesBuffer.next()); - } - }; - - this.shiftedInput = () => { - if (!this.padInstancesBuffer.isShifted) { - this.padInstancesBuffer.shift(); - setPads(this.padInstancesBuffer.current()); + this.input = (isShifted) => { + if (isShifted !== this.padInstancesBuffer.isShifted) { + this.padInstancesBuffer.swapIndexable(); } else { - setPads(this.padInstancesBuffer.next()); - } + this.padInstancesBuffer.next(); + }; + setPads(this.padInstancesBuffer.current()); }; this.startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); @@ -340,39 +322,29 @@ DDJ200.init = function() { shiftControl: true, shiftOffset: 1, - input: function(_channel, _control, value, _status, _g) { + input: function(_channel, control, value, _status, _g) { if (value) { Object.values(DDJ200.Decks).forEach(deck => { - deck.padUnit.input(); + deck.padUnit.input((control === 0x5A)); }); - this.output(value); + this.indicatePadMode(); }; }, - shiftedInput: function(_channel, _control, value, _status, _g) { - if (value) { - Object.values(DDJ200.Decks).forEach(deck => { - deck.padUnit.shiftedInput(); - }); - this.output(value); - }; + indicatorStyle: function() { + // use left Deck as reference for selected padInstance + return DDJ200.Decks.left.padUnit.choosenPadInstance.indicatorStyle; }, blinkConnection: undefined, - output: function(active) { - if (!active) { - this.send(0x00); + indicatePadMode: function() { + if (this.blinkConnection) { + this.blinkConnection.disconnect(); + }; + if (this.indicatorStyle() === "indicator_250ms" || this.indicatorStyle() === "indicator_500ms") { + this.blinkConnection = engine.makeConnection("[App]", this.indicatorStyle(), function(value, _group, _control) { + DDJ200.transFxButton.send(DDJ200.transFxButton.on * value); + }); } else { - if (this.blinkConnection) { - this.blinkConnection.disconnect(); - }; - // use left Deck as reference for current padInstance - const indicatorValue = DDJ200.Decks.left.padUnit.choosenPadInstance.indicatorStyle; - if (indicatorValue === "indicator_250ms" || indicatorValue === "indicator_500ms") { - this.blinkConnection = engine.makeConnection("[App]", indicatorValue, function(value, _group, _control) { - DDJ200.transFxButton.send(0x7F * value); - }); - } else { - this.send(indicatorValue); - }; + this.send(this.on * this.indicatorStyle()); }; }, }); From 618ea4eca6708da984e62913aa870e6d23ff5e51 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 17:39:47 +0000 Subject: [PATCH 17/70] Pioneer DDJ-200: indication fix for PadMode change fix for issue introduced with last commit --- res/controllers/Pioneer-DDJ-200-scripts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index eac938526b37..eeb7be400210 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -95,7 +95,7 @@ DDJ200.PadModeContainers.Hotcue = function(deckOffset) { ); }; DDJ200.PadModeContainers.Hotcue.prototype = new DDJ200.PadMode({ - indicatorStyle: 0x00, + indicatorStyle: 0, }); DDJ200.PadModeContainers.Loop = function(deckOffset) { @@ -139,7 +139,7 @@ DDJ200.PadModeContainers.Loop = function(deckOffset) { ); }; DDJ200.PadModeContainers.Loop.prototype = new DDJ200.PadMode({ - indicatorStyle: 0x7F, + indicatorStyle: 1, }); DDJ200.PadModeContainers.Effect = function(deckOffset) { From bcd4fe20d9c9aabcaed752c95fd71aca128700fa Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 19:10:09 +0000 Subject: [PATCH 18/70] Pioneer DDJ-200: transFxButton change in midi transFxButton will call now input, shift will detected later --- res/controllers/Pioneer DDJ-200.midi.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index d476fd1e12ae..35d01b075741 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -249,7 +249,7 @@ [AutoDJ] - DDJ200.transFxButton.shiftedInput + DDJ200.transFxButton.input Change Pad mode 0x96 0x5A From 6fd424f4a88f6a6f61e0771aba0e6e399f70ef93 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 19:12:06 +0000 Subject: [PATCH 19/70] Pioneer DDJ-200: updated Implementation of Loop Pads Loop Pad indication must be changed on changes in loop size and if loop gets enabled or disabled. Used multiple connections. --- res/controllers/Pioneer-DDJ-200-scripts.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index eeb7be400210..f39ac6d2f525 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -105,35 +105,39 @@ DDJ200.PadModeContainers.Loop = function(deckOffset) { this.currentBaseLoopSize = parseInt(engine.getSetting("defaultLoopRootSize")); this.constructPads(i => - new DDJ200.Pad(i, deckOffset, { + new components.Component({ + midi: [0x97 + deckOffset, i], unshift: function() { this.inKey = "beatloop_activate"; }, shift: function() { this.inKey = "beatlooproll_activate"; }, + on: 0x7F, + off: 0x00, loopSize: Math.pow(2, theContainer.currentBaseLoopSize + i), - input: function(channel, _control, value, _status, _mode) { + input: function(_channel, _control, value, _status, _mode) { if (value) { const loopEnabled = engine.getValue(this.group, "loop_enabled"); const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); - engine.setValue(this.group, "beatloop_size", this.loopSize); // this should trigger output and switch all buttons off + engine.setValue(this.group, "beatloop_size", this.loopSize); if (matchingLoopSize || !loopEnabled) { engine.setValue(this.group, this.inKey, true); }; - } else { - const loopEnabled = engine.getValue(this.group, "loop_enabled"); - this.send(loopEnabled?0x7F:0x00); }; }, - outKey: "beatloop_size", + outKey: null, // hack to get Component constructor to call connect() + connect: function() { + this.connections[0] = engine.makeConnection(this.group, "beatloop_size", this.output.bind(this)); + this.connections[1] = engine.makeConnection(this.group, "loop_enabled", this.output.bind(this)); + }, outValueScale: function(value) { if (value) { const loopEnabled = engine.getValue(this.group, "loop_enabled"); const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); - return matchingLoopSize?loopEnabled*0x7F:0x00; + return (matchingLoopSize && loopEnabled) ? this.on : this.off; } - return 0x00; + return this.off; }, }) ); From 265a467c18a3f45e7a3ae7f7d558eda83b8ffc7f Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 19:31:44 +0000 Subject: [PATCH 20/70] Pioneer DDJ-200: updated Implementation of BeatJump Pads BeatJump indication must be changed on changes in jump size directly on jump activation. Used multiple connections. --- res/controllers/Pioneer-DDJ-200-scripts.js | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index f39ac6d2f525..f3019afa4e83 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -195,7 +195,7 @@ DDJ200.PadModeContainers.Jump = function(deckOffset) { this.currentBaseBeatJumpSize = parseInt(engine.getSetting("defaultBeatJumpRootSize")); this.constructPads(i => - new components.Button({ + new components.Component({ midi: [0x97 + deckOffset, i], unshift: function() { this.inKey = "beatjump_forward"; @@ -203,17 +203,25 @@ DDJ200.PadModeContainers.Jump = function(deckOffset) { shift: function() { this.inKey = "beatjump_backward"; }, + on: 0x7F, + off: 0x00, beatJumpSize: Math.pow(2, theContainer.currentBaseBeatJumpSize + i), - input: function(channel, control, value, _status, _g) { + input: function(_channel, _control, value, _status, _mode) { + engine.setValue(this.group, "beatjump_size", this.beatJumpSize); + engine.setValue(this.group, this.inKey, value); + }, + outKey: null, // hack to get Component constructor to call connect() + connect: function() { + this.connections[0] = engine.makeConnection(this.group, "beatjump_forward", this.output.bind(this)); + this.connections[1] = engine.makeConnection(this.group, "beatjump_backward", this.output.bind(this)); + }, + outValueScale: function(value) { if (value) { - engine.setValue(this.group, "beatjump_size", this.beatJumpSize); - engine.setValue(this.group, this.inKey, true); - }; - this.send(this.outValueScale(value)); + const matchingJumpSize = (engine.getValue(this.group, "beatjump_size") === this.beatJumpSize); + return (matchingJumpSize) ? this.on : this.off; + } + return this.off; }, - trigger: function(_value) { - this.send(0x00); - } }) ); }; From e4be97c0ae5a347ba59e084c62d8e33c25b63330 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 20:16:10 +0000 Subject: [PATCH 21/70] Pioneer DDJ-200: simplified Effect Button implementation implemented simpler Effect Button version - now only the first two Effect-Racks can be used. Thats probably enough. --- res/controllers/Pioneer-DDJ-200-scripts.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index f3019afa4e83..f0afb2e7c2e7 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -146,7 +146,7 @@ DDJ200.PadModeContainers.Loop.prototype = new DDJ200.PadMode({ indicatorStyle: 1, }); -DDJ200.PadModeContainers.Effect = function(deckOffset) { +DDJ200.PadModeContainers.Effect = function(deckOffset, group) { DDJ200.PadMode.call(this); this.constructPads(i => { @@ -156,17 +156,11 @@ DDJ200.PadModeContainers.Effect = function(deckOffset) { number: deckOffset * 2 + i + 1, }); } else if (i < 7) { - return new DDJ200.Pad(i, deckOffset, { + return new components.Component({ midi: [0x97 + deckOffset, i], - input: function(_channel, _control, value, _status, _g) { - const effect = `[EffectRack1_EffectUnit${ script.deckFromGroup(this.group) }_Effect${ i - 3 }]`; - engine.setValue(effect, "enabled", value); - this.send(this.outValueScale(value)); - }, - outValueScale: function(_value) { - const effect = `[EffectRack1_EffectUnit${ script.deckFromGroup(this.group) }_Effect${ i - 3 }]`; - return engine.getValue(effect, "loaded")?0x7F:0x00; - } + group: `[EffectRack1_EffectUnit${ script.deckFromGroup(group) }_Effect${ i - 3 }]`, + inKey: "enabled", + outKey: "loaded", }); } else { return new components.Button({ @@ -282,7 +276,7 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { this.startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); this.loopInstance = new DDJ200.PadModeContainers.Loop(deckOffset); - this.effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset); + this.effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset, group); this.jumpInstance = new DDJ200.PadModeContainers.Jump(deckOffset); this.padInstancesBuffer = new DDJ200.DoubleRingBuffer( From e7859cb5761334a2df1912c32753918b014023b8 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 20:33:43 +0000 Subject: [PATCH 22/70] Pioneer DDJ-200: updated bpmTap buttons cleanup of bpmTap button implementation --- res/controllers/Pioneer-DDJ-200-scripts.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index f0afb2e7c2e7..b8871c5e0149 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -165,14 +165,14 @@ DDJ200.PadModeContainers.Effect = function(deckOffset, group) { } else { return new components.Button({ midi: [0x97 + deckOffset, i], - input: function(_channel, _control, value, _status, _g) { + indicateButtonPress: function(value) { + this.output(value, null, null); + }, + inSetValue: function(value) { if (value) { bpm.tapButton(script.deckFromGroup(this.group)); }; - this.send(this.outValueScale(value)); - }, - trigger: function(_value) { - this.send(0x00); + this.indicateButtonPress(value); }, }); }; From 9dbc8cac04752a76da5f38539794d28556a7b77b Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 21:23:43 +0000 Subject: [PATCH 23/70] Pioneer DDJ-200: updated implementation of headMix --- res/controllers/Pioneer-DDJ-200-scripts.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index b8871c5e0149..304d70f54c41 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -295,16 +295,20 @@ DDJ200.init = function() { right: new DDJ200.Deck([2, 4], 2), }; - this.headMixButton = new components.Button({ + this.headMixButton = new components.Component({ midi: [0x96, 0x63], key: "headMix", - type: components.Button.prototype.types.toggle, - input: function(_channel, _control, value, _status, _g) { + group: "[Master]", + on: 0x7F, + off: 0x00, + inValueScale: function(value) { if (value) { - const masterMixEnabled = (engine.getValue("[Master]", "headMix") >= 0); - engine.setValue("[Master]", "headMix", masterMixEnabled ? -1 : 0); - this.send(masterMixEnabled?0:0x7F); // set LED - }; + return (this.inGetValue() >= 0) ? -1 : 1; + } + return this.inGetValue(); + }, + outValueScale: function(value) { + return value >= 0 ? this.on : this.off; }, shiftedInput: function(_channel, _control, value, _status, _g) { if (value) { @@ -320,6 +324,9 @@ DDJ200.init = function() { }; }; }, + shutdown: function() { + this.send(this.off); + } }); this.transFxButton = new components.Button({ From 8de411afbecad0bb20cd22203e269ca7177e6b9e Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 21:47:54 +0000 Subject: [PATCH 24/70] Pioneer DDJ-200: cleanup of sync Button --- res/controllers/Pioneer-DDJ-200-scripts.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 304d70f54c41..84ba4b0da0bb 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -442,16 +442,16 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { shiftOffset: 8, input: function(_channel, _control, value, _status, _g) { if (value) { - if (engine.getValue(this.group, "sync_enabled") === 0) { + if (this.inGetValue() === 0) { engine.setValue(this.group, "beatsync", 1); } else { - engine.setValue(this.group, "sync_enabled", 0); + this.inSetValue(0); }; }; }, inputLongPress: function(_channel, _control, value, _status, _g) { if (value) { - engine.setValue(this.group, "sync_enabled", 1); + this.inSetValue(1); }; }, shiftedInput: function(_channel, _control, value, _status, _g) { @@ -460,7 +460,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { theDeck.toggle(); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - theDeck.syncButton.send(0x7F * value); + theDeck.syncButton.send(theDeck.syncButton.on * value); }); } else if (this.blinkConnection) { this.blinkConnection.disconnect(); From 4285cd4eb8a21c8eaf3fbf03d23f0a0d6381e4c6 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 21:48:17 +0000 Subject: [PATCH 25/70] Pioneer DDJ-200: layout changes --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 84ba4b0da0bb..b3dfe1d504f4 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -375,8 +375,8 @@ DDJ200.init = function() { // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); - // start with focus on library for selecting tracks (delay seems required) + // start with focus on library for selecting tracks (delay seems required) engine.beginTimer(500, function() { engine.setValue("[Library]", "MoveFocus", 1); }, true); @@ -536,7 +536,6 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { c.group = this.currentDeck; }; }); - }; DDJ200.Deck.prototype = new components.Deck(); From 1a23575da03fe70bb7bc72482711018cecaf3c07 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 21:50:30 +0000 Subject: [PATCH 26/70] Pioneer DDJ-200: removed obsolete shutdown at the start --- res/controllers/Pioneer-DDJ-200-scripts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index b3dfe1d504f4..425141b4540f 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -371,7 +371,6 @@ DDJ200.init = function() { engine.setValue("[Channel3]", "volume", 0); engine.setValue("[Channel4]", "volume", 0); }; - this.shutdown(); // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); From 42f5342be24c467449df6092cd1b9117b5ef5381 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 28 Sep 2025 22:04:51 +0000 Subject: [PATCH 27/70] Pioneer DDJ-200: Changed DDJ200.decks into ComponentContainer renamed DDJ200.Decks -> DDJ200.decks, configured as ComponentContainer --- res/controllers/Pioneer DDJ-200.midi.xml | 164 ++++++++++----------- res/controllers/Pioneer-DDJ-200-scripts.js | 20 +-- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 35d01b075741..d3b6e02fe8ef 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -57,7 +57,7 @@ [Channel1] - DDJ200.Decks.left.shiftButton.input + DDJ200.decks.left.shiftButton.input Deck 1: Shift pressed 0x90 0x3F @@ -67,7 +67,7 @@ [Channel2] - DDJ200.Decks.right.shiftButton.input + DDJ200.decks.right.shiftButton.input Deck 2: Shift pressed 0x91 0x3F @@ -119,7 +119,7 @@ [Channel1] - DDJ200.Decks.left.pflButton.input + DDJ200.decks.left.pflButton.input Deck 1: Headphone listen (pfl) button 0x90 0x54 @@ -129,7 +129,7 @@ [Channel1] - DDJ200.Decks.left.loadTrack.input + DDJ200.decks.left.loadTrack.input Deck 1: Headphone (pfl) + shift 0x90 0x68 @@ -139,7 +139,7 @@ [Channel2] - DDJ200.Decks.right.pflButton.input + DDJ200.decks.right.pflButton.input Deck 2: Headphone listen (pfl) button 0x91 0x54 @@ -149,7 +149,7 @@ [Channel2] - DDJ200.Decks.right.loadTrack.input + DDJ200.decks.right.loadTrack.input Deck 2: Headphone (pfl) + shift 0x91 0x68 @@ -159,7 +159,7 @@ [Channel1] - DDJ200.Decks.left.syncButton.input + DDJ200.decks.left.syncButton.input Deck 1: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x90 0x58 @@ -169,7 +169,7 @@ [Channel2] - DDJ200.Decks.right.syncButton.input + DDJ200.decks.right.syncButton.input Deck 2: Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x91 0x58 @@ -179,7 +179,7 @@ [Channel1] - DDJ200.Decks.left.syncButton.inputLongPress + DDJ200.decks.left.syncButton.inputLongPress Deck 1: Long Press to enable permanent sync 0x90 0x5C @@ -189,7 +189,7 @@ [Channel2] - DDJ200.Decks.right.syncButton.inputLongPress + DDJ200.decks.right.syncButton.inputLongPress Deck 2: Long Press to enable permanent sync 0x91 0x5C @@ -199,7 +199,7 @@ [Channel1] - DDJ200.Decks.left.syncButton.shiftedInput + DDJ200.decks.left.syncButton.shiftedInput Deck 1: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x90 0x60 @@ -209,7 +209,7 @@ [Channel2] - DDJ200.Decks.right.syncButton.shiftedInput + DDJ200.decks.right.syncButton.shiftedInput Deck 2: Shift Tap to sync tempo (and phase with quantize enabled), hold to enable permanent sync 0x91 0x60 @@ -219,7 +219,7 @@ [Channel1] - DDJ200.Decks.left.jogWheel.inputSeek + DDJ200.decks.left.jogWheel.inputSeek Deck 1: Seek 0xB0 0x29 @@ -229,7 +229,7 @@ [Channel2] - DDJ200.Decks.right.jogWheel.inputSeek + DDJ200.decks.right.jogWheel.inputSeek Deck 2: Seek 0xB1 0x29 @@ -259,7 +259,7 @@ [Channel1] - DDJ200.Decks.left.jogWheel.inputTouch + DDJ200.decks.left.jogWheel.inputTouch Deck 1: Touch 0x90 0x36 @@ -269,7 +269,7 @@ [Channel2] - DDJ200.Decks.right.jogWheel.inputTouch + DDJ200.decks.right.jogWheel.inputTouch Deck 2: Touch 0x91 0x36 @@ -279,7 +279,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.Decks.left.eqKnob[0].input + DDJ200.decks.left.eqKnob[0].input Deck 1: Adjust Low EQ 0xB0 0x0F @@ -289,7 +289,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.Decks.left.eqKnob[1].input + DDJ200.decks.left.eqKnob[1].input Deck 1: Adjust Mid EQ 0xB0 0x0B @@ -299,7 +299,7 @@ [EqualizerRack1_[Channel1]_Effect1] - DDJ200.Decks.left.eqKnob[2].input + DDJ200.decks.left.eqKnob[2].input Deck 1: Adjust High EQ 0xB0 0x07 @@ -309,7 +309,7 @@ [QuickEffectRack1_[Channel1]] - DDJ200.Decks.left.super1.input + DDJ200.decks.left.super1.input Super Knob (msb): control linked effect 0xB6 0x17 @@ -319,7 +319,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.Decks.right.eqKnob[0].input + DDJ200.decks.right.eqKnob[0].input Deck 2: Adjust Low EQ 0xB1 0x0F @@ -329,7 +329,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.Decks.right.eqKnob[1].input + DDJ200.decks.right.eqKnob[1].input Deck 2: Adjust Mid EQ 0xB1 0x0B @@ -339,7 +339,7 @@ [EqualizerRack1_[Channel2]_Effect1] - DDJ200.Decks.right.eqKnob[2].input + DDJ200.decks.right.eqKnob[2].input Deck 2: Adjust High EQ 0xB1 0x07 @@ -349,7 +349,7 @@ [QuickEffectRack1_[Channel2]] - DDJ200.Decks.right.super1.input + DDJ200.decks.right.super1.input Quick Effect: Quick Effect Super Knob (control linked effect parameters) 0xB6 0x18 @@ -359,7 +359,7 @@ [Channel1] - DDJ200.Decks.left.volume.inputMSB + DDJ200.decks.left.volume.inputMSB Deck 1: Volume Fader 0xB0 0x13 @@ -369,7 +369,7 @@ [Channel1] - DDJ200.Decks.left.volume.inputLSB + DDJ200.decks.left.volume.inputLSB Deck 1: Volume Fader 0xB0 0x33 @@ -379,7 +379,7 @@ [Channel2] - DDJ200.Decks.right.volume.inputMSB + DDJ200.decks.right.volume.inputMSB Deck 2: Volume Fader 0xB1 0x13 @@ -389,7 +389,7 @@ [Channel2] - DDJ200.Decks.right.volume.inputLSB + DDJ200.decks.right.volume.inputLSB Deck 2: Volume Fader 0xB1 0x33 @@ -399,7 +399,7 @@ [Channel1] - DDJ200.Decks.left.playButton.input + DDJ200.decks.left.playButton.input Deck 1: Play button 0x90 0x0B @@ -409,7 +409,7 @@ [Channel2] - DDJ200.Decks.right.playButton.input + DDJ200.decks.right.playButton.input Deck 2: Play button 0x91 0x0B @@ -419,7 +419,7 @@ [Channel1] - DDJ200.Decks.left.playButton.inputFaderStart + DDJ200.decks.left.playButton.inputFaderStart Deck 1: Shift and Fader start 0x90 0x66 @@ -429,7 +429,7 @@ [Channel2] - DDJ200.Decks.right.playButton.inputFaderStart + DDJ200.decks.right.playButton.inputFaderStart Deck 2: Shift and Fader start 0x91 0x66 @@ -439,7 +439,7 @@ [Channel1] - DDJ200.Decks.left.cueButton.input + DDJ200.decks.left.cueButton.input Deck 1: Cue button 0x90 0x0C @@ -449,7 +449,7 @@ [Channel2] - DDJ200.Decks.right.cueButton.input + DDJ200.decks.right.cueButton.input Deck 2: Cue button 0x91 0x0C @@ -459,7 +459,7 @@ [Channel1] - DDJ200.Decks.left.cueButton.inputFaderStop + DDJ200.decks.left.cueButton.inputFaderStop Deck 1: Shift and Fader stop 0x90 0x52 @@ -469,7 +469,7 @@ [Channel2] - DDJ200.Decks.right.cueButton.inputFaderStop + DDJ200.decks.right.cueButton.inputFaderStop Deck 2: Shift and Fader stop 0x91 0x52 @@ -479,7 +479,7 @@ [Channel1] - DDJ200.Decks.left.cueButton.input + DDJ200.decks.left.cueButton.input Deck 1: Go to cue point and stop 0x90 0x48 @@ -489,7 +489,7 @@ [Channel2] - DDJ200.Decks.right.cueButton.input + DDJ200.decks.right.cueButton.input Deck 2: Go to cue point and stop 0x91 0x48 @@ -499,7 +499,7 @@ [Channel1] - DDJ200.Decks.left.rate.inputMSB + DDJ200.decks.left.rate.inputMSB Deck 1: Playback speed control 0xB0 0x00 @@ -510,7 +510,7 @@ [Channel1] - DDJ200.Decks.left.rate.inputLSB + DDJ200.decks.left.rate.inputLSB Deck 1: Playback speed control 0xB0 0x20 @@ -521,7 +521,7 @@ [Channel2] - DDJ200.Decks.right.rate.inputMSB + DDJ200.decks.right.rate.inputMSB Deck 2: Playback speed control 0xB1 0x00 @@ -531,7 +531,7 @@ [Channel2] - DDJ200.Decks.right.rate.inputLSB + DDJ200.decks.right.rate.inputLSB Deck 2: Playback speed control 0xB1 0x20 @@ -541,7 +541,7 @@ [Channel1] - DDJ200.Decks.left.jogWheel.inputWheel + DDJ200.decks.left.jogWheel.inputWheel Deck 1: Jog 0xB0 0x21 @@ -551,7 +551,7 @@ [Channel2] - DDJ200.Decks.right.jogWheel.inputWheel + DDJ200.decks.right.jogWheel.inputWheel Deck 2: Jog 0xB1 0x21 @@ -561,7 +561,7 @@ [Channel2] - DDJ200.Decks.right.jogWheel.inputWheel + DDJ200.decks.right.jogWheel.inputWheel Deck 2: Scratch 0xB1 0x22 @@ -571,7 +571,7 @@ [Channel1] - DDJ200.Decks.left.jogWheel.inputWheel + DDJ200.decks.left.jogWheel.inputWheel Deck 1: Scratch 0xB0 0x22 @@ -581,7 +581,7 @@ [Channel2] - DDJ200.Decks.right.jogWheel.inputWheel + DDJ200.decks.right.jogWheel.inputWheel Deck 2: Scratch 0xB1 0x23 @@ -591,7 +591,7 @@ [Channel1] - DDJ200.Decks.left.jogWheel.inputWheel + DDJ200.decks.left.jogWheel.inputWheel Deck 1: Scratch 0xB0 0x23 @@ -601,7 +601,7 @@ [Channel1] - DDJ200.Decks.left.playButton.input + DDJ200.decks.left.playButton.input Deck 1: Shift Play 0x90 0x47 @@ -611,7 +611,7 @@ [Channel2] - DDJ200.Decks.right.playButton.input + DDJ200.decks.right.playButton.input Deck 2: Shift Play 0x91 0x47 @@ -622,7 +622,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 1: Set, preview, jump to 0x97 0x00 @@ -632,7 +632,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 1: Set, preview, jump to 0x97 0x01 @@ -642,7 +642,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 1: Set, preview, jump to 0x97 0x02 @@ -652,7 +652,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 1: Set, preview, jump to 0x97 0x03 @@ -662,7 +662,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 1: Set, preview, jump to 0x97 0x04 @@ -672,7 +672,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 1: Set, preview, jump to 0x97 0x05 @@ -682,7 +682,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 1: Set, preview, jump to 0x97 0x06 @@ -692,7 +692,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 1: Set, preview, jump to 0x97 0x07 @@ -702,7 +702,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 2: Set, preview, jump to 0x99 0x00 @@ -712,7 +712,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 2: Set, preview, jump to 0x99 0x01 @@ -722,7 +722,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 2: Set, preview, jump to 0x99 0x02 @@ -732,7 +732,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 2: Set, preview, jump to 0x99 0x03 @@ -742,7 +742,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 2: Set, preview, jump to 0x99 0x04 @@ -752,7 +752,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 2: Set, preview, jump to 0x99 0x05 @@ -762,7 +762,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 2: Set, preview, jump to 0x99 0x06 @@ -772,7 +772,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 2: Set, preview, jump to 0x99 0x07 @@ -782,7 +782,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 1: Clear 0x98 0x00 @@ -792,7 +792,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 1: Clear 0x98 0x01 @@ -802,7 +802,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 1: Clear 0x98 0x02 @@ -812,7 +812,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 1: Clear 0x98 0x03 @@ -822,7 +822,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 1: Clear 0x98 0x04 @@ -832,7 +832,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 1: Clear 0x98 0x05 @@ -842,7 +842,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 1: Clear 0x98 0x06 @@ -852,7 +852,7 @@ [Channel1] - DDJ200.Decks.left.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.left.padUnit.choosenPadInstance.pads[7].input Hotcue 8, Deck 1: Clear 0x98 0x07 @@ -862,7 +862,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[0].input Hotcue 1, Deck 2: Clear 0x9A 0x00 @@ -872,7 +872,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[1].input Hotcue 2, Deck 2: Clear 0x9A 0x01 @@ -882,7 +882,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[2].input Hotcue 3, Deck 2: Clear 0x9A 0x02 @@ -892,7 +892,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[3].input Hotcue 4, Deck 2: Clear 0x9A 0x03 @@ -902,7 +902,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[4].input Hotcue 5, Deck 2: Clear 0x9A 0x04 @@ -912,7 +912,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[5].input Hotcue 6, Deck 2: Clear 0x9A 0x05 @@ -922,7 +922,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[6].input Hotcue 7, Deck 2: Clear 0x9A 0x06 @@ -932,7 +932,7 @@ [Channel2] - DDJ200.Decks.right.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.right.padUnit.choosenPadInstance.pads[7].input 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 425141b4540f..294bcc1f43a2 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -290,10 +290,10 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { DDJ200.PadModeContainers.ModeSelector.prototype = new components.ComponentContainer(); DDJ200.init = function() { - this.Decks = { + this.decks = new components.ComponentContainer({ left: new DDJ200.Deck([1, 3], 1), right: new DDJ200.Deck([2, 4], 2), - }; + }); this.headMixButton = new components.Component({ midi: [0x96, 0x63], @@ -314,9 +314,9 @@ DDJ200.init = function() { if (value) { engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); if (!engine.getValue("[Skin]", "show_4decks")) { - DDJ200.Decks.left.setCurrentDeck("[Channel1]"); - DDJ200.Decks.right.setCurrentDeck("[Channel2]"); - Object.values(DDJ200.Decks).forEach(deck => { + DDJ200.decks.left.setCurrentDeck("[Channel1]"); + DDJ200.decks.right.setCurrentDeck("[Channel2]"); + Object.values(DDJ200.decks).forEach(deck => { if (deck.syncButton.blinkConnection) { deck.syncButton.blinkConnection.disconnect(); }; @@ -337,7 +337,7 @@ DDJ200.init = function() { input: function(_channel, control, value, _status, _g) { if (value) { - Object.values(DDJ200.Decks).forEach(deck => { + Object.values(DDJ200.decks).forEach(deck => { deck.padUnit.input((control === 0x5A)); }); this.indicatePadMode(); @@ -345,7 +345,7 @@ DDJ200.init = function() { }, indicatorStyle: function() { // use left Deck as reference for selected padInstance - return DDJ200.Decks.left.padUnit.choosenPadInstance.indicatorStyle; + return DDJ200.decks.left.padUnit.choosenPadInstance.indicatorStyle; }, blinkConnection: undefined, indicatePadMode: function() { @@ -365,7 +365,7 @@ DDJ200.init = function() { this.shutdown = function() { DDJ200.headMixButton.shutdown(); DDJ200.transFxButton.shutdown(); - Object.values(DDJ200.Decks).forEach(deck => { + Object.values(DDJ200.decks).forEach(deck => { deck.shutdown(); }); engine.setValue("[Channel3]", "volume", 0); @@ -397,7 +397,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { inKey: "jog", jogCounter: 0, inputSeek: function(_channel, _control, value, _status, group) { - if (DDJ200.Decks.left.shiftButton.pressed) { + if (DDJ200.decks.left.shiftButton.pressed) { this.jogCounter += this.inValueScale(value); if (this.jogCounter > 9) { engine.setValue("[Library]", "MoveDown", true); @@ -423,7 +423,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { pressed: 0, input: function(_channel, _control, value, _status, _g) { this.pressed = value; - Object.values(DDJ200.Decks).forEach(deck => { + Object.values(DDJ200.decks).forEach(deck => { if (value) { deck.shift(); } else { From 85c7157c1b75cf3c6008dd2326258cd7d6abcf3e Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 00:23:02 +0000 Subject: [PATCH 28/70] Pioneer DDJ-200: replaced Object loops with forEachComponentContainer non-recursive forEachComponentContainer required, recursion will be done by Components if suitable --- res/controllers/Pioneer-DDJ-200-scripts.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 294bcc1f43a2..f1552fb48845 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -316,11 +316,11 @@ DDJ200.init = function() { if (!engine.getValue("[Skin]", "show_4decks")) { DDJ200.decks.left.setCurrentDeck("[Channel1]"); DDJ200.decks.right.setCurrentDeck("[Channel2]"); - Object.values(DDJ200.decks).forEach(deck => { + DDJ200.decks.forEachComponentContainer(deck => { if (deck.syncButton.blinkConnection) { deck.syncButton.blinkConnection.disconnect(); }; - }); + }, false); }; }; }, @@ -337,9 +337,9 @@ DDJ200.init = function() { input: function(_channel, control, value, _status, _g) { if (value) { - Object.values(DDJ200.decks).forEach(deck => { + DDJ200.decks.forEachComponentContainer(deck => { deck.padUnit.input((control === 0x5A)); - }); + }, false); this.indicatePadMode(); }; }, @@ -365,9 +365,9 @@ DDJ200.init = function() { this.shutdown = function() { DDJ200.headMixButton.shutdown(); DDJ200.transFxButton.shutdown(); - Object.values(DDJ200.decks).forEach(deck => { + DDJ200.decks.forEachComponentContainer(deck => { deck.shutdown(); - }); + }, false); engine.setValue("[Channel3]", "volume", 0); engine.setValue("[Channel4]", "volume", 0); }; @@ -423,13 +423,13 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { pressed: 0, input: function(_channel, _control, value, _status, _g) { this.pressed = value; - Object.values(DDJ200.decks).forEach(deck => { + DDJ200.decks.forEachComponentContainer(deck => { if (value) { deck.shift(); } else { deck.unshift(); }; - }); + }, false); }, }); From 8f41b18e18a31f0bb612536d88af441de9f6dc2f Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 17:31:25 +0000 Subject: [PATCH 29/70] Pioneer DDJ-200: removed DDJ200.Pad extra class not useful, only used once --- res/controllers/Pioneer-DDJ-200-scripts.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index f1552fb48845..fb100cbe64d1 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -78,20 +78,16 @@ DDJ200.PadMode = function(options) { }; DDJ200.PadMode.prototype = new components.ComponentContainer(); -DDJ200.Pad = function(pos, deckOffset, options) { - options.midi = [0x97 + deckOffset, pos]; - options.number = pos + 1; - components.HotcueButton.call(this, options); -}; -DDJ200.Pad.prototype = new components.HotcueButton({}); - DDJ200.PadModeContainers = {}; DDJ200.PadModeContainers.Hotcue = function(deckOffset) { DDJ200.PadMode.call(this); this.constructPads(i => - new DDJ200.Pad(i, deckOffset, { }) + new components.HotcueButton({ + midi: [0x97 + deckOffset, i], + number: i + 1, + }) ); }; DDJ200.PadModeContainers.Hotcue.prototype = new DDJ200.PadMode({ From 3c3f52336dcb40b88ef44b54f4de4480f66445ef Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 17:33:01 +0000 Subject: [PATCH 30/70] Pioneer DDJ-200: changed options and description changed option defaults and fixed description --- res/controllers/Pioneer DDJ-200.midi.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index d3b6e02fe8ef..7e88b0351fc4 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -15,8 +15,8 @@ -5 -4 - -3 - -2 + -3 + -2 -1 0 1 @@ -26,12 +26,12 @@ 5 6 7 - This specifies the smallest loop size, the larger loopsizes are automatically available on the other pads. This can also be changed on the fly using :hwbtn:SHIFT + "parameter adjust" + This specifies the smallest loop size, the larger loopsizes are automatically available on the other pads. From 4553c9be2748af62ecca571ef7e52c2ec9a4567c Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 17:36:31 +0000 Subject: [PATCH 31/70] Pioneer DDJ-200: added option to use SuperEQ as Gain DDJ-200 misses some hardware Gain Knob for the decks. Added some option to use the Quick Effects Super Knob on the hardware for Gain control. Default is off - SuperEQ is SuperEQ. --- res/controllers/Pioneer DDJ-200.midi.xml | 8 ++++++++ res/controllers/Pioneer-DDJ-200-scripts.js | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 7e88b0351fc4..eae29db47096 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -48,6 +48,14 @@ 7 This specifies the smallest jump size, the larger jumpsizes are automatically available on the other pads. + diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index fb100cbe64d1..69ce1e0a3a74 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -522,8 +522,8 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }; this.super1 = new components.Pot({ - group: `[QuickEffectRack1_${this.currentDeck}]`, - inKey: "super1", + group: (engine.getSetting("useSuperAsGain"))?theDeck.currentDeck:`[QuickEffectRack1_${this.currentDeck}]`, + inKey: (engine.getSetting("useSuperAsGain"))?"pregain":"super1", }); this.reconnectComponents(function(c) { From fcd71a4208231c7069a8f35d9acc42fa729579b0 Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 18:42:13 +0000 Subject: [PATCH 32/70] Pioneer DDJ-200: fixed EffectButtons and enabled 3/4th Unit changed effectButtons to toggle buttons and modified shift level to use 3rd and 4th EffectUnit on shift. --- res/controllers/Pioneer-DDJ-200-scripts.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 69ce1e0a3a74..276a19fd807a 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -152,11 +152,26 @@ DDJ200.PadModeContainers.Effect = function(deckOffset, group) { number: deckOffset * 2 + i + 1, }); } else if (i < 7) { - return new components.Component({ + return new components.Button({ midi: [0x97 + deckOffset, i], group: `[EffectRack1_EffectUnit${ script.deckFromGroup(group) }_Effect${ i - 3 }]`, inKey: "enabled", outKey: "loaded", + type: components.Button.prototype.types.toggle, + unshift: function() { + if (this.connections) { + this.disconnect(); + this.group = this.group.replace("EffectUnit3", "EffectUnit1").replace("EffectUnit4", "EffectUnit2"); + this.connect(); + this.trigger(); + } + }, + shift: function() { + this.disconnect(); + this.group = this.group.replace("EffectUnit1", "EffectUnit3").replace("EffectUnit2", "EffectUnit4"); + this.connect(); + this.trigger(); + }, }); } else { return new components.Button({ From dfca85078b13f20b8a58d0cf1c90ceceb4514c9a Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 23:17:34 +0000 Subject: [PATCH 33/70] Pioneer DDJ-200: fixed PadMode Modeselector removed externally accessible padInstance Containers (this.loopInstance -> const loopInstance). These led to multiple trigger connections during startup - too difficult to remove and handle them all cleanly with setPads. Implemented Deck-Switching internally, because without externally connected padInstances component-js Deckswitching is also not working. --- res/controllers/Pioneer DDJ-200.midi.xml | 64 +++++++-------- res/controllers/Pioneer-DDJ-200-scripts.js | 92 +++++++++++++++------- 2 files changed, 96 insertions(+), 60 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index eae29db47096..bf37c860d0bd 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -630,7 +630,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.left.padUnit.input Hotcue 1, Deck 1: Set, preview, jump to 0x97 0x00 @@ -640,7 +640,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.left.padUnit.input Hotcue 2, Deck 1: Set, preview, jump to 0x97 0x01 @@ -650,7 +650,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.left.padUnit.input Hotcue 3, Deck 1: Set, preview, jump to 0x97 0x02 @@ -660,7 +660,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.left.padUnit.input Hotcue 4, Deck 1: Set, preview, jump to 0x97 0x03 @@ -670,7 +670,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.left.padUnit.input Hotcue 5, Deck 1: Set, preview, jump to 0x97 0x04 @@ -680,7 +680,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.left.padUnit.input Hotcue 6, Deck 1: Set, preview, jump to 0x97 0x05 @@ -690,7 +690,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.left.padUnit.input Hotcue 7, Deck 1: Set, preview, jump to 0x97 0x06 @@ -700,7 +700,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.left.padUnit.input Hotcue 8, Deck 1: Set, preview, jump to 0x97 0x07 @@ -710,7 +710,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.right.padUnit.input Hotcue 1, Deck 2: Set, preview, jump to 0x99 0x00 @@ -720,7 +720,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.right.padUnit.input Hotcue 2, Deck 2: Set, preview, jump to 0x99 0x01 @@ -730,7 +730,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.right.padUnit.input Hotcue 3, Deck 2: Set, preview, jump to 0x99 0x02 @@ -740,7 +740,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.right.padUnit.input Hotcue 4, Deck 2: Set, preview, jump to 0x99 0x03 @@ -750,7 +750,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.right.padUnit.input Hotcue 5, Deck 2: Set, preview, jump to 0x99 0x04 @@ -760,7 +760,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.right.padUnit.input Hotcue 6, Deck 2: Set, preview, jump to 0x99 0x05 @@ -770,7 +770,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.right.padUnit.input Hotcue 7, Deck 2: Set, preview, jump to 0x99 0x06 @@ -780,7 +780,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.right.padUnit.input Hotcue 8, Deck 2: Set, preview, jump to 0x99 0x07 @@ -790,7 +790,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.left.padUnit.input Hotcue 1, Deck 1: Clear 0x98 0x00 @@ -800,7 +800,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.left.padUnit.input Hotcue 2, Deck 1: Clear 0x98 0x01 @@ -810,7 +810,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.left.padUnit.input Hotcue 3, Deck 1: Clear 0x98 0x02 @@ -820,7 +820,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.left.padUnit.input Hotcue 4, Deck 1: Clear 0x98 0x03 @@ -830,7 +830,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.left.padUnit.input Hotcue 5, Deck 1: Clear 0x98 0x04 @@ -840,7 +840,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.left.padUnit.input Hotcue 6, Deck 1: Clear 0x98 0x05 @@ -850,7 +850,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.left.padUnit.input Hotcue 7, Deck 1: Clear 0x98 0x06 @@ -860,7 +860,7 @@ [Channel1] - DDJ200.decks.left.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.left.padUnit.input Hotcue 8, Deck 1: Clear 0x98 0x07 @@ -870,7 +870,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[0].input + DDJ200.decks.right.padUnit.input Hotcue 1, Deck 2: Clear 0x9A 0x00 @@ -880,7 +880,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[1].input + DDJ200.decks.right.padUnit.input Hotcue 2, Deck 2: Clear 0x9A 0x01 @@ -890,7 +890,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[2].input + DDJ200.decks.right.padUnit.input Hotcue 3, Deck 2: Clear 0x9A 0x02 @@ -900,7 +900,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[3].input + DDJ200.decks.right.padUnit.input Hotcue 4, Deck 2: Clear 0x9A 0x03 @@ -910,7 +910,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[4].input + DDJ200.decks.right.padUnit.input Hotcue 5, Deck 2: Clear 0x9A 0x04 @@ -920,7 +920,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[5].input + DDJ200.decks.right.padUnit.input Hotcue 6, Deck 2: Clear 0x9A 0x05 @@ -930,7 +930,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[6].input + DDJ200.decks.right.padUnit.input Hotcue 7, Deck 2: Clear 0x9A 0x06 @@ -940,7 +940,7 @@ [Channel2] - DDJ200.decks.right.padUnit.choosenPadInstance.pads[7].input + DDJ200.decks.right.padUnit.input 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 276a19fd807a..751fbc04340d 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -255,48 +255,81 @@ DDJ200.DoubleRingBuffer = class { DDJ200.PadModeContainers.ModeSelector = function(group) { const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); - const updateSelectorLeds = () => { - this.forEachComponent(c => c.trigger()); - }; + const startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); + const loopInstance = new DDJ200.PadModeContainers.Loop(deckOffset); + const effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset, group); + const jumpInstance = new DDJ200.PadModeContainers.Jump(deckOffset); + + const padInstancesBuffer = new DDJ200.DoubleRingBuffer( + [startupModeInstance, loopInstance, effectInstance], + [jumpInstance] + ); + + let choosenPadInstance = startupModeInstance; + let startup = true; const setPads = newPadInstance => { - if (newPadInstance === this.choosenPadInstance) { + if (!startup && newPadInstance === choosenPadInstance) { return; } - - this.choosenPadInstance.forEachComponent(function(component) { + startup = false; + choosenPadInstance.forEachComponent(function(component) { component.disconnect(); }); - this.choosenPadInstance = newPadInstance; - updateSelectorLeds(); - this.choosenPadInstance.reconnectComponents(function(c) { - if (c.group === undefined) { - c.group = group; + choosenPadInstance = newPadInstance; + choosenPadInstance.forEachComponent(function(component) { + if (component.group === undefined) { + component.group = group; } + component.connect(); + component.trigger(); }); }; - this.input = (isShifted) => { - if (isShifted !== this.padInstancesBuffer.isShifted) { - this.padInstancesBuffer.swapIndexable(); + this.input = function(channel, control, value, status, group) { + choosenPadInstance.pads[control].input(channel, control, value, status, group); + }; + + this.changeMode = (isShifted) => { + if (isShifted !== padInstancesBuffer.isShifted) { + padInstancesBuffer.swapIndexable(); } else { - this.padInstancesBuffer.next(); + padInstancesBuffer.next(); }; - setPads(this.padInstancesBuffer.current()); + setPads(padInstancesBuffer.current()); }; - this.startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); - this.loopInstance = new DDJ200.PadModeContainers.Loop(deckOffset); - this.effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset, group); - this.jumpInstance = new DDJ200.PadModeContainers.Jump(deckOffset); + const updateDeckHelper = function(padInstance, newGroup) { + padInstance.forEachComponent(function(component) { + if (padInstance === choosenPadInstance) { + component.disconnect(); + } + if (component.group === undefined) { + component.group = newGroup; + } else { + const anyChannelRegEx = /\[Channel\d+([\]_])/; + component.group = component.group.replace(anyChannelRegEx, `${newGroup.slice(0, -1)}$1`); + } + if (padInstance === choosenPadInstance) { + component.connect(); + component.trigger(); + } + }); + }; - this.padInstancesBuffer = new DDJ200.DoubleRingBuffer( - [this.startupModeInstance, this.loopInstance, this.effectInstance], - [this.jumpInstance] - ); + this.updateDeck = function(currentDeck) { + padInstancesBuffer.indexable[0].forEach(function(padInstance) { + updateDeckHelper(padInstance, currentDeck); + }); + padInstancesBuffer.indexable[0].forEach(function(padInstance) { + updateDeckHelper(padInstance, currentDeck); + }); + }; - this.choosenPadInstance = new DDJ200.PadMode(); - setPads(this.startupModeInstance); + this.choosenPadInstance = function() { + return choosenPadInstance; + }; + setPads(startupModeInstance); }; DDJ200.PadModeContainers.ModeSelector.prototype = new components.ComponentContainer(); @@ -349,14 +382,14 @@ DDJ200.init = function() { input: function(_channel, control, value, _status, _g) { if (value) { DDJ200.decks.forEachComponentContainer(deck => { - deck.padUnit.input((control === 0x5A)); + deck.padUnit.changeMode((control === 0x5A)); }, false); this.indicatePadMode(); }; }, indicatorStyle: function() { // use left Deck as reference for selected padInstance - return DDJ200.decks.left.padUnit.choosenPadInstance.indicatorStyle; + return DDJ200.decks.left.padUnit.choosenPadInstance().indicatorStyle; }, blinkConnection: undefined, indicatePadMode: function() { @@ -468,6 +501,9 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { if (value) { if (engine.getValue("[Skin]", "show_4decks")) { theDeck.toggle(); + DDJ200.decks.forEachComponentContainer(deck => { + deck.padUnit.updateDeck(deck.currentDeck); + }, false); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { theDeck.syncButton.send(theDeck.syncButton.on * value); From cf121b1eca2f88f590d6c45769895802d069eec3 Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 23:19:24 +0000 Subject: [PATCH 34/70] =?UTF-8?q?Pioneer=20DDJ-200:=20minor=20bugfix=20f?= =?UTF-8?q?=C3=BCr=20blinking=20LED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unset blinkConnection if it is not used --- res/controllers/Pioneer-DDJ-200-scripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 751fbc04340d..192713950c19 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -401,6 +401,7 @@ DDJ200.init = function() { DDJ200.transFxButton.send(DDJ200.transFxButton.on * value); }); } else { + this.blinkConnection = undefined; this.send(this.on * this.indicatorStyle()); }; }, From a1b24abdbdcb9ed5d2a2b90efa83582d1bd1e18c Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 29 Sep 2025 23:20:48 +0000 Subject: [PATCH 35/70] Pioneer DDJ-200: prevent initialization warning triggers warning message when called withoput deck number --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 192713950c19..fca188dced72 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -584,5 +584,4 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }; }); }; - -DDJ200.Deck.prototype = new components.Deck(); +DDJ200.Deck.prototype = new components.Deck(2); From a1d5f660e0153a8b3e033872360fc4396c87b351 Mon Sep 17 00:00:00 2001 From: Rene Date: Tue, 30 Sep 2025 17:30:07 +0000 Subject: [PATCH 36/70] Pioneer DDJ-200: simplified shift Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer-DDJ-200-scripts.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index fca188dced72..19367bcb1c06 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -468,13 +468,11 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { pressed: 0, input: function(_channel, _control, value, _status, _g) { this.pressed = value; - DDJ200.decks.forEachComponentContainer(deck => { - if (value) { - deck.shift(); - } else { - deck.unshift(); - }; - }, false); + if (value) { + DDJ200.decks.shift(); + } else { + DDJ200.decks.unshift(); + } }, }); From 0d4fdf082ebd2a836b0fdf4d4ba9b2f457b67360 Mon Sep 17 00:00:00 2001 From: Rene Date: Tue, 30 Sep 2025 17:30:55 +0000 Subject: [PATCH 37/70] Pioneer DDJ-200: simplified shutdown Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer-DDJ-200-scripts.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 19367bcb1c06..3462c1bab312 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -410,9 +410,7 @@ DDJ200.init = function() { this.shutdown = function() { DDJ200.headMixButton.shutdown(); DDJ200.transFxButton.shutdown(); - DDJ200.decks.forEachComponentContainer(deck => { - deck.shutdown(); - }, false); + DDJ200.decks.shutdown(); engine.setValue("[Channel3]", "volume", 0); engine.setValue("[Channel4]", "volume", 0); }; From 875441bb439cfe1c57ae8d49059479db53d5d967 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 30 Sep 2025 17:23:14 +0000 Subject: [PATCH 38/70] Pioneer DDJ-200: cleanup obsolete loop not required to loop trough all decks, only the one which button was pressed has changed --- res/controllers/Pioneer-DDJ-200-scripts.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 3462c1bab312..2e88a240de0d 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -498,9 +498,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { if (value) { if (engine.getValue("[Skin]", "show_4decks")) { theDeck.toggle(); - DDJ200.decks.forEachComponentContainer(deck => { - deck.padUnit.updateDeck(deck.currentDeck); - }, false); + theDeck.padUnit.updateDeck(theDeck.currentDeck); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { theDeck.syncButton.send(theDeck.syncButton.on * value); From 4761218653c5e1e3ea68ed0f98ab689ee7d85547 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 30 Sep 2025 17:27:29 +0000 Subject: [PATCH 39/70] Pioneer DDJ-200: solve "missing scratch deck" warning --- res/controllers/Pioneer-DDJ-200-scripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 2e88a240de0d..1c517bc44c2e 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -439,6 +439,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }, inKey: "jog", jogCounter: 0, + deck: deckNumbers[0], inputSeek: function(_channel, _control, value, _status, group) { if (DDJ200.decks.left.shiftButton.pressed) { this.jogCounter += this.inValueScale(value); From 778e16851544d3f8624b802b7df6575318b42881 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 30 Sep 2025 18:37:45 +0000 Subject: [PATCH 40/70] Pioneer DDJ-200: fixed Shift issue Wihout external access to the pads (introduced in dfca85078b13f20b8a58d0cf1c90ceceb4514c9a) lso also shift/unshift and shutdown not working. Fixed this. --- res/controllers/Pioneer-DDJ-200-scripts.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 1c517bc44c2e..b14190ac29fb 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -337,6 +337,16 @@ DDJ200.init = function() { this.decks = new components.ComponentContainer({ left: new DDJ200.Deck([1, 3], 1), right: new DDJ200.Deck([2, 4], 2), + shift: function() { + this.left.padUnit.choosenPadInstance().shift(); + this.right.padUnit.choosenPadInstance().shift(); + components.ComponentContainer.prototype.shift(); + }, + unshift: function() { + (this.left.padUnit.choosenPadInstance()).unshift(); + this.right.padUnit.choosenPadInstance().unshift(); + components.ComponentContainer.prototype.unshift(); + } }); this.headMixButton = new components.Component({ @@ -411,6 +421,8 @@ DDJ200.init = function() { DDJ200.headMixButton.shutdown(); DDJ200.transFxButton.shutdown(); DDJ200.decks.shutdown(); + DDJ200.decks.left.padUnit.choosenPadInstance().shutdown(); + DDJ200.decks.right.padUnit.choosenPadInstance().shutdown(); engine.setValue("[Channel3]", "volume", 0); engine.setValue("[Channel4]", "volume", 0); }; From 98ce35903e35971e184cbb02af30b538ead54197 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 19:55:11 +0000 Subject: [PATCH 41/70] Pioneer DDJ-200: fixed JogWheel fix for issue with JogWheel and Deck switching --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index b14190ac29fb..c9c319ca1044 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -452,7 +452,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { inKey: "jog", jogCounter: 0, deck: deckNumbers[0], - inputSeek: function(_channel, _control, value, _status, group) { + inputSeek: function(_channel, _control, value, _status, _group) { if (DDJ200.decks.left.shiftButton.pressed) { this.jogCounter += this.inValueScale(value); if (this.jogCounter > 9) { @@ -463,6 +463,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { this.jogCounter = 0; }; } else { + const group = `[Channel${ this.deck }]`; // fix for wrong group const oldPos = engine.getValue(group, "playposition"); // Since ‘playposition’ is normalized to unity, we need to scale by // song duration in order for the jog wheel to cover the same amount From bd7df51119fa43af9d1b0f5d6d3433e41f8b996c Mon Sep 17 00:00:00 2001 From: Rene Date: Wed, 1 Oct 2025 20:04:20 +0000 Subject: [PATCH 42/70] Pioneer DDJ-200: fixed mixxx version string Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer DDJ-200.midi.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index bf37c860d0bd..728db41441da 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -1,5 +1,5 @@ - + Pioneer DDJ-200 Rene (mixxx at absorb.it), Dan Giddins, Frank.Breitling at gmx.de, Geovanni Pacheco From dcd6955af53146b1b112bcdc7085bc18c73c27bf Mon Sep 17 00:00:00 2001 From: Rene Date: Wed, 1 Oct 2025 20:08:30 +0000 Subject: [PATCH 43/70] Pioneer DDJ-200: improved code readability Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- res/controllers/Pioneer-DDJ-200-scripts.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index c9c319ca1044..92f5f249be49 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -581,10 +581,17 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }); }; - this.super1 = new components.Pot({ - group: (engine.getSetting("useSuperAsGain"))?theDeck.currentDeck:`[QuickEffectRack1_${this.currentDeck}]`, - inKey: (engine.getSetting("useSuperAsGain"))?"pregain":"super1", - }); + if (engine.getSetting("useSuperAsGain")) { + this.super1 = new components.Pot({ + group: theDeck.currentDeck, + inKey: "pregain", + }); + } else { + this.super1 = new components.Pot({ + group: `[QuickEffectRack1_${this.currentDeck}]`; + inKey: "super1", + }); + } this.reconnectComponents(function(c) { if (c.group === undefined) { From 76cb0a960d8ae7a7796f69b82334e91133238b67 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 20:32:26 +0000 Subject: [PATCH 44/70] Pioneer DDJ-200: completed midi documentation --- res/controllers/Pioneer-DDJ-200-scripts.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 92f5f249be49..c4c09396a761 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -43,6 +43,10 @@ Deck n = 0/1: Midi in Midi out PAD 6 press 9p 05 hh [midi in] OFF=0x00, ON=0x7F PAD 7 press 9p 06 hh [midi in] OFF=0x00, ON=0x7F PAD 8 press 9p 07 hh [midi in] OFF=0x00, ON=0x7F + + Loaded Deck1 none 9F 00 7F blinking PADs 1-4 followed by PADs 5-8 + Loaded Deck2 none 9F 01 7F blinking PADs 1-4 followed by PADs 5-8 + Viny Mode on/off none 9n 17 hh OFF=0x00, ON=0x7F (default ON) */ /* From 0917d06baeafb6e0314d989e6974943280aff7b9 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 20:39:10 +0000 Subject: [PATCH 45/70] Pioneer DDJ-200: bugfix for code typo introduced in dcd6955af53146b1b --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index c4c09396a761..2965468b8afe 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -592,7 +592,7 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { }); } else { this.super1 = new components.Pot({ - group: `[QuickEffectRack1_${this.currentDeck}]`; + group: `[QuickEffectRack1_${this.currentDeck}]`, inKey: "super1", }); } From a6dc66b8578618d1c3446cf5c11ec4f1fe2adf99 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 21:01:04 +0000 Subject: [PATCH 46/70] Pioneer DDJ-200: bugfix wrong index beatjump unit was not Deck-Shifted --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 2965468b8afe..375771e70013 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -325,7 +325,7 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { padInstancesBuffer.indexable[0].forEach(function(padInstance) { updateDeckHelper(padInstance, currentDeck); }); - padInstancesBuffer.indexable[0].forEach(function(padInstance) { + padInstancesBuffer.indexable[1].forEach(function(padInstance) { updateDeckHelper(padInstance, currentDeck); }); }; From c74d3f9808e309f8a227c6ec411147c7a473d459 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 21:08:26 +0000 Subject: [PATCH 47/70] Pioneer DDJ-200: fixed typo --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 375771e70013..1271fdcee121 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -347,7 +347,7 @@ DDJ200.init = function() { components.ComponentContainer.prototype.shift(); }, unshift: function() { - (this.left.padUnit.choosenPadInstance()).unshift(); + this.left.padUnit.choosenPadInstance().unshift(); this.right.padUnit.choosenPadInstance().unshift(); components.ComponentContainer.prototype.unshift(); } From a0b38ffb42a163eab1a02ed6b10664e395a8b63a Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 1 Oct 2025 21:36:32 +0000 Subject: [PATCH 48/70] Pioneer DDJ-200: moved information about DEMO mode to mixx-manual --- res/controllers/Pioneer-DDJ-200-scripts.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 1271fdcee121..a8a4086063df 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -49,19 +49,6 @@ Deck n = 0/1: Midi in Midi out Viny Mode on/off none 9n 17 hh OFF=0x00, ON=0x7F (default ON) */ -/* - Disabling Demo Mode according to the user manual: - 1 - Disconnect the USB cable / power supply - 2 - Hold both the [SHIFT] and [PLAY/PAUSE] buttons and connect USB cable / power supply - 3 - Use performance pads to change the settings - Pad 1 - Demo mode is switched off - Pad 2 - Demo mode starts when you don’t use the unit for 1 minute - Pad 3 - Demo mode starts when you don’t use the unit for 5 minutes - Pad 4 - Demo mode starts when you don’t use the unit for 10 minutes - While saving bottom row of Performance Pads is flashing. Wait till it stops. - 4 - Disconnect the USB cable / power supply -*/ - // eslint-disable-next-line no-var var DDJ200 = { }; From d6521fa8adbbfcd1592f2604feb38522071f3bc6 Mon Sep 17 00:00:00 2001 From: rene Date: Thu, 2 Oct 2025 20:39:38 +0000 Subject: [PATCH 49/70] Pioneer DDJ-200: fixed shift and shutdown fowarded shift, unshift and shutdown to the choosen padinstance --- res/controllers/Pioneer-DDJ-200-scripts.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index a8a4086063df..4a49f7e6620e 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -317,6 +317,10 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { }); }; + this.shift = () => choosenPadInstance.shift(); + this.unshift = () => choosenPadInstance.unshift(); + this.shutdown = () => choosenPadInstance.shutdown(); + this.choosenPadInstance = function() { return choosenPadInstance; }; @@ -328,16 +332,6 @@ DDJ200.init = function() { this.decks = new components.ComponentContainer({ left: new DDJ200.Deck([1, 3], 1), right: new DDJ200.Deck([2, 4], 2), - shift: function() { - this.left.padUnit.choosenPadInstance().shift(); - this.right.padUnit.choosenPadInstance().shift(); - components.ComponentContainer.prototype.shift(); - }, - unshift: function() { - this.left.padUnit.choosenPadInstance().unshift(); - this.right.padUnit.choosenPadInstance().unshift(); - components.ComponentContainer.prototype.unshift(); - } }); this.headMixButton = new components.Component({ @@ -412,8 +406,6 @@ DDJ200.init = function() { DDJ200.headMixButton.shutdown(); DDJ200.transFxButton.shutdown(); DDJ200.decks.shutdown(); - DDJ200.decks.left.padUnit.choosenPadInstance().shutdown(); - DDJ200.decks.right.padUnit.choosenPadInstance().shutdown(); engine.setValue("[Channel3]", "volume", 0); engine.setValue("[Channel4]", "volume", 0); }; From 81ac26c5fd31f039f55ad9d6854cfd050aa9eee4 Mon Sep 17 00:00:00 2001 From: rene Date: Thu, 2 Oct 2025 20:41:06 +0000 Subject: [PATCH 50/70] Pioneer DDJ-200: separated faderStart and faderStop --- res/controllers/Pioneer DDJ-200.midi.xml | 8 +++--- res/controllers/Pioneer-DDJ-200-scripts.js | 29 ++++++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 728db41441da..4fc5708bdd44 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -427,7 +427,7 @@ [Channel1] - DDJ200.decks.left.playButton.inputFaderStart + DDJ200.decks.left.faderStartButton.input Deck 1: Shift and Fader start 0x90 0x66 @@ -437,7 +437,7 @@ [Channel2] - DDJ200.decks.right.playButton.inputFaderStart + DDJ200.decks.right.faderStartButton.input Deck 2: Shift and Fader start 0x91 0x66 @@ -467,7 +467,7 @@ [Channel1] - DDJ200.decks.left.cueButton.inputFaderStop + DDJ200.decks.left.faderStopButton.input Deck 1: Shift and Fader stop 0x90 0x52 @@ -477,7 +477,7 @@ [Channel2] - DDJ200.decks.right.cueButton.inputFaderStop + DDJ200.decks.right.faderStopButton.input Deck 2: Shift and Fader stop 0x91 0x52 diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 4a49f7e6620e..13e95d45328c 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -516,10 +516,6 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { shiftChannel: false, shiftControl: true, shiftOffset: 0x3C, - inputFaderStart: function(channel, control, value, status, _g) { - this.inKey = "play"; - this.input(channel, control, value, status, _g); - }, }); this.cueButton = new components.CueButton({ @@ -527,15 +523,28 @@ DDJ200.Deck = function(deckNumbers, midiChannel) { shiftChannel: false, shiftControl: true, shiftOffset: 0x3C, - outKey: "cue_indicator", - inputFaderStop: function(channel, control, value, status, _g) { - this.inKey = "cue_set"; - this.input(channel, control, value, status, _g); - this.inKey = "cue_gotoandstop"; - this.input(channel, control, value, status, _g); + }); + + this.faderStartButton = new components.Button({ + midi: [0x8F + midiChannel, 0x66], + key: "cue_gotoandplay", + // type: components.Button.prototype.types.toggle, + input: function(channel, control, value, status, _g) { + console.warn("faderStart"); + // according the manual: + // Playback starts from the cue point + // When no cue point is set, playback starts from the beginning of the track. + components.Button.prototype.input.call(this, channel, control, value, status, _g); }, }); + this.faderStopButton = new components.Button({ + midi: [0x8F + midiChannel, 0x52], + // according the manual: + // the track instantly jumps back to the cue point and playback pauses + key: "cue_gotoandstop", + }); + this.pflButton = new components.Button({ midi: [0x8F + midiChannel, 0x54], key: "pfl", From 6973557c7fe17500a9c91393e7dbd2a4d5001562 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 4 Oct 2025 21:12:47 +0000 Subject: [PATCH 51/70] Pioneer DDJ-200: bugfix wrong deck selected of 4deck is left wrong deck might have been selected on pads when 4-deck was changed back to 2-deck view. Fixed. --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 13e95d45328c..459d9bed49f3 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -354,7 +354,9 @@ DDJ200.init = function() { engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); if (!engine.getValue("[Skin]", "show_4decks")) { DDJ200.decks.left.setCurrentDeck("[Channel1]"); + DDJ200.decks.left.padUnit.updateDeck("[Channel1]"); DDJ200.decks.right.setCurrentDeck("[Channel2]"); + DDJ200.decks.right.padUnit.updateDeck("[Channel2]"); DDJ200.decks.forEachComponentContainer(deck => { if (deck.syncButton.blinkConnection) { deck.syncButton.blinkConnection.disconnect(); From f90056620dfc83ff5c297ee050806098dce6cb48 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 4 Oct 2025 21:15:11 +0000 Subject: [PATCH 52/70] Pioneer DDJ-200: PadModeContainers cleanup rearranged and cleaned padModeContainer implementation --- res/controllers/Pioneer-DDJ-200-scripts.js | 45 ++++++++++------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 459d9bed49f3..fc1adc685453 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -247,41 +247,37 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); const startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); - const loopInstance = new DDJ200.PadModeContainers.Loop(deckOffset); - const effectInstance = new DDJ200.PadModeContainers.Effect(deckOffset, group); - const jumpInstance = new DDJ200.PadModeContainers.Jump(deckOffset); const padInstancesBuffer = new DDJ200.DoubleRingBuffer( - [startupModeInstance, loopInstance, effectInstance], - [jumpInstance] + [startupModeInstance, new DDJ200.PadModeContainers.Loop(deckOffset), new DDJ200.PadModeContainers.Effect(deckOffset, group)], + [new DDJ200.PadModeContainers.Jump(deckOffset)] ); + const connectPadInstance = function(padInstance) { + padInstance.forEachComponent(function(component) { + if (component.group === undefined) { + component.group = group; + } + component.connect(); + component.trigger(); + }); + }; + let choosenPadInstance = startupModeInstance; + connectPadInstance(choosenPadInstance); - let startup = true; const setPads = newPadInstance => { - if (!startup && newPadInstance === choosenPadInstance) { + if (newPadInstance === choosenPadInstance) { return; } - startup = false; choosenPadInstance.forEachComponent(function(component) { component.disconnect(); }); choosenPadInstance = newPadInstance; - choosenPadInstance.forEachComponent(function(component) { - if (component.group === undefined) { - component.group = group; - } - component.connect(); - component.trigger(); - }); + connectPadInstance(choosenPadInstance); }; - this.input = function(channel, control, value, status, group) { - choosenPadInstance.pads[control].input(channel, control, value, status, group); - }; - - this.changeMode = (isShifted) => { + this.changePadMode = (isShifted) => { if (isShifted !== padInstancesBuffer.isShifted) { padInstancesBuffer.swapIndexable(); } else { @@ -320,11 +316,10 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { this.shift = () => choosenPadInstance.shift(); this.unshift = () => choosenPadInstance.unshift(); this.shutdown = () => choosenPadInstance.shutdown(); - - this.choosenPadInstance = function() { - return choosenPadInstance; + this.choosenPadInstance = () => choosenPadInstance; + this.input = function(channel, control, value, status, group) { + choosenPadInstance.pads[control].input(channel, control, value, status, group); }; - setPads(startupModeInstance); }; DDJ200.PadModeContainers.ModeSelector.prototype = new components.ComponentContainer(); @@ -379,7 +374,7 @@ DDJ200.init = function() { input: function(_channel, control, value, _status, _g) { if (value) { DDJ200.decks.forEachComponentContainer(deck => { - deck.padUnit.changeMode((control === 0x5A)); + deck.padUnit.changePadMode((control === 0x5A)); }, false); this.indicatePadMode(); }; From 1cccc44fff3b7c097a08cb466e857f23b48054db Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 4 Oct 2025 22:47:25 +0000 Subject: [PATCH 53/70] Pioneer DDJ-200: conversion to classes implemented ES6 classes --- res/controllers/Pioneer-DDJ-200-scripts.js | 598 ++++++++++----------- 1 file changed, 298 insertions(+), 300 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index fc1adc685453..d49eaa5d3664 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -56,174 +56,169 @@ components.Component.prototype.shiftOffset = 1; components.Component.prototype.shiftChannel = true; components.Component.prototype.sendShifted = true; -DDJ200.PadMode = function(options) { - components.ComponentContainer.call(this, options); - - this.constructPads = constructPad => { +DDJ200.PadMode = class extends components.ComponentContainer { + constructor(options) { + super(options); + // this is a workaround for components, forEachComponent only iterates + // over ownProperties, so these have to constructed by the constructor here + // instead of being merged by the ComponentContainer constructor + this.pads = Array(8).fill(undefined); + } + constructPads(constructPad) { this.pads = this.pads.map((_, padIndex) => constructPad(padIndex)); - }; - // this is a workaround for components, forEachComponent only iterates - // over ownProperties, so these have to constructed by the constructor here - // instead of being merged by the ComponentContainer constructor - this.pads = Array(8).fill(undefined); + } }; -DDJ200.PadMode.prototype = new components.ComponentContainer(); - -DDJ200.PadModeContainers = {}; -DDJ200.PadModeContainers.Hotcue = function(deckOffset) { - DDJ200.PadMode.call(this); +DDJ200.PadModeContainers = { + Hotcue: class extends DDJ200.PadMode { + constructor(deckOffset) { + super(); - this.constructPads(i => - new components.HotcueButton({ - midi: [0x97 + deckOffset, i], - number: i + 1, - }) - ); -}; -DDJ200.PadModeContainers.Hotcue.prototype = new DDJ200.PadMode({ - indicatorStyle: 0, -}); + super.constructPads(i => new components.HotcueButton({ + midi: [0x97 + deckOffset, i], + number: i + 1, + }) + ); -DDJ200.PadModeContainers.Loop = function(deckOffset) { - DDJ200.PadMode.call(this); + this.indicatorStyle = 0; + } + }, + Loop: class extends DDJ200.PadMode { + constructor(deckOffset) { + super(); - const theContainer = this; - this.currentBaseLoopSize = parseInt(engine.getSetting("defaultLoopRootSize")); + const theContainer = this; + this.currentBaseLoopSize = parseInt(engine.getSetting("defaultLoopRootSize")); - this.constructPads(i => - new components.Component({ - midi: [0x97 + deckOffset, i], - unshift: function() { - this.inKey = "beatloop_activate"; - }, - shift: function() { - this.inKey = "beatlooproll_activate"; - }, - on: 0x7F, - off: 0x00, - loopSize: Math.pow(2, theContainer.currentBaseLoopSize + i), - input: function(_channel, _control, value, _status, _mode) { - if (value) { - const loopEnabled = engine.getValue(this.group, "loop_enabled"); - const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); - engine.setValue(this.group, "beatloop_size", this.loopSize); - if (matchingLoopSize || !loopEnabled) { - engine.setValue(this.group, this.inKey, true); + super.constructPads(i => new components.Component({ + midi: [0x97 + deckOffset, i], + unshift: function() { + this.inKey = "beatloop_activate"; + }, + shift: function() { + this.inKey = "beatlooproll_activate"; + }, + on: 0x7F, + off: 0x00, + loopSize: Math.pow(2, theContainer.currentBaseLoopSize + i), + input: function(_channel, _control, value, _status, _mode) { + if (value) { + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); + engine.setValue(this.group, "beatloop_size", this.loopSize); + if (matchingLoopSize || !loopEnabled) { + engine.setValue(this.group, this.inKey, true); + }; }; + }, + outKey: null, // hack to get Component constructor to call connect() + connect: function() { + this.connections[0] = engine.makeConnection(this.group, "beatloop_size", this.output.bind(this)); + this.connections[1] = engine.makeConnection(this.group, "loop_enabled", this.output.bind(this)); + }, + outValueScale: function(value) { + if (value) { + const loopEnabled = engine.getValue(this.group, "loop_enabled"); + const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); + return (matchingLoopSize && loopEnabled) ? this.on : this.off; + } + return this.off; + }, + }) + ); + this.indicatorStyle = 1; + } + }, + Effect: class extends DDJ200.PadMode { + constructor(deckOffset, group) { + super(); + + super.constructPads(i => { + if (i < 4) { + return new components.SamplerButton({ + midi: [0x97 + deckOffset, i], + number: deckOffset * 2 + i + 1, + }); + } else if (i < 7) { + return new components.Button({ + midi: [0x97 + deckOffset, i], + group: `[EffectRack1_EffectUnit${script.deckFromGroup(group)}_Effect${i - 3}]`, + inKey: "enabled", + outKey: "loaded", + type: components.Button.prototype.types.toggle, + unshift: function() { + if (this.connections) { + this.disconnect(); + this.group = this.group.replace("EffectUnit3", "EffectUnit1").replace("EffectUnit4", "EffectUnit2"); + this.connect(); + this.trigger(); + } + }, + shift: function() { + this.disconnect(); + this.group = this.group.replace("EffectUnit1", "EffectUnit3").replace("EffectUnit2", "EffectUnit4"); + this.connect(); + this.trigger(); + }, + }); + } else { + return new components.Button({ + midi: [0x97 + deckOffset, i], + indicateButtonPress: function(value) { + this.output(value, null, null); + }, + inSetValue: function(value) { + if (value) { + bpm.tapButton(script.deckFromGroup(this.group)); + }; + this.indicateButtonPress(value); + }, + }); }; - }, - outKey: null, // hack to get Component constructor to call connect() - connect: function() { - this.connections[0] = engine.makeConnection(this.group, "beatloop_size", this.output.bind(this)); - this.connections[1] = engine.makeConnection(this.group, "loop_enabled", this.output.bind(this)); - }, - outValueScale: function(value) { - if (value) { - const loopEnabled = engine.getValue(this.group, "loop_enabled"); - const matchingLoopSize = (engine.getValue(this.group, "beatloop_size") === this.loopSize); - return (matchingLoopSize && loopEnabled) ? this.on : this.off; - } - return this.off; - }, - }) - ); -}; -DDJ200.PadModeContainers.Loop.prototype = new DDJ200.PadMode({ - indicatorStyle: 1, -}); + }); + this.indicatorStyle = "indicator_500ms"; + } + }, + Jump: class extends DDJ200.PadMode { + constructor(deckOffset) { + super(); -DDJ200.PadModeContainers.Effect = function(deckOffset, group) { - DDJ200.PadMode.call(this); + const theContainer = this; + this.currentBaseBeatJumpSize = parseInt(engine.getSetting("defaultBeatJumpRootSize")); - this.constructPads(i => { - if (i < 4) { - return new components.SamplerButton({ - midi: [0x97 + deckOffset, i], - number: deckOffset * 2 + i + 1, - }); - } else if (i < 7) { - return new components.Button({ + super.constructPads(i => new components.Component({ midi: [0x97 + deckOffset, i], - group: `[EffectRack1_EffectUnit${ script.deckFromGroup(group) }_Effect${ i - 3 }]`, - inKey: "enabled", - outKey: "loaded", - type: components.Button.prototype.types.toggle, unshift: function() { - if (this.connections) { - this.disconnect(); - this.group = this.group.replace("EffectUnit3", "EffectUnit1").replace("EffectUnit4", "EffectUnit2"); - this.connect(); - this.trigger(); - } + this.inKey = "beatjump_forward"; }, shift: function() { - this.disconnect(); - this.group = this.group.replace("EffectUnit1", "EffectUnit3").replace("EffectUnit2", "EffectUnit4"); - this.connect(); - this.trigger(); + this.inKey = "beatjump_backward"; }, - }); - } else { - return new components.Button({ - midi: [0x97 + deckOffset, i], - indicateButtonPress: function(value) { - this.output(value, null, null); + on: 0x7F, + off: 0x00, + beatJumpSize: Math.pow(2, theContainer.currentBaseBeatJumpSize + i), + input: function(_channel, _control, value, _status, _mode) { + engine.setValue(this.group, "beatjump_size", this.beatJumpSize); + engine.setValue(this.group, this.inKey, value); }, - inSetValue: function(value) { + outKey: null, // hack to get Component constructor to call connect() + connect: function() { + this.connections[0] = engine.makeConnection(this.group, "beatjump_forward", this.output.bind(this)); + this.connections[1] = engine.makeConnection(this.group, "beatjump_backward", this.output.bind(this)); + }, + outValueScale: function(value) { if (value) { - bpm.tapButton(script.deckFromGroup(this.group)); - }; - this.indicateButtonPress(value); + const matchingJumpSize = (engine.getValue(this.group, "beatjump_size") === this.beatJumpSize); + return (matchingJumpSize) ? this.on : this.off; + } + return this.off; }, - }); - }; - }); -}; -DDJ200.PadModeContainers.Effect.prototype = new DDJ200.PadMode({ - indicatorStyle: "indicator_500ms", -}); - -DDJ200.PadModeContainers.Jump = function(deckOffset) { - DDJ200.PadMode.call(this); - - const theContainer = this; - this.currentBaseBeatJumpSize = parseInt(engine.getSetting("defaultBeatJumpRootSize")); - - this.constructPads(i => - new components.Component({ - midi: [0x97 + deckOffset, i], - unshift: function() { - this.inKey = "beatjump_forward"; - }, - shift: function() { - this.inKey = "beatjump_backward"; - }, - on: 0x7F, - off: 0x00, - beatJumpSize: Math.pow(2, theContainer.currentBaseBeatJumpSize + i), - input: function(_channel, _control, value, _status, _mode) { - engine.setValue(this.group, "beatjump_size", this.beatJumpSize); - engine.setValue(this.group, this.inKey, value); - }, - outKey: null, // hack to get Component constructor to call connect() - connect: function() { - this.connections[0] = engine.makeConnection(this.group, "beatjump_forward", this.output.bind(this)); - this.connections[1] = engine.makeConnection(this.group, "beatjump_backward", this.output.bind(this)); - }, - outValueScale: function(value) { - if (value) { - const matchingJumpSize = (engine.getValue(this.group, "beatjump_size") === this.beatJumpSize); - return (matchingJumpSize) ? this.on : this.off; - } - return this.off; - }, - }) - ); + }) + ); + this.indicatorStyle = "indicator_250ms"; + } + }, }; -DDJ200.PadModeContainers.Jump.prototype = new DDJ200.PadMode({ - indicatorStyle: "indicator_250ms", -}); DDJ200.DoubleRingBuffer = class { constructor(indexableUnshifted, indexableShifted) { @@ -416,176 +411,179 @@ DDJ200.init = function() { }, true); }; -DDJ200.Deck = function(deckNumbers, midiChannel) { - components.Deck.call(this, deckNumbers); - const theDeck = this; - this.padUnit = new DDJ200.PadModeContainers.ModeSelector(this.currentDeck); +DDJ200.Deck = class extends components.Deck { + constructor(deckNumbers, midiChannel) { + super(deckNumbers); - this.jogWheel = new components.JogWheelBasic({ - wheelResolution: 128, // how many ticks per revolution the jogwheel has - alpha: 1/8, // alpha-filter - beta: 1/8/32, - rpm: 33 + 1/3, - inValueScale: function(value) { - return value - 64; - }, - inKey: "jog", - jogCounter: 0, - deck: deckNumbers[0], - inputSeek: function(_channel, _control, value, _status, _group) { - if (DDJ200.decks.left.shiftButton.pressed) { - this.jogCounter += this.inValueScale(value); - if (this.jogCounter > 9) { - engine.setValue("[Library]", "MoveDown", true); - this.jogCounter = 0; - } else if (this.jogCounter < -9) { - engine.setValue("[Library]", "MoveUp", true); - this.jogCounter = 0; - }; - } else { - const group = `[Channel${ this.deck }]`; // fix for wrong group - const oldPos = engine.getValue(group, "playposition"); - // Since ‘playposition’ is normalized to unity, we need to scale by - // song duration in order for the jog wheel to cover the same amount - // of time given a constant turning angle. - const duration = engine.getValue(group, "duration"); - const newPos = Math.max(0, oldPos + (this.inValueScale(value) * 0.2 / duration)); - - engine.setValue(group, "playposition", newPos); // Strip search - }; - }, - }); + const theDeck = this; + this.padUnit = new DDJ200.PadModeContainers.ModeSelector(this.currentDeck); - this.shiftButton = new components.Button({ - pressed: 0, - input: function(_channel, _control, value, _status, _g) { - this.pressed = value; - if (value) { - DDJ200.decks.shift(); - } else { - DDJ200.decks.unshift(); - } - }, - }); + this.jogWheel = new components.JogWheelBasic({ + wheelResolution: 128, // how many ticks per revolution the jogwheel has + alpha: 1 / 8, // alpha-filter + beta: 1 / 8 / 32, + rpm: 33 + 1 / 3, + inValueScale: function(value) { + return value - 64; + }, + inKey: "jog", + jogCounter: 0, + deck: deckNumbers[0], + inputSeek: function(_channel, _control, value, _status, _group) { + if (DDJ200.decks.left.shiftButton.pressed) { + this.jogCounter += this.inValueScale(value); + if (this.jogCounter > 9) { + engine.setValue("[Library]", "MoveDown", true); + this.jogCounter = 0; + } else if (this.jogCounter < -9) { + engine.setValue("[Library]", "MoveUp", true); + this.jogCounter = 0; + }; + } else { + const group = `[Channel${this.deck}]`; // fix for wrong group + const oldPos = engine.getValue(group, "playposition"); + // Since ‘playposition’ is normalized to unity, we need to scale by + // song duration in order for the jog wheel to cover the same amount + // of time given a constant turning angle. + const duration = engine.getValue(group, "duration"); + const newPos = Math.max(0, oldPos + (this.inValueScale(value) * 0.2 / duration)); + + engine.setValue(group, "playposition", newPos); // Strip search + }; + }, + }); - this.syncButton = new components.Button({ - midi: [0x8F + midiChannel, 0x58], - key: "sync_enabled", - shiftChannel: false, - shiftControl: true, - shiftOffset: 8, - input: function(_channel, _control, value, _status, _g) { - if (value) { - if (this.inGetValue() === 0) { - engine.setValue(this.group, "beatsync", 1); + this.shiftButton = new components.Button({ + pressed: 0, + input: function(_channel, _control, value, _status, _g) { + this.pressed = value; + if (value) { + DDJ200.decks.shift(); } else { - this.inSetValue(0); + DDJ200.decks.unshift(); + } + }, + }); + + this.syncButton = new components.Button({ + midi: [0x8F + midiChannel, 0x58], + key: "sync_enabled", + shiftChannel: false, + shiftControl: true, + shiftOffset: 8, + input: function(_channel, _control, value, _status, _g) { + if (value) { + if (this.inGetValue() === 0) { + engine.setValue(this.group, "beatsync", 1); + } else { + this.inSetValue(0); + }; }; - }; - }, - inputLongPress: function(_channel, _control, value, _status, _g) { - if (value) { - this.inSetValue(1); - }; - }, - shiftedInput: function(_channel, _control, value, _status, _g) { - if (value) { - if (engine.getValue("[Skin]", "show_4decks")) { - theDeck.toggle(); - theDeck.padUnit.updateDeck(theDeck.currentDeck); - if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - theDeck.syncButton.send(theDeck.syncButton.on * value); - }); - } else if (this.blinkConnection) { - this.blinkConnection.disconnect(); + }, + inputLongPress: function(_channel, _control, value, _status, _g) { + if (value) { + this.inSetValue(1); + }; + }, + shiftedInput: function(_channel, _control, value, _status, _g) { + if (value) { + midi.sendShortMsg(0x9F, (script.deckFromGroup(theDeck.currentDeck) - 1) % 2, 0x7F); + + if (engine.getValue("[Skin]", "show_4decks")) { + theDeck.toggle(); + theDeck.padUnit.updateDeck(theDeck.currentDeck); + if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + theDeck.syncButton.send(theDeck.syncButton.on * value); + }); + } else if (this.blinkConnection) { + this.blinkConnection.disconnect(); + }; + } else { + const currentRange = engine.getValue(this.group, "rateRange"); + engine.setValue(this.group, "rateRange", (currentRange > 0.9) ? 0.1 : currentRange + 0.1); }; - } else { - const currentRange = engine.getValue(this.group, "rateRange"); - engine.setValue(this.group, "rateRange", (currentRange>0.9)?0.1:currentRange+0.1); }; - }; - }, - }); + }, + }); - this.playButton = new components.PlayButton({ - midi: [0x8F + midiChannel, 0x0B], - shiftChannel: false, - shiftControl: true, - shiftOffset: 0x3C, - }); + this.playButton = new components.PlayButton({ + midi: [0x8F + midiChannel, 0x0B], + shiftChannel: false, + shiftControl: true, + shiftOffset: 0x3C, + }); - this.cueButton = new components.CueButton({ - midi: [0x8F + midiChannel, 0x0C], - shiftChannel: false, - shiftControl: true, - shiftOffset: 0x3C, - }); + this.cueButton = new components.CueButton({ + midi: [0x8F + midiChannel, 0x0C], + shiftChannel: false, + shiftControl: true, + shiftOffset: 0x3C, + }); + + this.faderStartButton = new components.Button({ + midi: [0x8F + midiChannel, 0x66], + key: "cue_gotoandplay", + input: function(channel, control, value, status, _g) { + console.warn("faderStart"); + // according the manual: + // Playback starts from the cue point + // When no cue point is set, playback starts from the beginning of the track. + components.Button.prototype.input.call(this, channel, control, value, status, _g); + }, + }); - this.faderStartButton = new components.Button({ - midi: [0x8F + midiChannel, 0x66], - key: "cue_gotoandplay", - // type: components.Button.prototype.types.toggle, - input: function(channel, control, value, status, _g) { - console.warn("faderStart"); + this.faderStopButton = new components.Button({ + midi: [0x8F + midiChannel, 0x52], // according the manual: - // Playback starts from the cue point - // When no cue point is set, playback starts from the beginning of the track. - components.Button.prototype.input.call(this, channel, control, value, status, _g); - }, - }); + // the track instantly jumps back to the cue point and playback pauses + key: "cue_gotoandstop", + }); - this.faderStopButton = new components.Button({ - midi: [0x8F + midiChannel, 0x52], - // according the manual: - // the track instantly jumps back to the cue point and playback pauses - key: "cue_gotoandstop", - }); + this.pflButton = new components.Button({ + midi: [0x8F + midiChannel, 0x54], + key: "pfl", + type: components.Button.prototype.types.toggle, + }); - this.pflButton = new components.Button({ - midi: [0x8F + midiChannel, 0x54], - key: "pfl", - type: components.Button.prototype.types.toggle, - }); + this.loadTrack = new components.Button({ + midi: [0x8F + midiChannel, 0x68], + inKey: "LoadSelectedTrack", + }); - this.loadTrack = new components.Button({ - midi: [0x8F + midiChannel, 0x68], - inKey: "LoadSelectedTrack", - }); + this.volume = new components.Pot({ + inKey: "volume", + }); - this.volume = new components.Pot({ - inKey: "volume", - }); + this.rate = new components.Pot({ + inKey: "rate", + invert: 1, + }); - this.rate = new components.Pot({ - inKey: "rate", - invert: 1, - }); + this.eqKnob = []; + for (let i = 0; i < 3; i++) { + this.eqKnob[i] = new components.Pot({ + group: `[EqualizerRack1_${this.currentDeck}_Effect1]`, + inKey: `parameter${i + 1}`, + }); + }; - this.eqKnob = []; - for (let i = 0; i < 3; i++) { - this.eqKnob[i] = new components.Pot({ - group: `[EqualizerRack1_${this.currentDeck}_Effect1]`, - inKey: `parameter${i+1}`, - }); - }; + if (engine.getSetting("useSuperAsGain")) { + this.super1 = new components.Pot({ + group: theDeck.currentDeck, + inKey: "pregain", + }); + } else { + this.super1 = new components.Pot({ + group: `[QuickEffectRack1_${this.currentDeck}]`, + inKey: "super1", + }); + } - if (engine.getSetting("useSuperAsGain")) { - this.super1 = new components.Pot({ - group: theDeck.currentDeck, - inKey: "pregain", - }); - } else { - this.super1 = new components.Pot({ - group: `[QuickEffectRack1_${this.currentDeck}]`, - inKey: "super1", + this.reconnectComponents(function(c) { + if (c.group === undefined) { + c.group = this.currentDeck; + }; }); } - - this.reconnectComponents(function(c) { - if (c.group === undefined) { - c.group = this.currentDeck; - }; - }); }; -DDJ200.Deck.prototype = new components.Deck(2); From 751e5508e15905c28bb13957e9044ca01c54e0d1 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 4 Oct 2025 23:16:11 +0000 Subject: [PATCH 54/70] Pioneer DDJ-200: cleanup + ES6 for padModeContainers further cleanup padModeCntainers is now a ES6 class --- res/controllers/Pioneer-DDJ-200-scripts.js | 102 ++++++++++----------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index d49eaa5d3664..aa5b98ff6e93 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -238,52 +238,53 @@ DDJ200.DoubleRingBuffer = class { }; }; -DDJ200.PadModeContainers.ModeSelector = function(group) { - const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); - - const startupModeInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); - - const padInstancesBuffer = new DDJ200.DoubleRingBuffer( - [startupModeInstance, new DDJ200.PadModeContainers.Loop(deckOffset), new DDJ200.PadModeContainers.Effect(deckOffset, group)], - [new DDJ200.PadModeContainers.Jump(deckOffset)] - ); - - const connectPadInstance = function(padInstance) { - padInstance.forEachComponent(function(component) { - if (component.group === undefined) { - component.group = group; - } - component.connect(); - component.trigger(); - }); - }; - - let choosenPadInstance = startupModeInstance; - connectPadInstance(choosenPadInstance); +DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContainer { + constructor(group) { + super(); + const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); + + this.choosenPadInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); + + this.padInstancesBuffer = new DDJ200.DoubleRingBuffer( + [this.choosenPadInstance, new DDJ200.PadModeContainers.Loop(deckOffset), new DDJ200.PadModeContainers.Effect(deckOffset, group)], + [new DDJ200.PadModeContainers.Jump(deckOffset)] + ); + + this.connectPadInstance = padInstance => { + padInstance.forEachComponent(function(component) { + if (component.group === undefined) { + component.group = group; + } + component.connect(); + component.trigger(); + }); + }; + this.connectPadInstance(this.choosenPadInstance); + } - const setPads = newPadInstance => { - if (newPadInstance === choosenPadInstance) { + setPads(newPadInstance) { + if (newPadInstance === this.choosenPadInstance) { return; } - choosenPadInstance.forEachComponent(function(component) { + this.choosenPadInstance.forEachComponent(function(component) { component.disconnect(); }); - choosenPadInstance = newPadInstance; - connectPadInstance(choosenPadInstance); - }; + this.choosenPadInstance = newPadInstance; + this.connectPadInstance(this.choosenPadInstance); + } - this.changePadMode = (isShifted) => { - if (isShifted !== padInstancesBuffer.isShifted) { - padInstancesBuffer.swapIndexable(); + changePadMode(isShifted) { + if (isShifted !== this.padInstancesBuffer.isShifted) { + this.padInstancesBuffer.swapIndexable(); } else { - padInstancesBuffer.next(); + this.padInstancesBuffer.next(); }; - setPads(padInstancesBuffer.current()); - }; + this.setPads(this.padInstancesBuffer.current()); + } - const updateDeckHelper = function(padInstance, newGroup) { + updateDeckHelper(padInstance, newGroup) { padInstance.forEachComponent(function(component) { - if (padInstance === choosenPadInstance) { + if (padInstance === this.choosenPadInstance) { component.disconnect(); } if (component.group === undefined) { @@ -292,31 +293,26 @@ DDJ200.PadModeContainers.ModeSelector = function(group) { const anyChannelRegEx = /\[Channel\d+([\]_])/; component.group = component.group.replace(anyChannelRegEx, `${newGroup.slice(0, -1)}$1`); } - if (padInstance === choosenPadInstance) { + if (padInstance === this.choosenPadInstance) { component.connect(); component.trigger(); } }); - }; + } - this.updateDeck = function(currentDeck) { - padInstancesBuffer.indexable[0].forEach(function(padInstance) { - updateDeckHelper(padInstance, currentDeck); + updateDeck(currentDeck) { + this.padInstancesBuffer.indexable[0].forEach(padInstance => { + this.updateDeckHelper(padInstance, currentDeck); }); - padInstancesBuffer.indexable[1].forEach(function(padInstance) { - updateDeckHelper(padInstance, currentDeck); + this.padInstancesBuffer.indexable[1].forEach(padInstance => { + this.updateDeckHelper(padInstance, currentDeck); }); - }; + } - this.shift = () => choosenPadInstance.shift(); - this.unshift = () => choosenPadInstance.unshift(); - this.shutdown = () => choosenPadInstance.shutdown(); - this.choosenPadInstance = () => choosenPadInstance; - this.input = function(channel, control, value, status, group) { - choosenPadInstance.pads[control].input(channel, control, value, status, group); - }; + input(channel, control, value, status, group) { + this.choosenPadInstance.pads[control].input(channel, control, value, status, group); + } }; -DDJ200.PadModeContainers.ModeSelector.prototype = new components.ComponentContainer(); DDJ200.init = function() { this.decks = new components.ComponentContainer({ @@ -376,7 +372,7 @@ DDJ200.init = function() { }, indicatorStyle: function() { // use left Deck as reference for selected padInstance - return DDJ200.decks.left.padUnit.choosenPadInstance().indicatorStyle; + return DDJ200.decks.left.padUnit.choosenPadInstance.indicatorStyle; }, blinkConnection: undefined, indicatePadMode: function() { From 49589cf2e7ff670bdb1ad245427ec7ae4d05fe3b Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 4 Oct 2025 23:24:56 +0000 Subject: [PATCH 55/70] Pioneer DDJ-200: removed keyboard flash effect was not planned for a release -just a test if LED-ready signal is useful for deck switching signalization - it isn't --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index aa5b98ff6e93..d57a7ce6e407 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -483,8 +483,6 @@ DDJ200.Deck = class extends components.Deck { }, shiftedInput: function(_channel, _control, value, _status, _g) { if (value) { - midi.sendShortMsg(0x9F, (script.deckFromGroup(theDeck.currentDeck) - 1) % 2, 0x7F); - if (engine.getValue("[Skin]", "show_4decks")) { theDeck.toggle(); theDeck.padUnit.updateDeck(theDeck.currentDeck); From e11cf53b4d54f29b6ca256d934f73d02543111e1 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 5 Oct 2025 17:34:59 +0000 Subject: [PATCH 56/70] Pioneer DDJ-200: centralized setCurrentDeck --- res/controllers/Pioneer-DDJ-200-scripts.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index d57a7ce6e407..261dab5a2de0 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -282,7 +282,7 @@ DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContai this.setPads(this.padInstancesBuffer.current()); } - updateDeckHelper(padInstance, newGroup) { + setCurrentDeckHelper(padInstance, newGroup) { padInstance.forEachComponent(function(component) { if (padInstance === this.choosenPadInstance) { component.disconnect(); @@ -300,12 +300,12 @@ DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContai }); } - updateDeck(currentDeck) { + setCurrentDeck(newGroup) { this.padInstancesBuffer.indexable[0].forEach(padInstance => { - this.updateDeckHelper(padInstance, currentDeck); + this.setCurrentDeckHelper(padInstance, newGroup); }); this.padInstancesBuffer.indexable[1].forEach(padInstance => { - this.updateDeckHelper(padInstance, currentDeck); + this.setCurrentDeckHelper(padInstance, newGroup); }); } @@ -340,9 +340,7 @@ DDJ200.init = function() { engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); if (!engine.getValue("[Skin]", "show_4decks")) { DDJ200.decks.left.setCurrentDeck("[Channel1]"); - DDJ200.decks.left.padUnit.updateDeck("[Channel1]"); DDJ200.decks.right.setCurrentDeck("[Channel2]"); - DDJ200.decks.right.padUnit.updateDeck("[Channel2]"); DDJ200.decks.forEachComponentContainer(deck => { if (deck.syncButton.blinkConnection) { deck.syncButton.blinkConnection.disconnect(); @@ -485,7 +483,6 @@ DDJ200.Deck = class extends components.Deck { if (value) { if (engine.getValue("[Skin]", "show_4decks")) { theDeck.toggle(); - theDeck.padUnit.updateDeck(theDeck.currentDeck); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { theDeck.syncButton.send(theDeck.syncButton.on * value); @@ -580,4 +577,9 @@ DDJ200.Deck = class extends components.Deck { }; }); } + + setCurrentDeck(newGroup) { + this.padUnit.setCurrentDeck(newGroup); + super.setCurrentDeck(newGroup); + } }; From 1f3bf9d75ce155b2aa9a59733c97b135f989e384 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 5 Oct 2025 20:20:10 +0000 Subject: [PATCH 57/70] Pioneer DDJ-200: reset Volume of Deck 3 and 4 on start if not set, it will be 100% on every start - thats not suitable for starting with these decks. --- res/controllers/Pioneer-DDJ-200-scripts.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 261dab5a2de0..3ea5edc0847d 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -399,6 +399,10 @@ DDJ200.init = function() { // query the controller for current control positions on startup midi.sendSysexMsg([0xF0, 0x00, 0x40, 0x05, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x03, 0x01, 0xf7], 12); + // reset start volume of channels 3 and 4 (can't be read from 2-deck controller) + engine.setValue("[Channel3]", "volume", 0); + engine.setValue("[Channel4]", "volume", 0); + // start with focus on library for selecting tracks (delay seems required) engine.beginTimer(500, function() { engine.setValue("[Library]", "MoveFocus", 1); From 36bd35187d3f3913cca5dd36b85fcd9a5ebaea2d Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 6 Oct 2025 19:38:27 +0000 Subject: [PATCH 58/70] Pioneer DDJ-200: bugfix to prevent double connections --- res/controllers/Pioneer-DDJ-200-scripts.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 3ea5edc0847d..3038783ef143 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -575,10 +575,9 @@ DDJ200.Deck = class extends components.Deck { }); } - this.reconnectComponents(function(c) { - if (c.group === undefined) { - c.group = this.currentDeck; - }; + // this is required, otherwise there is one connection too much per Component + this.forEachComponent(function(component) { + component.disconnect(); }); } From 2cbea4ad3553e7e5e006dc19effb428c9e48c40f Mon Sep 17 00:00:00 2001 From: rene Date: Mon, 6 Oct 2025 19:49:22 +0000 Subject: [PATCH 59/70] Pioneer DDJ-200: readded group configuration it's required and was removed in last commit - fixed --- res/controllers/Pioneer-DDJ-200-scripts.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 3038783ef143..9c962c7c9445 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -577,6 +577,9 @@ DDJ200.Deck = class extends components.Deck { // this is required, otherwise there is one connection too much per Component this.forEachComponent(function(component) { + if (component.group === undefined) { + component.group = this.currentDeck; + }; component.disconnect(); }); } From 6d195e01bac59689169b2438f3db5ece7c5c3de4 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 7 Oct 2025 00:10:09 +0000 Subject: [PATCH 60/70] Pioneer DDJ-200: double connection issue cleaned Setting outConnect: false and adding group to all instances of PadModeContainer solved finally the problems with double connections. They had been introduced by connectPadInstance - connection and trigger was not required there. Initial connections will be established by components.componentContainer.applyLayer --- res/controllers/Pioneer-DDJ-200-scripts.js | 41 +++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 9c962c7c9445..8cdc8519fa03 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -71,12 +71,14 @@ DDJ200.PadMode = class extends components.ComponentContainer { DDJ200.PadModeContainers = { Hotcue: class extends DDJ200.PadMode { - constructor(deckOffset) { + constructor(deckOffset, group) { super(); super.constructPads(i => new components.HotcueButton({ midi: [0x97 + deckOffset, i], number: i + 1, + group, + outConnect: false, }) ); @@ -84,7 +86,7 @@ DDJ200.PadModeContainers = { } }, Loop: class extends DDJ200.PadMode { - constructor(deckOffset) { + constructor(deckOffset, group) { super(); const theContainer = this; @@ -100,6 +102,8 @@ DDJ200.PadModeContainers = { }, on: 0x7F, off: 0x00, + group, + outConnect: false, loopSize: Math.pow(2, theContainer.currentBaseLoopSize + i), input: function(_channel, _control, value, _status, _mode) { if (value) { @@ -138,6 +142,8 @@ DDJ200.PadModeContainers = { return new components.SamplerButton({ midi: [0x97 + deckOffset, i], number: deckOffset * 2 + i + 1, + group, + outConnect: false, }); } else if (i < 7) { return new components.Button({ @@ -145,6 +151,7 @@ DDJ200.PadModeContainers = { group: `[EffectRack1_EffectUnit${script.deckFromGroup(group)}_Effect${i - 3}]`, inKey: "enabled", outKey: "loaded", + outConnect: false, type: components.Button.prototype.types.toggle, unshift: function() { if (this.connections) { @@ -164,6 +171,8 @@ DDJ200.PadModeContainers = { } else { return new components.Button({ midi: [0x97 + deckOffset, i], + group, + outConnect: false, indicateButtonPress: function(value) { this.output(value, null, null); }, @@ -180,7 +189,7 @@ DDJ200.PadModeContainers = { } }, Jump: class extends DDJ200.PadMode { - constructor(deckOffset) { + constructor(deckOffset, group) { super(); const theContainer = this; @@ -196,6 +205,8 @@ DDJ200.PadModeContainers = { }, on: 0x7F, off: 0x00, + group, + outConnect: false, beatJumpSize: Math.pow(2, theContainer.currentBaseBeatJumpSize + i), input: function(_channel, _control, value, _status, _mode) { engine.setValue(this.group, "beatjump_size", this.beatJumpSize); @@ -243,23 +254,11 @@ DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContai super(); const deckOffset = (((script.deckFromGroup(group) - 1) % 2) * 2); - this.choosenPadInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset); - + this.choosenPadInstance = new DDJ200.PadModeContainers.Hotcue(deckOffset, group); this.padInstancesBuffer = new DDJ200.DoubleRingBuffer( - [this.choosenPadInstance, new DDJ200.PadModeContainers.Loop(deckOffset), new DDJ200.PadModeContainers.Effect(deckOffset, group)], - [new DDJ200.PadModeContainers.Jump(deckOffset)] + [this.choosenPadInstance, new DDJ200.PadModeContainers.Loop(deckOffset, group), new DDJ200.PadModeContainers.Effect(deckOffset, group)], + [new DDJ200.PadModeContainers.Jump(deckOffset, group)] ); - - this.connectPadInstance = padInstance => { - padInstance.forEachComponent(function(component) { - if (component.group === undefined) { - component.group = group; - } - component.connect(); - component.trigger(); - }); - }; - this.connectPadInstance(this.choosenPadInstance); } setPads(newPadInstance) { @@ -270,7 +269,10 @@ DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContai component.disconnect(); }); this.choosenPadInstance = newPadInstance; - this.connectPadInstance(this.choosenPadInstance); + this.choosenPadInstance.forEachComponent(function(component) { + component.connect(); + component.trigger(); + }); } changePadMode(isShifted) { @@ -580,7 +582,6 @@ DDJ200.Deck = class extends components.Deck { if (component.group === undefined) { component.group = this.currentDeck; }; - component.disconnect(); }); } From 4927b0d34f021af43b893093bc8c3f114660f65f Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 7 Oct 2025 23:13:55 +0000 Subject: [PATCH 61/70] Pioneer DDJ-200: ensure that indication lights are off indication lights might stay on if blinking is stopped during on-cycle. fixed. --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 8cdc8519fa03..da617d6ec2b8 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -346,6 +346,7 @@ DDJ200.init = function() { DDJ200.decks.forEachComponentContainer(deck => { if (deck.syncButton.blinkConnection) { deck.syncButton.blinkConnection.disconnect(); + deck.syncButton.send(deck.syncButton.off); }; }, false); }; @@ -495,6 +496,7 @@ DDJ200.Deck = class extends components.Deck { }); } else if (this.blinkConnection) { this.blinkConnection.disconnect(); + theDeck.syncButton.send(theDeck.syncButton.off); }; } else { const currentRange = engine.getValue(this.group, "rateRange"); From 0567fba6ede05dc8e20b5dff0b8b906f083a3be9 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 7 Oct 2025 23:18:50 +0000 Subject: [PATCH 62/70] Pioneer DDJ-200: improved library handling added option to choose which shift button to use for library scrolling. pressing boith shift buttons together will now allow you to change currently focused pane --- res/controllers/Pioneer DDJ-200.midi.xml | 24 ++++++++++++++++++++++ res/controllers/Pioneer-DDJ-200-scripts.js | 6 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 4fc5708bdd44..014a265cf31e 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -56,6 +56,30 @@ There is no hardware "Gain" knob on the Pioneer DDJ-200. When enabled, the "Quick Effect" knob can be used to control the gain of the respective deck instead. + + + diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index da617d6ec2b8..684862a7d791 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -431,7 +431,8 @@ DDJ200.Deck = class extends components.Deck { jogCounter: 0, deck: deckNumbers[0], inputSeek: function(_channel, _control, value, _status, _group) { - if (DDJ200.decks.left.shiftButton.pressed) { + if ((engine.getSetting("useLeftShiftAsLibraryScroll") && DDJ200.decks.left.shiftButton.pressed) || + (engine.getSetting("useRightShiftAsLibraryScroll") && DDJ200.decks.right.shiftButton.pressed)) { this.jogCounter += this.inValueScale(value); if (this.jogCounter > 9) { engine.setValue("[Library]", "MoveDown", true); @@ -459,6 +460,9 @@ DDJ200.Deck = class extends components.Deck { input: function(_channel, _control, value, _status, _g) { this.pressed = value; if (value) { + if (DDJ200.decks.left.shiftButton.pressed && DDJ200.decks.right.shiftButton.pressed) { + engine.setValue("[Library]", "MoveFocusForward", true); + } DDJ200.decks.shift(); } else { DDJ200.decks.unshift(); From 2afc0ad12d7c39e0296e210ef9322d902b4666c1 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 8 Oct 2025 17:33:35 +0000 Subject: [PATCH 63/70] Pioneer DDJ-200: bugfix for sampler buttons regression with introduced with 6d195e01 . SamplerButton sets own group, should not be overridden. --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 684862a7d791..050a255ad004 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -142,8 +142,6 @@ DDJ200.PadModeContainers = { return new components.SamplerButton({ midi: [0x97 + deckOffset, i], number: deckOffset * 2 + i + 1, - group, - outConnect: false, }); } else if (i < 7) { return new components.Button({ From 5689e1b003490c3d29bb34f59b6dda6a0950cf03 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 11 Oct 2025 18:19:32 +0000 Subject: [PATCH 64/70] Pioneer DDJ-200: added option to change rateRange added Option to change rateRange/Tempo Range even if 4deck mode is used: pressing both Shift buttons and SyncButton. unified detection of bith Shift button presses. --- res/controllers/Pioneer-DDJ-200-scripts.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 050a255ad004..382c531efaf4 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -458,7 +458,7 @@ DDJ200.Deck = class extends components.Deck { input: function(_channel, _control, value, _status, _g) { this.pressed = value; if (value) { - if (DDJ200.decks.left.shiftButton.pressed && DDJ200.decks.right.shiftButton.pressed) { + if (theDeck.bothShift()) { engine.setValue("[Library]", "MoveFocusForward", true); } DDJ200.decks.shift(); @@ -490,7 +490,7 @@ DDJ200.Deck = class extends components.Deck { }, shiftedInput: function(_channel, _control, value, _status, _g) { if (value) { - if (engine.getValue("[Skin]", "show_4decks")) { + if (engine.getValue("[Skin]", "show_4decks") && !theDeck.bothShift()) { theDeck.toggle(); if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { @@ -593,4 +593,8 @@ DDJ200.Deck = class extends components.Deck { this.padUnit.setCurrentDeck(newGroup); super.setCurrentDeck(newGroup); } + + bothShift() { + return (DDJ200.decks.left.shiftButton.pressed && DDJ200.decks.right.shiftButton.pressed); + } }; From a5a1007b04b004638fbf916b4487732fa88aca9e Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 11 Oct 2025 20:44:26 +0000 Subject: [PATCH 65/70] Pioneer DDJ-200: use dblClick on Shift Btn to swap decks improved 4-deck handling: just double-clickung on the shift button changes the selected deck. Handling of Shift + Beat-Sync now mathces the controller label in all cases and changes Tempo Slider Range. --- res/controllers/Pioneer-DDJ-200-scripts.js | 38 +++++++++++++--------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index 382c531efaf4..bd4b0f7fd322 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -455,11 +455,19 @@ DDJ200.Deck = class extends components.Deck { this.shiftButton = new components.Button({ pressed: 0, + clickTime: 0, input: function(_channel, _control, value, _status, _g) { this.pressed = value; if (value) { - if (theDeck.bothShift()) { - engine.setValue("[Library]", "MoveFocusForward", true); + if (engine.getValue("[Skin]", "show_4decks") && ((Date.now() - this.clickTime) < 500)) { // double-click + this.clickTime = 0; + theDeck.toggle(); + theDeck.syncButton.indicateDeck(); + } else { + this.clickTime = Date.now(); + if (theDeck.bothShift()) { + engine.setValue("[Library]", "MoveFocusForward", true); + } } DDJ200.decks.shift(); } else { @@ -488,22 +496,20 @@ DDJ200.Deck = class extends components.Deck { this.inSetValue(1); }; }, + indicateDeck: function() { + if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { + this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { + theDeck.syncButton.send(theDeck.syncButton.on * value); + }); + } else if (this.blinkConnection) { + this.blinkConnection.disconnect(); + theDeck.syncButton.send(theDeck.syncButton.off); + }; + }, shiftedInput: function(_channel, _control, value, _status, _g) { if (value) { - if (engine.getValue("[Skin]", "show_4decks") && !theDeck.bothShift()) { - theDeck.toggle(); - if (theDeck.currentDeck === "[Channel3]" || theDeck.currentDeck === "[Channel4]") { - this.blinkConnection = engine.makeConnection("[App]", "indicator_250ms", function(value, _group, _control) { - theDeck.syncButton.send(theDeck.syncButton.on * value); - }); - } else if (this.blinkConnection) { - this.blinkConnection.disconnect(); - theDeck.syncButton.send(theDeck.syncButton.off); - }; - } else { - const currentRange = engine.getValue(this.group, "rateRange"); - engine.setValue(this.group, "rateRange", (currentRange > 0.9) ? 0.1 : currentRange + 0.1); - }; + const currentRange = engine.getValue(this.group, "rateRange"); + engine.setValue(this.group, "rateRange", (currentRange > 0.9) ? 0.1 : currentRange + 0.1); }; }, }); From 7b9a618159f2e94e919a93898ba9dfec0713929e Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 15 Oct 2025 17:20:04 +0000 Subject: [PATCH 66/70] Pioneer DDJ-200: removed Mapping setting duplication --- res/controllers/Pioneer DDJ-200.midi.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index 014a265cf31e..af1c09479cdf 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -72,14 +72,6 @@ Usually pressing shift will allow you to scratch through your track faster. When enabled, the Right Shift together with Jog Wheel (top) can be used to scroll through your library. - From 2ce96e8741e6806c7155738190bade693ebf2c00 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 15 Oct 2025 21:05:34 +0200 Subject: [PATCH 67/70] Pioneer DDJ-200: fixed wrong pfl button indication --- res/controllers/Pioneer-DDJ-200-scripts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index bd4b0f7fd322..d5924d144469 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -549,12 +549,14 @@ DDJ200.Deck = class extends components.Deck { this.pflButton = new components.Button({ midi: [0x8F + midiChannel, 0x54], + sendShifted: false, key: "pfl", type: components.Button.prototype.types.toggle, }); this.loadTrack = new components.Button({ midi: [0x8F + midiChannel, 0x68], + sendShifted: false, inKey: "LoadSelectedTrack", }); From eabd4c1b84ee586fb80e533b486eb5e9196a26ab Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 31 Oct 2025 07:45:25 +0100 Subject: [PATCH 68/70] Pioneer DDJ-200: reset 4-deck state if changed via gui change the current deck selection back to 2-deck even if state was changed via settings gui. --- res/controllers/Pioneer-DDJ-200-scripts.js | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index d5924d144469..ebbab57f4ed3 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -335,25 +335,29 @@ DDJ200.init = function() { outValueScale: function(value) { return value >= 0 ? this.on : this.off; }, + indicateDeck: function(show_4decks, _group, _control) { + if (!show_4decks) { + DDJ200.decks.left.setCurrentDeck("[Channel1]"); + DDJ200.decks.right.setCurrentDeck("[Channel2]"); + DDJ200.decks.forEachComponentContainer(deck => { + if (deck.syncButton.blinkConnection) { + deck.syncButton.blinkConnection.disconnect(); + deck.syncButton.send(deck.syncButton.off); + }; + }, false); + }; + }, shiftedInput: function(_channel, _control, value, _status, _g) { if (value) { engine.setValue("[Skin]", "show_4decks", !engine.getValue("[Skin]", "show_4decks")); - if (!engine.getValue("[Skin]", "show_4decks")) { - DDJ200.decks.left.setCurrentDeck("[Channel1]"); - DDJ200.decks.right.setCurrentDeck("[Channel2]"); - DDJ200.decks.forEachComponentContainer(deck => { - if (deck.syncButton.blinkConnection) { - deck.syncButton.blinkConnection.disconnect(); - deck.syncButton.send(deck.syncButton.off); - }; - }, false); - }; }; }, shutdown: function() { this.send(this.off); } }); + engine.makeConnection("[Skin]", "show_4decks", this.headMixButton.indicateDeck); + this.transFxButton = new components.Button({ midi: [0x96, 0x59], From cd60555dd4a7765f00142ff2cb758dd80d3ba1dd Mon Sep 17 00:00:00 2001 From: Rene Date: Sat, 14 Mar 2026 22:33:30 -0300 Subject: [PATCH 69/70] Pioneer DDJ-200: changed controller name removed leftover alternative naming, set to default controller name --- res/controllers/Pioneer DDJ-200.midi.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/controllers/Pioneer DDJ-200.midi.xml b/res/controllers/Pioneer DDJ-200.midi.xml index af1c09479cdf..d4fbc2d79b4c 100755 --- a/res/controllers/Pioneer DDJ-200.midi.xml +++ b/res/controllers/Pioneer DDJ-200.midi.xml @@ -73,7 +73,7 @@ - + From 4021e1de1e1adbbd702f9c4762b31d0ef28c1b09 Mon Sep 17 00:00:00 2001 From: Rene Date: Sun, 15 Mar 2026 23:11:28 -0300 Subject: [PATCH 70/70] Pioneer DDJ-200: shift/unshift new padmodeContainer When changing the PadMode container with shift, the shift-state was not taken over to the new Pads. Fixed now. --- res/controllers/Pioneer-DDJ-200-scripts.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/controllers/Pioneer-DDJ-200-scripts.js b/res/controllers/Pioneer-DDJ-200-scripts.js index ebbab57f4ed3..d9eeae178911 100755 --- a/res/controllers/Pioneer-DDJ-200-scripts.js +++ b/res/controllers/Pioneer-DDJ-200-scripts.js @@ -280,6 +280,11 @@ DDJ200.PadModeContainers.ModeSelector = class extends components.ComponentContai this.padInstancesBuffer.next(); }; this.setPads(this.padInstancesBuffer.current()); + if (isShifted) { + this.choosenPadInstance.shift(); + } else { + this.choosenPadInstance.unshift(); + } } setCurrentDeckHelper(padInstance, newGroup) {