Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slip button, tap tempo, strip search, FX button extras #1

Merged
merged 11 commits into from
Apr 12, 2018
211 changes: 165 additions & 46 deletions res/controllers/Roland_DJ-202-scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ DJ202.tempoRange = [0.08, 0.16, 0.5]

DJ202.init = function () {

DJ202.shiftButton = function (channel, control, value, status, group) {
DJ202.deck.concat(DJ202.effectUnit).forEach(
value
? function (module) { module.shift(); }
: function (module) { module.unshift(); }
);
};

DJ202.leftDeck = new DJ202.Deck([1,3], 0);
DJ202.rightDeck = new DJ202.Deck([2,4], 1);

DJ202.deck = [DJ202.leftDeck, DJ202.rightDeck];

DJ202.effectUnit = [];
DJ202.effectUnit[1] = new DJ202.EffectUnit(1);
DJ202.effectUnit[2] = new DJ202.EffectUnit(2);
Expand All @@ -21,16 +30,22 @@ DJ202.shutdown = function () {
};

DJ202.browseEncoder = new components.Encoder({
midi: [0xBF, 0x00],
group: '[Playlist]',
inKey: 'SelectTrackKnob',
input: function (channel, control, value, status, group) {
if (value === 1) {
this.inSetParameter(1);
} else if (value === 127) {
this.inSetParameter(-1);
var isShifted = control % 2 != 0;
switch (status) {
case 0xBF: // Rotate.
if (value === 1) {
script.triggerControl(group, isShifted ? 'ScrollUp' : 'MoveUp');
} else if (value === 127) {
script.triggerControl(group, isShifted ? 'ScrollDown' : 'MoveDown');
}
break;
case 0x9F: // Push.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could add a way to open/close tree leaves. Eg. Push: Move focus
Shift+Push in tree view: Open leaf
Shift+Push in playlist view: Load track into preview deck

Or we could use the load buttons, as they're not used in the tree view.

if (value) {
script.triggerControl(group, isShifted ? 'MoveFocusBackward' : 'MoveFocusForward');
}
}
},
}
});

DJ202.crossfader = new components.Pot({
Expand All @@ -43,14 +58,6 @@ DJ202.Deck = function (deckNumbers, offset) {
components.Deck.call(this, deckNumbers);
channel = offset+1;

this.shiftButton = function (channel, control, value, status, group) {
if (value === 127) {
this.shift();
} else {
this.unshift();
}
};

this.loadTrack = new components.Button({
midi: [0x9F, 0x02 + offset],
unshift: function () {
Expand All @@ -61,6 +68,34 @@ DJ202.Deck = function (deckNumbers, offset) {
},
});

this.paramUp = function (channel, control, value, status, group) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the MIDI control is supplied, paramUp and paramDown could probably be merged into one binding.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now that's true. We'd probably have to rethink this in case we want to use them for layering the performance pads #5

if (value) {
this.paramUp.active = true;
if (this.paramDown.active) {
script.triggerControl(group, 'reset_key');
} else if (this.keylock.is_held) {
var adjust = engine.getValue(group, 'pitch_adjust');
engine.setValue(group, 'pitch_adjust', Math.min(7, adjust + 1));
}
} else {
this.paramUp.active = false;
}
};

this.paramDown = function (channel, control, value, status, group) {
if (value) {
this.paramDown.active = true;
if (this.paramUp.active) {
script.triggerControl(group, 'reset_key');
} else if (this.keylock.is_held) {
var adjust = engine.getValue(group, 'pitch_adjust');
engine.setValue(group, 'pitch_adjust', Math.max(-7, adjust - 1));
}
} else {
this.paramDown.active = false;
}
};

this.keylock = new components.Button({
midi: [0x90 + offset, 0x0D],
shiftOffset: 1,
Expand All @@ -69,9 +104,25 @@ DJ202.Deck = function (deckNumbers, offset) {
outKey: 'keylock',
currentRangeIndex: 0,
unshift: function () {
this.type = components.Button.prototype.types.toggle;
this.input = components.Button.prototype.input;
this.input = function (channel, control, value, status, group) {
if (value) {
this.longPressTimer = engine.beginTimer(this.longPressTimeout, function () {
this.is_held = true;
}, true);
} else {
if (!this.is_held) {
script.toggleControl(this.group, this.outKey);
};
engine.stopTimer(this.longPressTimer);
this.is_held = false;
}
};
this.inKey = 'keylock';
this.outKey = 'keylock';
// The DJ-202 disables the keylock LED when the button is pressed
// shifted. Restore the LED when shift is released.
this.send(this.outGetValue());
midi.sendShortMsg(0x84, 0x00, 0x3);
},
shift: function () {
this.inKey = 'rateRange';
Expand All @@ -98,7 +149,7 @@ DJ202.Deck = function (deckNumbers, offset) {

// ============================= JOG WHEELS =================================
this.wheelTouch = function (channel, control, value, status, group) {
if (value === 0x7F) {
if (value === 0x7F && !this.isShifted) {
var alpha = 1.0/8;
var beta = alpha/32;
engine.scratchEnable(script.deckFromGroup(this.currentDeck), 512, 45, alpha, beta);
Expand All @@ -109,8 +160,14 @@ DJ202.Deck = function (deckNumbers, offset) {

this.wheelTurn = function (channel, control, value, status, group) {
var newValue = value - 64;
if (engine.isScratching(1)) {
engine.scratchTick(script.deckFromGroup(this.currentDeck), newValue); // Scratch!
var deck = script.deckFromGroup(this.currentDeck);
if (engine.isScratching(deck)) {
engine.scratchTick(deck, newValue); // Scratch!
} else if (this.isShifted) {
// Strip search.
var oldPos = engine.getValue(this.currentDeck, 'playposition');
var newPos = Math.max(0, oldPos + newValue / 0xff);
engine.setValue(this.currentDeck, 'playposition', newPos);
} else {
engine.setValue(this.currentDeck, 'jog', newValue); // Pitch bend
}
Expand Down Expand Up @@ -198,7 +255,24 @@ DJ202.Deck = function (deckNumbers, offset) {
type: components.Button.prototype.types.toggle,
inKey: 'pfl',
outKey: 'pfl',
// missing: shift -> TAP
});

this.tapBPM = new components.Button({
input: function (channel, control, value, status, group) {
if (value == 127) {
script.triggerControl(group, 'beats_translate_curpos');
bpm.tapButton(script.deckFromGroup(group));
this.longPressTimer = engine.beginTimer(
this.longPressTimeout,
function () {
script.triggerControl(group, 'beats_translate_match_alignment');
},
true
);
} else {
engine.stopTimer(this.longPressTimer);
}
}
});

this.volume = new components.Pot({
Expand Down Expand Up @@ -226,6 +300,20 @@ DJ202.EffectUnit = function (unitNumber) {
this.group = '[EffectRack1_EffectUnit' + unitNumber + ']';
engine.setValue(this.group, 'show_focus', 1);

this.shift = function () {
this.button.forEach(function (button) {
button.shift();
});
this.knob.shift();
};

this.unshift = function () {
this.button.forEach(function (button) {
button.unshift();
});
this.knob.unshift();
};

this.EffectButton = function (buttonNumber) {
this.buttonNumber = buttonNumber;

Expand All @@ -235,33 +323,41 @@ DJ202.EffectUnit = function (unitNumber) {
components.Button.call(this);
};
this.EffectButton.prototype = new components.Button({
input: function (channel, control, value, status) {
if (this.isPress(channel, control, value, status)) {
this.isLongPressed = false;
this.longPressTimer = engine.beginTimer(this.longPressTimeout, function () {
var effectGroup = '[EffectRack1_EffectUnit' + unitNumber + '_Effect' + this.buttonNumber + ']';
script.toggleControl(effectGroup, 'enabled');
this.isLongPressed = true;
}, true);
} else {
if (!this.isLongPressed) {
var focusedEffect = engine.getValue(eu.group, 'focused_effect');
if (focusedEffect === this.buttonNumber) {
engine.setValue(eu.group, 'focused_effect', 0);
} else {
engine.setValue(eu.group, 'focused_effect', this.buttonNumber);
unshift: function() {
this.input = function (channel, control, value, status) {
if (this.isPress(channel, control, value, status)) {
this.isLongPressed = false;
this.longPressTimer = engine.beginTimer(this.longPressTimeout, function () {
var effectGroup = '[EffectRack1_EffectUnit' + unitNumber + '_Effect' + this.buttonNumber + ']';
script.toggleControl(effectGroup, 'enabled');
this.isLongPressed = true;
}, true);
} else {
if (!this.isLongPressed) {
var focusedEffect = engine.getValue(eu.group, 'focused_effect');
if (focusedEffect === this.buttonNumber) {
engine.setValue(eu.group, 'focused_effect', 0);
} else {
engine.setValue(eu.group, 'focused_effect', this.buttonNumber);
}
}
this.isLongPressed = false;
engine.stopTimer(this.longPressTimer);
}
this.isLongPressed = false;
engine.stopTimer(this.longPressTimer);
}
this.outKey = 'focused_effect';
this.output = function (value, group, control) {
this.send((value === this.buttonNumber) ? this.on : this.off);
};
this.sendShifted = true;
this.shiftOffset = 0x0B;
},
outKey: 'focused_effect',
output: function (value, group, control) {
this.send((value === this.buttonNumber) ? this.on : this.off);
},
sendShifted: true,
shiftOffset: 0x0B,
shift: function () {
this.input = function (channel, control, value, status) {
var group = '[EffectRack1_EffectUnit' + unitNumber + '_Effect' + this.buttonNumber + ']';
script.toggleControl(group, 'next_effect');
};
}
});

this.button = [];
Expand All @@ -273,6 +369,23 @@ DJ202.EffectUnit = function (unitNumber) {
engine.softTakeover(eu.group, 'mix', true);
}

this.headphones = new components.Button({
group: '[EffectRack1_EffectUnit' + unitNumber + ']',
midi: [0x98, 0x04],
unshift: function() {
this.outKey = 'group_[Headphone]_enable';
this.inKey = this.outKey;
this.input = function (channel, control, value, status) {
// FIXME Trigger *after* release, to work-around the device
// disabling the LED on release. Refactor this once a customized
// ‘Button’ class is available.
if (!value) {
script.toggleControl(this.group, this.outKey);
};
};
}
});

this.knob = new components.Pot({
unshift: function () {
this.input = function (channel, control, value, status) {
Expand All @@ -287,6 +400,12 @@ DJ202.EffectUnit = function (unitNumber) {
}
};
},
shift: function() {
this.input = function (channel, control, value, status) {
var group = '[EffectRack1_EffectUnit' + unitNumber + ']';
engine.setParameter(group, 'super1', value / 0x7f);
}
}
});

this.knobSoftTakeoverHandler = engine.makeConnection(eu.group, 'focused_effect', function (value, group, control) {
Expand Down
Loading