diff --git a/README.MD b/README.MD index a494fcb..b55b4d2 100644 --- a/README.MD +++ b/README.MD @@ -8,8 +8,10 @@ This program allows jog wheels and pitch control on third-party controllers to w - Hercules DJControl - Inpulse 200 - Mix -- Numark +- Numark - Mixtrack 3 +- Native Instruments + - Traktor Kontrol S2 MK3 To use it with other controllers, you'll need to find the MIDI calls and their pattern using MIDI-OX or a similar tool and modify the source code accordingly. Feel free to send a Pull Request! diff --git a/RekordJog_TraktorKontrolS2MK3.py b/RekordJog_TraktorKontrolS2MK3.py new file mode 100644 index 0000000..993b32e --- /dev/null +++ b/RekordJog_TraktorKontrolS2MK3.py @@ -0,0 +1,97 @@ +import os +import mido +from functions.check_config import check_config +from functions.rekordjog_start_sequence import rekordjog_start_sequence + +JOG_MULTIPLIER = 1 + +CONV_J_VAL = { + # Counter-Clockwise (CCW) + 46: 46, 47: 47, 48: 48, 49: 49, 50: 50, + 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, + 56: 56, 57: 57, 58: 58, 59: 59, 60: 60, + 61: 61, 62: 62, 63: 63, + + # Clockwise (CW) + 65: 65, 66: 66, 67: 67, 68: 68, 69: 69, + 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, + 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, + 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, +} + +JOG_CODES = { + (0xb1, 0x1e): 0, + (0xb3, 0x1e): 1 +} + +TOUCH_ON_CODES = { + (0x91, 0x14): 0, + (0x93, 0x14): 1 +} + +TOUCH_OFF_CODES = { + (0x91, 0x14): 0, + (0x93, 0x14): 1 +} + + +def map_jog_value(midi_value): + return CONV_J_VAL.get(midi_value, 64) + + +def jog(midi_out, msg): + try: + id = JOG_CODES[tuple(msg.bytes()[:2])] + v = map_jog_value(msg.bytes()[2]) + + ms = mido.Message.from_bytes([176 + id, 0x22, v]) + + for i in range(JOG_MULTIPLIER): + midi_out.send(ms) + except KeyError: + pass + + +def main(): + midi_inp, midi_out = check_config() + try: + midi_inp_conf, midi_out_conf = check_config() + midi_inp = mido.open_input(midi_inp_conf) + if os.name == 'nt': + midi_out = mido.open_output(midi_out_conf) + else: + midi_out = mido.open_output("Pioneer DDJ-SX", True) + + rekordjog_start_sequence() + print("\nTraktor Kontrol S2 MK3 handler started.") + + while True: + ims = midi_inp.receive() + ims_2b = tuple(ims.bytes()[:2]) + + if ims_2b in JOG_CODES: + jog(midi_out, ims) + + elif ims_2b in TOUCH_ON_CODES: + deck_id = TOUCH_ON_CODES[ims_2b] + + if hasattr(ims, 'type') and ims.type == 'note_on' and ims.velocity == 0: + release = mido.Message.from_bytes( + [0x90 + deck_id, 0x36, 0x00]) + midi_out.send(release) + else: + touch = mido.Message.from_bytes( + [0x90 + deck_id, 0x36, 0x7F]) + midi_out.send(touch) + + elif ims_2b in TOUCH_OFF_CODES: + deck_id = TOUCH_OFF_CODES[ims_2b] + release = mido.Message.from_bytes([0x90 + deck_id, 0x36, 0x00]) + midi_out.send(release) + + except KeyboardInterrupt: + print("\nClosing RekordJog, bye.") + + +if __name__ == "__main__": + main() diff --git a/midi_mappings/Traktor Kontrol S2 MK3.csv b/midi_mappings/Traktor Kontrol S2 MK3.csv new file mode 100644 index 0000000..aad0aaf --- /dev/null +++ b/midi_mappings/Traktor Kontrol S2 MK3.csv @@ -0,0 +1,56 @@ +@file,1,Traktor Kontrol S2 MK3 +Browse,,Rotary,B119,,,,,,,,,,, +Browse,,Rotary,B319,,,,,,,,,,, +ChannelFader,,KnobSlider,,B501,B601,,,,,,,,, +CrossFader,,KnobSlider,B701,,,,,,,,,,Fast;, +Cue,,Button,,9102,9302,,,,9102,9302,,,Fast;Blink=500;Priority=50;, +EQHigh,,KnobSlider,,B505,B605,,,,,,,,Fast;, +EQLow,,KnobSlider,,B503,B603,,,,,,,,Fast;, +EQMid,,KnobSlider,,B504,B604,,,,,,,,Fast;, +Gain,,KnobSlider,,B506,B606,,,,,,,,Fast;, +GridAdjust,,Button,,910D,930D,,,,910D,930D,,,, +HeadphoneCue,,Button,,9508,9608,,,,9508,9608,,,, +HeadphonesMix,,KnobSlider,B707,,,,,,,,,,, +HeadphonesVolume,,KnobSlider,B706,,,,,,,,,,, +HotCue,,Button,,910B,,,,,910B,,,,Fast;, +KeySync,,Button,,910F,930F,,,,910F,930F,,,, +Load,,Button,,9118,9318,,,,,,,,, +MFX1,,Rotary,B502,,,,,,,,,,, +MFX2,,Rotary,B602,,,,,,,,,,, +MasterLevel,,KnobSlider,B709,,,,,,,,,,, +NoFunction,,Button,,920B,,,,,920B,,,,Fast;, +NoFunction,,Button,,9227,,,,,9227,,,,Fast;, +NoFunction,,Button,,9314,,,,,9314,,,,Fast;, +NoFunction,,Button,,B31E,,,,,B31E,,,,Fast;, +NoFunction,,DdjSxPad,,9114,,,,,9114,,,,Fast;, +NoFunction,,DdjSxPad,,9203,,,,,9203,,,,Fast;, +NoFunction,,DdjSxPad,,B21E,,,,,B21E,,,,Fast;, +NoFunction,,Rotary,9129,,,,,,,,,,, +NoFunction,,Rotary,9329,,,,,,,,,,, +NoFunction,,Button,,,,,,,9118,9318,,,, +NoFunction,,Button,,,,,,,9129,9329,,,, +PAD1_HotCue,,DdjSxPad,,9103,,,,,9103,,,,Fast;, +PAD1_HotCue+Shift,,DdjSxPad,,9127,,,,,9127,,,,Fast;, +PAD1_PadFx1,,DdjSxPad,,B11E,,,,,B11E,,,,Fast;, +PAD2_HotCue,,DdjSxPad,,9104,,,,,9104,,,,Fast;, +PAD2_HotCue+Shift,,DdjSxPad,,9204,,,,,9204,,,,Fast;, +PAD3_HotCue,,DdjSxPad,,9105,,,,,9105,,,,Fast;, +PAD3_HotCue+Shift,,DdjSxPad,,9205,,,,,9205,,,,Fast;, +PAD4_HotCue,,DdjSxPad,,9106,,,,,9106,,,,Fast;, +PAD4_HotCue+Shift,,DdjSxPad,,9206,,,,,9206,,,,Fast;, +PAD5_HotCue,,DdjSxPad,,9107,,,,,9107,,,,Fast;, +PAD5_HotCue+Shift,,DdjSxPad,,9207,,,,,9207,,,,Fast;, +PAD6_HotCue,,DdjSxPad,,9108,,,,,9108,,,,Fast;, +PAD6_HotCue+Shift,,DdjSxPad,,9208,,,,,9208,,,,Fast;, +PAD7_HotCue,,DdjSxPad,,9109,,,,,9109,,,,Fast;, +PAD7_HotCue+Shift,,DdjSxPad,,9209,,,,,9209,,,,Fast;, +PAD8_HotCue,,DdjSxPad,,910A,,,,,910A,,,,Fast;, +PAD8_HotCue+Shift,,DdjSxPad,,920A,,,,,920A,,,,Fast;, +PadFx1,,Button,,910C,,,,,910C,,,,Fast;, +PlayPause,,Button,,9101,9301,,,,9101,9301,,,Fast;Blink=1000;Priority=50;, +Quantize,,Button,,970A,9328,,,,970A,9328,,,, +Reverse,,Button,,9115,9315,,,,9115,9315,,,Blink=500;, +SamplerGain,,KnobSlider,B708,,,,,,,,,,, +Slip,,Button,,9116,9316,,,,9116,9316,,,, +Sync,,Button,,9110,9310,,,,9110,9310,,,Blink=600;, +TempoSlider,,KnobSlider,,B12A,B32A,,,,,,,,Fast;,