home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2011 November
/
CHIP_2011_11.iso
/
Programy
/
Narzedzia
/
Aplikacje_64-bitowe
/
Mixxx
/
mixxx-1.9.0-win64.exe
/
midi
/
Hercules-DJ-Console-Mk2-scripts.js
< prev
next >
Wrap
Text File
|
2011-02-04
|
18KB
|
485 lines
function HerculesMk2 () {}
HerculesMk2.ledOn = 0x7F;
HerculesMk2.ledOff = 0x00;
HerculesMk2.debug = false;
HerculesMk2.scratchMode = false;
HerculesMk2.decayLast = new Date().getTime();
HerculesMk2.decayInterval = 300;
HerculesMk2.decayRate = 1.5;
HerculesMk2.buttons123Modes = ["kill", "fx", "cue", "loop"];
HerculesMk2.buttons123used = {"[Channel1]": false, "[Channel1]": false};
// TODO HerculesMk2 controls should be divided into groups, then signals
// should directed to each group without thinking about specific controls
// to allow for easy rebinding.
HerculesMk2.cueLastDate1 = {"[Channel1]": 0, "[Channel2]" : 0};
HerculesMk2.cueLastDate2 = {"[Channel1]": 0, "[Channel2]" : 0};
HerculesMk2.cueLastDate3 = {"[Channel1]": 0, "[Channel2]" : 0};
HerculesMk2.cueLongTime = 500;
HerculesMk2.controls = {
"inputs": {
0x09: { "channel": 1, "name": "cue", "type": "button" },
0x03: { "channel": 2, "name": "cue", "type": "button" },
0x08: { "channel": 1, "name": "play", "type": "button" },
0x02: { "channel": 2, "name": "play", "type": "button" },
0x07: { "channel": 1, "name": "fx select", "type": "button",
"mode": 0 },
0x01: { "channel": 2, "name": "fx select", "type": "button",
"mode": 0 },
0x0F: { "channel": 1, "name": "fx 1", "type": "button", "used": false },
0x10: { "channel": 2, "name": "fx 1", "type": "button", "used": false },
0x0E: { "channel": 1, "name": "fx 2", "type": "button", "used": false },
0x11: { "channel": 2, "name": "fx 2", "type": "button", "used": false },
0x0D: { "channel": 1, "name": "fx 3", "type": "button", "used": false },
0x12: { "channel": 2, "name": "fx 3", "type": "button", "used": false },
0x1B: { "channel": 1, "name": "mouse", "type": "button" },
0x1C: { "channel": 2, "name": "mouse", "type": "button" },
0x34: { "channel": 1, "name": "pitch", "type": "pot" },
0x35: { "channel": 2, "name": "pitch", "type": "pot" },
0x36: { "channel": 1, "name": "wheel", "type": "pot" },
0x37: { "channel": 2, "name": "wheel", "type": "pot" }
},
"outputs": {
0x0F: { "channel": 1, "name": "fx mode", "type": "led" },
0x10: { "channel": 2, "name": "fx mode", "type": "led" },
0x0E: { "channel": 1, "name": "cue mode", "type": "led" },
0x11: { "channel": 2, "name": "cue mode", "type": "led" },
0x0D: { "channel": 1, "name": "loop mode", "type": "led" },
0x12: { "channel": 2, "name": "loop mode", "type": "led" },
0x16: { "channel": 1, "name": "master tempo", "type": "led" },
0x1A: { "channel": 2, "name": "master tempo", "type": "led" },
0x0A: { "channel": 1, "name": "auto beat", "type": "led" },
0x04: { "channel": 2, "name": "auto beat", "type": "led" },
0x09: { "channel": 1, "name": "cue", "type": "led" },
0x03: { "channel": 2, "name": "cue", "type": "led" },
0x00: { "channel": 1, "name": "play blink", "type": "led" },
0x05: { "channel": 2, "name": "play blink", "type": "led" },
0x08: { "channel": 1, "name": "play", "type": "led" },
0x02: { "channel": 2, "name": "play", "type": "led" }
}
};
HerculesMk2.leds = {
};
HerculesMk2.init = function (id) { // called when the device is opened & set up
HerculesMk2.initializeControls();
engine.connectControl("[Channel1]","playposition","HerculesMk2.wheelDecay");
engine.connectControl("[Channel2]","playposition","HerculesMk2.wheelDecay");
print ("HerculesMk2 id: \""+id+"\" initialized.");
};
HerculesMk2.initializeControls = function () {
for (control in HerculesMk2.controls.outputs) {
if (HerculesMk2.controls.outputs[control].type == 'led') {
key = "[Channel" + HerculesMk2.controls.outputs[control].channel + "] " + HerculesMk2.controls.outputs[control].name;
HerculesMk2.leds[key] = control;
}
}
HerculesMk2.setLeds("on");
HerculesMk2.setLeds("off");
// Set controls in Mixxx to reflect settings on the device
midi.sendShortMsg(0xB0,0x7F,0x7F);
};
HerculesMk2.shutdown = function (id) {
HerculesMk2.setLeds("off");
};
HerculesMk2.getGroup = function (control){
// Get the "group" that used to be provided in group, this is not reusable
// across devices and also breaks remapping of these functions to other
// buttons.
return "[Channel" + HerculesMk2.controls.inputs[control].channel + "]";
};
HerculesMk2.getControl = function (io, channel, name) {
// Accept channel in form 'N' or '[ChannelN]'
channel = channel.replace(/\[Channel(\d)\]/, "$1");
for (control in HerculesMk2.controls.inputs) {
if (HerculesMk2.controls.inputs[control].channel == channel &&
HerculesMk2.controls.inputs[control].name == name
) return HerculesMk2.controls.inputs[control];
}
print ("HerculesMk2.getControl: Control not found: io=" + io + ": channel=" + channel + ": name=" + name);
};
HerculesMk2.setLeds = function (onOff) {
for (LED in HerculesMk2.leds) {
HerculesMk2.setLed(LED,onOff);
// Seems that if midi messages are sent too quickly, leds don't behave
// as expected. A pause rectifies this.
HerculesMk2.pauseScript(10);
}
};
HerculesMk2.setLed = function (led, onOff) {
value = onOff=="on" ? HerculesMk2.ledOn : HerculesMk2.ledOff;
if (HerculesMk2.debug) print ("HerculesMk2.setLed: Setting " + led + " led " + onOff);
if (HerculesMk2.debug) print ("HerculesMk2.setLed: midi.sendShortMsg(0xB0," + HerculesMk2.leds[led].toString(16) + "," + value + ")");
midi.sendShortMsg(0xB0,HerculesMk2.leds[led],value);
HerculesMk2.controls.outputs[HerculesMk2.leds[led]].isOn = onOff=="on" ? true : false;
};
HerculesMk2.pauseScript = function(ms) {
startDate = new Date();
currentDate = null;
while(currentDate-startDate < ms) currentDate = new Date();
};
HerculesMk2.pfl = function (group, control, value, status) {
if (value) { // Act on given mode being selected, not deselected.
if (HerculesMk2.debug) print("HerculesMk2.pfl: " + control.toString(16) + " " + value.toString(16));
switch (control) {
case 0x23: // Headphones Split
case 0x24: // Headphones Mix
if (HerculesMk2.debug) print("HerculesMk2.pfl: Mix/Split");
engine.setValue("[Channel1]", "pfl", 1);
engine.setValue("[Channel2]", "pfl", 1);
break;
case 0x21: // Headphones Deck A
if (HerculesMk2.debug) print("HerculesMk2.pfl: Deck A");
engine.setValue("[Channel1]", "pfl", 1);
engine.setValue("[Channel2]", "pfl", 0);
break;
case 0x22: // Headphones Deck B
if (HerculesMk2.debug) print("HerculesMk2.pfl: Deck B");
engine.setValue("[Channel1]", "pfl", 0);
engine.setValue("[Channel2]", "pfl", 1);
}
}
};
HerculesMk2.cue = function (group, control, value, status) {
group = HerculesMk2.getGroup(control);
if ((engine.getValue(group, "duration") == 0) && (value)) {
print("No song on " + group);
return;
}
if (value) { // Down
engine.setValue(group,"cue_default",1);
HerculesMk2.setLed(group + " cue", "on");
} else { // Release
engine.setValue(group,"cue_default",0);
}
};
HerculesMk2.play = function (group, control, value, status) {
if (value) { // Only do stuff when play is pushed, not released.
group = HerculesMk2.getGroup(control);
if (engine.getValue(group, "duration") == 0) {
print("No song on " + group);
return;
}
engine.setValue(group,"play", !engine.getValue(group,"play"));
HerculesMk2.setLed(group + " cue", "off");
}
};
HerculesMk2.loadSelectedTrack = function (group, control, value, status) {
if (value) { // Only do stuff when pushed, not released.
group = HerculesMk2.getGroup(control);
engine.setValue(group, "LoadSelectedTrack", 1);
HerculesMk2.setLed(group + " cue", "on");
}
};
HerculesMk2.buttons123 = function (group, control, value, status) {
group = HerculesMk2.getGroup(control);
if (value) { // Button pressed.
HerculesMk2.controls.inputs[control].isDown = true;
} else { //Button released.
HerculesMk2.controls.inputs[control].isDown = false;
}
mode = HerculesMk2.getControl("inputs", group, "fx select").mode;
mode = HerculesMk2.buttons123Modes[mode];
switch (mode) {
case "kill": // Kill mode
if (value) { // Button pressed.
switch (HerculesMk2.controls.inputs[control].name) {
case "fx 1":
engine.setValue(group, "filterLowKill", !engine.getValue(group, "filterLowKill"));
break;
case "fx 2":
engine.setValue(group, "filterMidKill", !engine.getValue(group, "filterMidKill"));
break;
case "fx 3":
engine.setValue(group, "filterHighKill", !engine.getValue(group, "filterHighKill"));
break;
}
}
break; // End kill mode
case "fx": // Fx mode
// Were only turning off the flanger if any of the 123 buttons are
// released, not pushed. This is so we can have any of the 123 buttons
// held down, then use the pitch pot to modify the effect settings
if (!value) { // Button released.
if (HerculesMk2.controls.inputs[control].used) {
// Button was used to turn the pitch control into a modifier
// for the effect settings, so don't go on and turn the flanger
// on/off
HerculesMk2.controls.inputs[control].used = false;
return;
}
switch (HerculesMk2.controls.inputs[control].name) {
case "fx 1":
case "fx 2":
case "fx 3":
engine.setValue(group, "flanger", !engine.getValue(group, "flanger"));
break;
}
}
break; // End fx mode
case "cue":
if (value){
switch (HerculesMk2.controls.inputs[control].name) {
case "fx 1":
HerculesMk2.cueLastDate1[group] = new Date().getTime();
break;
case "fx 2":
HerculesMk2.cueLastDate2[group] = new Date().getTime();
break;
case "fx 3":
HerculesMk2.cueLastDate3[group] = new Date().getTime();
break;
}
}
if (!value){
currentDate = new Date().getTime();
switch (HerculesMk2.controls.inputs[control].name) {
case "fx 1":
if (currentDate - HerculesMk2.cueLastDate1[group] < HerculesMk2.cueLongTime)
engine.setValue(group,"hotcue_1_activate",1)
else
engine.setValue(group,"hotcue_1_clear",1)
break;
case "fx 2":
if (currentDate - HerculesMk2.cueLastDate2[group] < HerculesMk2.cueLongTime)
engine.setValue(group,"hotcue_2_activate",1)
else
engine.setValue(group,"hotcue_2_clear",1)
break;
case "fx 3":
if (currentDate - HerculesMk2.cueLastDate3[group] < HerculesMk2.cueLongTime)
engine.setValue(group,"hotcue_3_activate",1)
else
engine.setValue(group,"hotcue_3_clear",1)
break;
}
}
break;
case "loop":
if (value) { // Button pressed.
switch (HerculesMk2.controls.inputs[control].name) {
case "fx 1": // "fx 1,2,3" should be globally renamed as said before?...
// trigger loop in
engine.setValue(group,"loop_in", !engine.getValue(group,"start")); // Am I correct?
break;
case "fx 2":
// trigger loop out
engine.setValue(group,"loop_out", !engine.getValue(group,"end")); // Am I correct?
break;
case "fx 3":
// trigger loop exit
engine.setValue(group,"reloop_exit", !engine.getValue(group,"loop")); // Am I correct?
break;
}
}
break;
default:
print("HerculesMk2.buttons123: " + mode + " mode unsupported");
}
};
HerculesMk2.buttons123mode = function (group, control, value, status) {
group = HerculesMk2.getGroup(control);
if (value) { // Only do stuff when pushed, not released.
currentMode = HerculesMk2.controls.inputs[control].mode;
nextMode = currentMode < HerculesMk2.buttons123Modes.length-1 ? currentMode+1 : 0;
currentLed = group + " " + HerculesMk2.buttons123Modes[currentMode] + " mode";
nextLed = group + " " + HerculesMk2.buttons123Modes[nextMode] + " mode";
sNextMode = HerculesMk2.buttons123Modes[nextMode];
switch (sNextMode) {
case "kill":
case "fx":
print("HerculesMk2.buttons123mode: Switching to " + sNextMode + " mode");
break;
case "cue":
print("HerculesMk2.buttons123mode: Switching to " + sNextMode + " mode");
break;
case "loop":
print("HerculesMk2.buttons123mode: Switching to " + sNextMode + " mode");
break;
default:
print("HerculesMk2.buttons123mode: Switching to " + sNextMode + " mode");
}
// Only turn on/off leds for non-zero modes as 0 is kill mode which
// has no corresponding LED. i.e. all LEDs off for kill mode.
if (currentMode) HerculesMk2.setLed(currentLed, "off");
// Seems that if midi messages are sent too quickly, leds don't behave
// as expected. A pause rectifies this.
HerculesMk2.pauseScript(10);
if (nextMode) HerculesMk2.setLed(nextLed, "on");
HerculesMk2.controls.inputs[control].mode = nextMode;
}
};
HerculesMk2.pitch = function (group, control, value, status) {
// 7F > 40: CCW Slow > Fast - 127 > 64
// 01 > 3F: CW Slow > Fast - 0 > 63
group = HerculesMk2.getGroup(control);
pitchControl = HerculesMk2.getControl("inputs", group, "pitch");
done = false;
currentMode = HerculesMk2.getControl("inputs", group, "fx select").mode;
currentMode = HerculesMk2.buttons123Modes[currentMode];
// If in fx mode and one or more of buttons 123 are pressed, use pitch
// pot to adjust the relevant flanger parameters instead of changing
// the rate (as is normal operation for the pitch pot)
if (currentMode == "fx") {
potStep = 25; // How many clicks round the pot from min to max values
if (HerculesMk2.getControl("inputs", group, "fx 1").isDown) {
min = 0; max = 1;
increment = (max-min)/potStep;
increment = (value <= 0x3F) ? increment : increment * -1;
currentValue = engine.getValue("[Flanger]", "lfoDepth");
newValue = currentValue + increment;
newValue = newValue > max ? max : newValue < min ? min : newValue;
if (HerculesMk2.debug) print ("HerculesMk2.pitch: value= " + newValue);
if (newValue != currentValue)
engine.setValue("[Flanger]", "lfoDepth", newValue);
HerculesMk2.getControl("inputs", group, "fx 1").used = true;
done = true;
}
if (HerculesMk2.getControl("inputs", group, "fx 2").isDown) {
min = 50; max = 10000;
increment = (max-min)/potStep;
increment = (value <= 0x3F) ? increment : increment * -1;
currentValue = engine.getValue("[Flanger]", "lfoDelay");
newValue = currentValue + increment;
newValue = newValue > max ? max : newValue < min ? min : newValue;
if (HerculesMk2.debug) print ("HerculesMk2.pitch: value= " + newValue);
if (newValue != currentValue)
engine.setValue("[Flanger]", "lfoDelay", newValue);
HerculesMk2.getControl("inputs", group, "fx 2").used = true;
done = true;
}
if (HerculesMk2.getControl("inputs", group, "fx 3").isDown) {
min = 50000; max = 2000000
increment = (max-min)/potStep;
increment = (value <= 0x3F) ? increment : increment * -1;
currentValue = engine.getValue("[Flanger]", "lfoPeriod");
newValue = currentValue + increment;
newValue = newValue > max ? max : newValue < min ? min : newValue;
if (HerculesMk2.debug) print ("HerculesMk2.pitch: value= " + newValue);
if (newValue != currentValue)
engine.setValue("[Flanger]", "lfoPeriod", newValue);
HerculesMk2.getControl("inputs", group, "fx 3").used = true;
done = true;
}
}
if (done) return;
increment = 0.016;
increment = (value <= 0x3F) ? increment : increment * -1;
if (HerculesMk2.debug) print ("HerculesMk2.pitch: value=" + value);
engine.setValue(group, "rate", engine.getValue(group, "rate") + increment);
};
HerculesMk2.jog_wheel = function (group, control, value, status) {
// 7F > 40: CCW Slow > Fast - 127 > 64
// 01 > 3F: CW Slow > Fast - 0 > 63
group = HerculesMk2.getGroup(control);
if (HerculesMk2.controls.outputs[HerculesMk2.leds[group + " cue"]].isOn == true) {
HerculesMk2.setLed(group + " cue", "off");
}
jogValue = value >=0x40 ? value - 0x80 : value; // -64 to +63, - = CCW, + = CW
if (HerculesMk2.scratchMode) { // do some scratching
if (HerculesMk2.debug) print("Do scratching value:" + value + " jogValue: " + jogValue );
engine.setValue(group,"scratch", (engine.getValue(group,"scratch") + (jogValue/64)).toFixed(2));
} else { // do pitch adjustment
newValue = jogValue;
if (HerculesMk2.debug) print("do pitching adjust " + jogValue + " new Value: " + newValue);
engine.setValue(group,"jog", newValue);
}
};
HerculesMk2.wheelDecay = function (value) {
currentDate = new Date().getTime();
if (currentDate > HerculesMk2.decayLast + HerculesMk2.decayInterval) {
HerculesMk2.decayLast = currentDate;
if (HerculesMk2.debug) print(" new playposition: " + value + " decayLast: "+ HerculesMk2.decayLast);
if (HerculesMk2.scratchMode) { // do some scratching
if (HerculesMk2.debug) print("Scratch deck1: " + engine.getValue("[Channel1]","scratch") + " deck2: "+ engine.getValue("[Channel2]","scratch"));
jog1DecayRate = HerculesMk2.decayRate * (engine.getValue("[Channel1]","play") ? 1 : 5);
jog1 = engine.getValue("[Channel1]","scratch");
if (jog1 != 0) {
if (Math.abs(jog1) > jog1DecayRate) {
engine.setValue("[Channel1]","scratch", (jog1 / jog1DecayRate).toFixed(2));
} else {
engine.setValue("[Channel1]","scratch", 0);
}
}
jog2DecayRate = HerculesMk2.decayRate * (engine.getValue("[Channel2]","play") ? 1 : 5);
jog2 = engine.getValue("[Channel2]","scratch");
if (jog2 != 0) {
if (Math.abs(jog2) > jog2DecayRate) {
engine.setValue("[Channel2]","scratch", (jog2 / jog2DecayRate).toFixed(2));
} else {
engine.setValue("[Channel2]","scratch", 0);
}
}
}
}
};