2
// Pioneer CDJ cd player HID script v0.01
3
// Copyright (C) 2012, Ilkka Tuohela, Sean M. Pappalardo
4
// but feel free to tweak this to your heart's content!
5
// For Mixxx version 1.11.x
8
PioneerCDJHID = new HIDController();
10
// Valid values: 1 for mouse mode, 0 for xy-pad mode
11
PioneerCDJHID.LEDUpdateInterval = undefined;
12
PioneerCDJHID.version_major = undefined;
13
PioneerCDJHID.version_minor = undefined;
16
PioneerCDJHID.deckSwitchClicked = false;
17
PioneerCDJHID.deckSwitchClickTimer = undefined;
19
PioneerCDJHID.LEDColors = { off: 0x0, on: 0x01 }
21
PioneerCDJHID.beatLoopSizeMap = {
22
beatloop_2: '8', beatloop_2_shift: '0.5',
23
beatloop_4: '4', beatloop_4_shift: '0.25',
24
beatloop_8: '2', beatloop_8_shift: '0.125',
25
beatloop_16: '1', beatloop_16_shift: '0.0625'
28
PioneerCDJHID.ignoredControlChanges = [ ];
29
PioneerCDJHID.WheelLEDCount = 0;
30
PioneerCDJHID.ButtonLEDCount = 22;
32
PioneerCDJHID.activeDeck = 1;
35
PioneerCDJHID.scratchintervalsPerRev = 1024;
36
PioneerCDJHID.scratchAlpha = 1.0/8;
37
PioneerCDJHID.rampedScratchEnable = true;
38
PioneerCDJHID.rampedScratchEnable = true;
41
// Functions to modify be end user
44
// Initialize device state
45
PioneerCDJHID.init = function (id) {
46
PioneerCDJHID.id = id;
48
PioneerCDJHID.registerInputPackets();
49
PioneerCDJHID.registerOutputPackets();
50
PioneerCDJHID.registerScalers();
51
PioneerCDJHID.registerCallbacks();
53
PioneerCDJHID.initializeHIDMode();
54
PioneerCDJHID.updateLEDs();
56
PioneerCDJHID.toggleButtons = [ 'play', 'keylock', 'pfl' ]
57
engine.softTakeover('[Channel1]','pregain',true);
58
engine.softTakeover('[Channel2]','pregain',true);
60
if (PioneerCDJHID.LEDUpdateInterval!=undefined) {
61
PioneerCDJHID.LEDTimer = engine.beginTimer(
62
PioneerCDJHID.LEDUpdateInterval,
63
"PioneerCDJHID.updateLEDs(true)"
68
// Device cleanup function
69
PioneerCDJHID.shutdown = function() {
70
if (PioneerCDJHID.LEDTimer!=undefined) {
71
engine.stopTimer(PioneerCDJHID.LEDTimer);
72
PioneerCDJHID.LEDTimer = undefined;
74
script.HIDDebug("Pioneer CDJ Deck "+PioneerCDJHID.id+" shut down");
77
PioneerCDJHID.initializeHIDMode = function() {
78
var packet = PioneerCDJHID.OutputPackets['request_hid_mode'];
79
script.HIDDebug("Sending HID mode init packet");
83
// Mandatory default handler for incoming packets
84
PioneerCDJHID.incomingData = function(data,length) {
85
PioneerCDJHID.parsePacket(data,length);
88
PioneerCDJHID.ignore = function(field) { }
89
PioneerCDJHID.dump = function(field) {
92
+ ' value ' + field.value
93
+ ' delta ' + field.delta
97
// Register value scaling functions
98
PioneerCDJHID.registerScalers = function() {
99
// Register functions to scale value
100
PioneerCDJHID.registerScalingFunction('rate',PioneerCDJHID.pitchScaler);
101
PioneerCDJHID.registerScalingFunction('pregain',PioneerCDJHID.pregainScaler);
102
PioneerCDJHID.registerScalingFunction('jog',PioneerCDJHID.jogScaler);
103
PioneerCDJHID.registerScalingFunction('jog_scratch',PioneerCDJHID.jogPositionDelta);
106
// Register input/output field callback functions
107
PioneerCDJHID.registerCallbacks = function() {
108
PioneerCDJHID.registerInputCallback('control','hid','deck_switch',PioneerCDJHID.deckSwitch);
109
PioneerCDJHID.registerInputCallback('control','deck','beatloop_16',PioneerCDJHID.beatloop);
110
PioneerCDJHID.registerInputCallback('control','deck','beatloop_8',PioneerCDJHID.beatloop);
111
PioneerCDJHID.registerInputCallback('control','deck','beatloop_4',PioneerCDJHID.beatloop);
112
PioneerCDJHID.registerInputCallback('control','deck','beatloop_2',PioneerCDJHID.beatloop);
113
PioneerCDJHID.registerInputCallback('control','deck','jog_direction',PioneerCDJHID.ignore);
114
PioneerCDJHID.registerInputCallback('control','deck','jog_move',PioneerCDJHID.ignore);
115
PioneerCDJHID.registerInputCallback('control','deck','jog_ticks',PioneerCDJHID.ignore);
116
PioneerCDJHID.registerInputCallback('control','deck','needle_search',PioneerCDJHID.dump);
120
// Jog wheel seek event scaler
121
PioneerCDJHID.jogScaler = function(group,name,value) {
125
// Jog wheel scratch event scaler
126
PioneerCDJHID.jogPositionDelta = function(group,name,value) {
130
// Pitch on CDJ sends -1000 to 1000, reset at 0, swap direction
131
PioneerCDJHID.pitchScaler = function(gruop,name,value) {
132
return -(value/1000);
135
// Volume slider scaling for 0..1..5 scaling from 0-255
136
PioneerCDJHID.pregainScaler = function(group,name,value) {
137
return script.absoluteNonLin(value, 0, 1, 5, 0, 256);
140
// Generic unsigned short to -1..0..1 range scaling
141
PioneerCDJHID.plusMinus1Scaler = function(group,name,value) {
143
return value/32768-1;
145
return (value-32768)/32768;
148
PioneerCDJHID.seek_fwd = function (field) {
149
var active_group = PioneerCDJHID.resolveGroup(field.group);
150
if (field.value==PioneerCDJHID.buttonStates.released)
151
engine.setValue(active_group,'fwd',false);
152
if (field.value==PioneerCDJHID.buttonStates.pressed)
153
engine.setValue(active_group,'fwd',true);
156
// Hotcues activated with normal press, cleared with shift
157
PioneerCDJHID.beatloop = function (field) {
159
if (field.value==PioneerCDJHID.buttonStates.released)
161
if (PioneerCDJHID.activeDeck==undefined)
164
var active_group = PioneerCDJHID.resolveGroup(field.group);
165
if (PioneerCDJHID.modifiers['beatloop_size']) {
166
size = PioneerCDJHID.beatLoopSizeMap[field.name+'_shift'] ;
168
size = PioneerCDJHID.beatLoopSizeMap[field.name];
170
var command = 'beatloop_' + size + '_toggle';
171
print ("BEATLOOP SIZE" + active_group + " name " + command);
172
engine.setValue(active_group,command,true);
175
// Use pregain if modifier shift is active, volume otherwise
176
PioneerCDJHID.pregain = function (field) {
177
if (PioneerCDJHID.activeDeck==undefined)
179
var active_group = PioneerCDJHID.resolveGroup(field.group);
181
if (PioneerCDJHID.modifiers['shift']) {
182
value = script.absoluteNonLin(field.value, 0, 1, 5, 0, 65536);
183
engine.setValue(active_group,'pregain',value);
185
value = field.value / 65536;
186
engine.setValue(active_group,'volume',value);
190
// Function called when the special 'Deck Switch' button is pressed
191
PioneerCDJHID.deckSwitch = function(field) {
192
script.HIDDebug('DECK SWITCH pressed');
193
if (field.value == PioneerCDJHID.buttonStates.released) {
194
if (PioneerCDJHID.deckSwitchClicked==false) {
195
PioneerCDJHID.deckSwitchClicked=true;
196
PioneerCDJHID.deckSwitchClickTimer = engine.beginTimer(
197
250,"PioneerCDJHID.deckSwitchClickedClear()"
200
PioneerCDJHID.deckSwitchDoubleClick();
203
// TODO - add code for 'hold deck_switch and press hot_cue[1-4] to select deck 1-4
206
// Timer to clear the double click status for deck switch
207
PioneerCDJHID.deckSwitchClickedClear = function() {
208
PioneerCDJHID.deckSwitchClicked = false;
209
if (PioneerCDJHID.deckSwitchClickTimer!=undefined) {
210
engine.stopTimer(PioneerCDJHID.deckSwitchClickTimer);
211
PioneerCDJHID.deckSwitchClickTimer = undefined;
215
// Function to handle case when 'deck_switch' button was double clicked
216
PioneerCDJHID.deckSwitchDoubleClick = function() {
217
PioneerCDJHID.deckSwitchClicked = false;
218
if (PioneerCDJHID.deckSwitchClickTimer!=undefined) {
219
engine.stopTimer(PioneerCDJHID.deckSwitchClickTimer);
220
PioneerCDJHID.deckSwitchClickTimer = undefined;
222
if (PioneerCDJHID.activeDeck!=undefined)
223
PioneerCDJHID.disconnectDeckLEDs();
224
switch (PioneerCDJHID.activeDeck) {
226
PioneerCDJHID.activeDeck = 2;
227
PioneerCDJHID.setLED('hid','deck_switch','green');
230
PioneerCDJHID.activeDeck = 1;
231
PioneerCDJHID.setLED('hid','deck_switch','red');
234
PioneerCDJHID.activeDeck = 4;
235
PioneerCDJHID.setLED('hid','deck_switch','green');
238
PioneerCDJHID.activeDeck = 3;
239
PioneerCDJHID.setLED('hid','deck_switch','red');
242
PioneerCDJHID.activeDeck = 1;
243
PioneerCDJHID.setLED('hid','deck_switch','red');
246
PioneerCDJHID.connectDeckLEDs();
247
this.updateActiveDeckLEDs();
248
script.HIDDebug('Active CDJ deck now ' + PioneerCDJHID.activeDeck);
251
PioneerCDJHID.activeLEDUpdateWrapper = function() {
252
PioneerCDJHID.updateActiveDeckLEDs();
255
// Initialize control fields, buttons and LEDs
256
// Group name 'deck' is dynamically modified to active deck, since
257
// Otus is a dualdeck controller.
258
PioneerCDJHID.registerInputPackets = function() {
259
var packet = undefined;
260
var name = undefined;
263
// addControl(group,name,offset,pack,bitmask,isEncoder,callback)
264
// Input controller state packet - 'control' is a special name
265
packet = new HIDPacket('control',[],20);
266
packet.addControl('hid','deck_switch',0,'B',0x1);
267
packet.addControl('[Playlist]','SelectPrevTrack',0,'B',0x4);
269
packet.addControl('[Playlist]','SelectNextTrack',0,'B',0x8);
270
packet.addControl('deck','back',0,'B',0x10);
271
packet.addControl('deck','fwd',0,'B',0x20);
272
packet.addControl('deck','cue_default',0,'B',0x40);
273
packet.addControl('deck','play',0,'B',0x80);
275
packet.addControl('deck','reloop_exit',1,'B',0x20);
276
packet.addControl('deck','loop_out',1,'B',0x40);
277
packet.addControl('deck','loop_in',1,'B',0x80);
279
packet.addControl('deck','tempo_mode',2,'B',0x8);
280
packet.addControl('deck','keylock',2,'B',0x10);
281
packet.addControl('deck','loop_halve',2,'B',0x20);
282
packet.addControl('deck','loop_double',2,'B',0x40);
283
packet.addControl('deck','quantize',2,'B',0x80);
285
packet.addControl('deck','pfl',3,'B',0x2);
286
packet.addControl('deck','beatsync',3,'B',0x8);
287
packet.addControl('deck','beats_translate_curpos',3,'B',0x10);
288
packet.addControl('deck','LoadSelectedTrack',3,'B',0x20);
290
packet.addControl('modifiers','beatloop_size',4,'B',0x8);
291
packet.addControl('deck','beatloop_16',4,'B',0x10);
292
packet.addControl('deck','beatloop_8',4,'B',0x20);
293
packet.addControl('deck','beatloop_4',4,'B',0x40);
294
packet.addControl('deck','beatloop_2',4,'B',0x80);
296
packet.addControl('deck','reverse',7,'B',0x1);
297
packet.addControl('deck','jog_touch',7,'B',0x20);
298
packet.addControl('deck','jog_direction',7,'B',0x40);
299
packet.addControl('deck','jog_move',7,'B',0x80);
301
packet.addControl('deck','pregain',8,'B');
302
packet.addControl('[Playlist]','SelectTrackKnob',10,'H',undefined,true);
304
packet.addControl('deck','rate',12,'h');
305
packet.addControl('deck','jog_wheel',14,'h',undefined,true);
306
packet.addControl('deck','jog_ticks',16,'h');
308
packet.addControl('deck','needle_search',18,'h');
310
// Adjust minimum deltas from unstable potentiometers
311
// packet.setMinDelta('deck','pitch',4);
312
// packet.setMinDelta('deck','jog_ticks',4);
313
PioneerCDJHID.registerInputPacket(packet);
316
// Register output packets we send to the controller
317
PioneerCDJHID.registerOutputPackets = function() {
318
var packet = undefined;
319
var name = undefined;
322
// Control packet to initialize HID mode on CDJ
323
packet = new HIDPacket('request_hid_mode',[0x1],0x20);
324
packet.addControl('hid','mode',0,'B',1);
325
PioneerCDJHID.registerOutputPacket(packet);
327
// Control packet for button LEDs
328
packet = new HIDPacket('button_leds',[],20);
329
packet.addLED('deck','previous',0,'B',2);
330
packet.addLED('deck','next',0,'B',3);
331
packet.addLED('deck','cue',0,'B',6);
332
PioneerCDJHID.registerOutputPacket(packet);