diff options
Diffstat (limited to 'res/controllers/Behringer-CMDStudio4a-scripts.js')
-rw-r--r-- | res/controllers/Behringer-CMDStudio4a-scripts.js | 548 |
1 files changed, 274 insertions, 274 deletions
diff --git a/res/controllers/Behringer-CMDStudio4a-scripts.js b/res/controllers/Behringer-CMDStudio4a-scripts.js index 54046b8cf7..211bf30491 100644 --- a/res/controllers/Behringer-CMDStudio4a-scripts.js +++ b/res/controllers/Behringer-CMDStudio4a-scripts.js @@ -1,274 +1,274 @@ -// ****************************************************************************
-// * Mixxx mapping script file for the Behringer CMD Studio 4a.
-// * Author: Craig Easton
-// * Version 1.4 (Jan 2016)
-// * Forum: http://www.mixxx.org/forums/viewtopic.php?f=7&t=7868
-// * Wiki: http://www.mixxx.org/wiki/doku.php/behringer_cmd_studio_4a
-// ****************************************************************************
-
-////////////////////////////////////////////////////////////////////////
-// JSHint configuration //
-////////////////////////////////////////////////////////////////////////
-/* global engine */
-/* global script */
-/* global print */
-/* global midi */
-////////////////////////////////////////////////////////////////////////
-
-// Master function definition.
-function BehringerCMDStudio4a() {}
-
-
-// ***************************** Global Vars **********************************
-
-// Shift/mode state variables.
-BehringerCMDStudio4a.delButtonState = [false,false,false,false];
-BehringerCMDStudio4a.scratchButtonState = [false,false,false,false];
-
-// Button push/release state variables.
-BehringerCMDStudio4a.pitchPushed = [[false,false,false,false], [false,false,false,false]];
-BehringerCMDStudio4a.delPushed = false;
-BehringerCMDStudio4a.delShiftUsed = false;
-BehringerCMDStudio4a.fxAssignPushed = false;
-BehringerCMDStudio4a.fxAssignShiftUsed = false;
-BehringerCMDStudio4a.fxAssignLastGroup = "";
-
-// ************************ Initialisation stuff. *****************************
-
-BehringerCMDStudio4a.vuMeterUpdate = function (value, group, control){
- value = (value*15)+48;
- switch(control) {
- case "VuMeterL":
- midi.sendShortMsg(0xB0, 0x7E, value);
- break;
- case "VuMeterR":
- midi.sendShortMsg(0xB0, 0x7F, value);
- break;
- }
-}
-
-BehringerCMDStudio4a.initLEDs = function () {
- // (re)Initialise any LEDs that are direcctly controlled by this script.
- // DEL buttons (one for each virtual deck).
- midi.sendShortMsg(0x90, 0x2A, 0x00);
- midi.sendShortMsg(0x91, 0x4A, 0x00);
- midi.sendShortMsg(0x92, 0x2A, 0x00);
- midi.sendShortMsg(0x93, 0x4A, 0x00);
- // Scratch buttons (one for each virtual deck).
- midi.sendShortMsg(0x90, 0x16, 0x00);
- midi.sendShortMsg(0x91, 0x36, 0x00);
- midi.sendShortMsg(0x92, 0x16, 0x00);
- midi.sendShortMsg(0x93, 0x36, 0x00);
-}
-
-BehringerCMDStudio4a.init = function () {
- // Initialise anything that might not be in the correct state.
- BehringerCMDStudio4a.initLEDs();
- // Connect the VUMeters
- engine.connectControl("[Master]","VuMeterL","BehringerCMDStudio4a.vuMeterUpdate");
- engine.connectControl("[Master]","VuMeterR","BehringerCMDStudio4a.vuMeterUpdate");
-}
-
-BehringerCMDStudio4a.shutdown = function() {
- // Leave the deck in a properly initialised state.
- BehringerCMDStudio4a.initLEDs();
-
- // Disconnect the VUMeters.
-// Maybe not! It seems you don't have to do this even though the connection
-// in done in init(), in fact if you try it throws an error.
-// engine.connectControl("[Master]","VuMeterL","BehringerCMDStudio4a.vuMeterUpdate",true);
-// engine.connectControl("[Master]","VuMeterR","BehringerCMDStudio4a.vuMeterUpdate",true);
-}
-
-
-// *************************** Control Stuff. *********************************
-// The code below is primarily "shift/mode" key functionality as there is no
-// native support for this in Mixxx at the moment.
-// I suspect that the vast majority of controller mappings could be completed
-// with little or no scripting if Mixxx supported shift/mode buttons in the
-// XML (together with standard wheel/scratching functionality).
-
-// Function to deal with the DEL "shift/mode" buttons.
-BehringerCMDStudio4a.del = function (channel, control, value, status, group) {
- if (value == 127) {
- // Button pushed.
- BehringerCMDStudio4a.delPushed = true;
- BehringerCMDStudio4a.delShiftUsed = false;
- } else {
- // Button released.
- BehringerCMDStudio4a.delPushed = false;
- // Only toggle the DEL-mode if the "shift" function wasn't used.
- if (!BehringerCMDStudio4a.delShiftUsed) {
- BehringerCMDStudio4a.delButtonState[channel] = !BehringerCMDStudio4a.delButtonState[channel];
- midi.sendShortMsg(0x90 + channel, control, BehringerCMDStudio4a.delButtonState[channel] ? 0x01 : 0x00);
- }
- }
-}
-
-// Function to deal with the play buttons, (because they have a DEL-mode behaviour).
-BehringerCMDStudio4a.play = function (channel, control, value, status, group) {
- if (BehringerCMDStudio4a.delButtonState[channel]) {
- // DEL-mode is active, do reverse-roll (slip).
- engine.setValue(group, "reverseroll", (value == 127) ? 1 : 0);
- } else {
- // DEL-mode is not active, just toggle play (on push only).
- if (value == 127) {
- script.toggleControl(group,"play");
- }
- }
-}
-
-// Function to deal with the cue buttons, (because they have a DEL-mode behaviour).
-BehringerCMDStudio4a.cue = function (channel, control, value, status, group) {
- if (BehringerCMDStudio4a.delButtonState[channel]) {
- // DEL-mode is active, do reverse play.
- engine.setValue(group, "reverse", (value == 127) ? 1 : 0);
- } else {
- // DEL-mode is not active so just cue.
- engine.setValue(group, "cue_default", (value == 127) ? 1 : 0);
- }
-}
-
-// Function to deal with the scratch mode buttons.
-BehringerCMDStudio4a.scratch = function (channel, control, value, status, group) {
- BehringerCMDStudio4a.scratchButtonState[channel] = !BehringerCMDStudio4a.scratchButtonState[channel];
- midi.sendShortMsg(status, control, BehringerCMDStudio4a.scratchButtonState[channel] ? 0x01 : 0x00);
-}
-
-// Function to deal with the FX Assign buttons, (because they also act as "shift" buttons).
-BehringerCMDStudio4a.fxAssign = function (channel, control, value, status, group) {
- // FX Assign buttons start at 0x52.
- var fxAssignButton = (control - 0x52) & 1; // Either 0 or 1 depending on button (1 or 2).
- if (value == 127) {
- // Button pushed.
- BehringerCMDStudio4a.fxAssignPushed = true;
- BehringerCMDStudio4a.fxAssignShiftUsed = false;
- BehringerCMDStudio4a.fxAssignLastGroup = group;
- }
- else
- {
- // Button released.
- BehringerCMDStudio4a.fxAssignPushed = false;
- // Only toggle the effect on release if the "shift" function wasn't used.
- if (!BehringerCMDStudio4a.fxAssignShiftUsed) {
- script.toggleControl(group,"group_[Channel"+(channel+1)+"]_enable");
- }
- }
-}
-
-// Function to deal with the browse left/right buttons, (because they have an "FX Assign mode" behaviour).
-BehringerCMDStudio4a.browseLR = function (channel, control, value, status, group) {
- if (BehringerCMDStudio4a.fxAssignPushed) {
- BehringerCMDStudio4a.fxAssignShiftUsed = true;
- if (control == 0x2) {
- // Left.
- engine.setValue(BehringerCMDStudio4a.fxAssignLastGroup,"prev_chain", 1);
- } else {
- // Right.
- engine.setValue(BehringerCMDStudio4a.fxAssignLastGroup,"next_chain", 1);
- }
- } else {
- if (control == 0x2) {
- // Left.
- engine.setValue(group, "SelectPrevPlaylist",1)
- } else {
- // Right.
- engine.setValue(group, "SelectNextPlaylist",1)
- }
- }
-}
-
-// Functions to deal with the hot-cue buttons, (because they have a DEL-mode behaviour).
-BehringerCMDStudio4a.hotcue = function (channel, control, value, status, group) {
- // Translate the button to the actual hotcue.
- var hotcue = control-0x21; // Hotcue buttons on left deck go from 0x22 to 0x29
- if (hotcue>8) {
- // Right deck, buttons are 0x20 higher so we need to compensate.
- hotcue = hotcue-0x20;
- }
- if (BehringerCMDStudio4a.delPushed) {
- // DEL button is being held so delete the hotcue.
- engine.setValue(group, "hotcue_"+hotcue+"_clear", 1);
- BehringerCMDStudio4a.delShiftUsed = true;
- } else {
- // DEL button is not being held down.
- if (BehringerCMDStudio4a.delButtonState[channel]) {
- // DEL-mode is active, lets do auto-loops.
- engine.setValue(group, "beatloop_"+(1/8)*Math.pow(2,hotcue-1)+"_toggle", 1);
- if (value == 0) {
- // Button is being released. Disable then re-enable slip if it
- // is active. This "re-syncs" the playback after every
- // auto-loop in slip-mode which is a nice effect and probably
- // what you want most of the time if slip is on.
- if (engine.getValue(group, "slip_enabled") == 1) {
- engine.setValue(group, "slip_enabled", 0);
- // It seems we can't just flip a param off and on in the
- // same call! Since we've just turned slip off, I can't now
- // turn it on directly here, the only work-around I could
- // think of was to create a (very short) timed call-back
- // to turn it off!
- // Raised bug about this:
- // https://bugs.launchpad.net/mixxx/+bug/1538200
- // Changed timer from 50 to 100 after the pathology of this
- // bug was explined in the bug report.
- engine.beginTimer(100, function() { engine.setValue(group, "slip_enabled", 1); }, 1);
- }
- }
- } else {
- // DEL-mode is not active so do the set/jump-to hotcue function as normal.
- engine.setValue(group, "hotcue_"+hotcue+"_activate", (value == 127) ? 1 : 0);
- }
- }
-}
-
-// Functions to deal with the pitch inc/dec buttons, (because they have a DEL-mode behaviour).
-BehringerCMDStudio4a.pitch = function (channel, control, value, status, group) {
- // Work out the direction.
- var direction = ((control & 0x01) == 0) ? "down" : "up";
- // Work out the type (and join) by looking at the DEL button state.
- var type = BehringerCMDStudio4a.delButtonState[channel] ? "pitch" : "rate";
- var join = BehringerCMDStudio4a.delButtonState[channel] ? "" : "_perm";
- // Pushed or released?
- if (value == 127) {
- // Button pushed.
- BehringerCMDStudio4a.pitchPushed[control & 0x01][channel] = true;
- // Is the other button pushed too?
- if (BehringerCMDStudio4a.pitchPushed[(~control) & 0x01][channel]) {
- engine.setValue(group, type, 0); // Yep! reset the control.
- } else {
- engine.setValue(group, type+join+"_"+direction, 1);
- }
- } else {
- // Button released.
- BehringerCMDStudio4a.pitchPushed[control & 0x01][channel] = false;
- engine.setValue(group, "rate_perm_"+direction, 0); // Keeps the UI in sync with the button state.
- }
-}
-
-// Functions to deal with the wheel (i.e. scratcing and jog).
-// Why is there no (XML) support in Mixxx for this most basic of functions?
-// I suspect the vast majority of controller mappings use the same code
-// (provided in the Wiki).
-BehringerCMDStudio4a.wheelTouch = function (channel, control, value, status, group) {
- channel = channel+1;
- if (value > 0) {
- // We're touching the wheel.
- var alpha = 1.0/8;
- var beta = alpha/32;
- engine.scratchEnable(channel, 600, 33+1/3, alpha, beta);
- } else {
- // We've released the wheel.
- engine.scratchDisable(channel);
- }
-};
-BehringerCMDStudio4a.wheelTurn = function (channel, control, value, status, group) {
- var deck = channel+1;
- var newValue = value-64;
- if (BehringerCMDStudio4a.scratchButtonState[channel]){
- if (engine.isScratching(deck)){
- engine.scratchTick(deck,newValue); // Scratch!
- }
- } else {
- engine.setValue(group, "jog", newValue); // Jog.
- }
-};
+// **************************************************************************** +// * Mixxx mapping script file for the Behringer CMD Studio 4a. +// * Author: Craig Easton +// * Version 1.4 (Jan 2016) +// * Forum: http://www.mixxx.org/forums/viewtopic.php?f=7&t=7868 +// * Wiki: http://www.mixxx.org/wiki/doku.php/behringer_cmd_studio_4a +// **************************************************************************** + +//////////////////////////////////////////////////////////////////////// +// JSHint configuration // +//////////////////////////////////////////////////////////////////////// +/* global engine */ +/* global script */ +/* global print */ +/* global midi */ +//////////////////////////////////////////////////////////////////////// + +// Master function definition. +function BehringerCMDStudio4a() {} + + +// ***************************** Global Vars ********************************** + +// Shift/mode state variables. +BehringerCMDStudio4a.delButtonState = [false,false,false,false]; +BehringerCMDStudio4a.scratchButtonState = [false,false,false,false]; + +// Button push/release state variables. +BehringerCMDStudio4a.pitchPushed = [[false,false,false,false], [false,false,false,false]]; +BehringerCMDStudio4a.delPushed = false; +BehringerCMDStudio4a.delShiftUsed = false; +BehringerCMDStudio4a.fxAssignPushed = false; +BehringerCMDStudio4a.fxAssignShiftUsed = false; +BehringerCMDStudio4a.fxAssignLastGroup = ""; + +// ************************ Initialisation stuff. ***************************** + +BehringerCMDStudio4a.vuMeterUpdate = function (value, group, control){ + value = (value*15)+48; + switch(control) { + case "VuMeterL": + midi.sendShortMsg(0xB0, 0x7E, value); + break; + case "VuMeterR": + midi.sendShortMsg(0xB0, 0x7F, value); + break; + } +} + +BehringerCMDStudio4a.initLEDs = function () { + // (re)Initialise any LEDs that are direcctly controlled by this script. + // DEL buttons (one for each virtual deck). + midi.sendShortMsg(0x90, 0x2A, 0x00); + midi.sendShortMsg(0x91, 0x4A, 0x00); + midi.sendShortMsg(0x92, 0x2A, 0x00); + midi.sendShortMsg(0x93, 0x4A, 0x00); + // Scratch buttons (one for each virtual deck). + midi.sendShortMsg(0x90, 0x16, 0x00); + midi.sendShortMsg(0x91, 0x36, 0x00); + midi.sendShortMsg(0x92, 0x16, 0x00); + midi.sendShortMsg(0x93, 0x36, 0x00); +} + +BehringerCMDStudio4a.init = function () { + // Initialise anything that might not be in the correct state. + BehringerCMDStudio4a.initLEDs(); + // Connect the VUMeters + engine.connectControl("[Master]","VuMeterL","BehringerCMDStudio4a.vuMeterUpdate"); + engine.connectControl("[Master]","VuMeterR","BehringerCMDStudio4a.vuMeterUpdate"); +} + +BehringerCMDStudio4a.shutdown = function() { + // Leave the deck in a properly initialised state. + BehringerCMDStudio4a.initLEDs(); + + // Disconnect the VUMeters. +// Maybe not! It seems you don't have to do this even though the connection +// in done in init(), in fact if you try it throws an error. +// engine.connectControl("[Master]","VuMeterL","BehringerCMDStudio4a.vuMeterUpdate",true); +// engine.connectControl("[Master]","VuMeterR","BehringerCMDStudio4a.vuMeterUpdate",true); +} + + +// *************************** Control Stuff. ********************************* +// The code below is primarily "shift/mode" key functionality as there is no +// native support for this in Mixxx at the moment. +// I suspect that the vast majority of controller mappings could be completed +// with little or no scripting if Mixxx supported shift/mode buttons in the +// XML (together with standard wheel/scratching functionality). + +// Function to deal with the DEL "shift/mode" buttons. +BehringerCMDStudio4a.del = function (channel, control, value, status, group) { + if (value == 127) { + // Button pushed. + BehringerCMDStudio4a.delPushed = true; + BehringerCMDStudio4a.delShiftUsed = false; + } else { + // Button released. + BehringerCMDStudio4a.delPushed = false; + // Only toggle the DEL-mode if the "shift" function wasn't used. + if (!BehringerCMDStudio4a.delShiftUsed) { + BehringerCMDStudio4a.delButtonState[channel] = !BehringerCMDStudio4a.delButtonState[channel]; + midi.sendShortMsg(0x90 + channel, control, BehringerCMDStudio4a.delButtonState[channel] ? 0x01 : 0x00); + } + } +} + +// Function to deal with the play buttons, (because they have a DEL-mode behaviour). +BehringerCMDStudio4a.play = function (channel, control, value, status, group) { + if (BehringerCMDStudio4a.delButtonState[channel]) { + // DEL-mode is active, do reverse-roll (slip). + engine.setValue(group, "reverseroll", (value == 127) ? 1 : 0); + } else { + // DEL-mode is not active, just toggle play (on push only). + if (value == 127) { + script.toggleControl(group,"play"); + } + } +} + +// Function to deal with the cue buttons, (because they have a DEL-mode behaviour). +BehringerCMDStudio4a.cue = function (channel, control, value, status, group) { + if (BehringerCMDStudio4a.delButtonState[channel]) { + // DEL-mode is active, do reverse play. + engine.setValue(group, "reverse", (value == 127) ? 1 : 0); + } else { + // DEL-mode is not active so just cue. + engine.setValue(group, "cue_default", (value == 127) ? 1 : 0); + } +} + +// Function to deal with the scratch mode buttons. +BehringerCMDStudio4a.scratch = function (channel, control, value, status, group) { + BehringerCMDStudio4a.scratchButtonState[channel] = !BehringerCMDStudio4a.scratchButtonState[channel]; + midi.sendShortMsg(status, control, BehringerCMDStudio4a.scratchButtonState[channel] ? 0x01 : 0x00); +} + +// Function to deal with the FX Assign buttons, (because they also act as "shift" buttons). +BehringerCMDStudio4a.fxAssign = function (channel, control, value, status, group) { + // FX Assign buttons start at 0x52. + var fxAssignButton = (control - 0x52) & 1; // Either 0 or 1 depending on button (1 or 2). + if (value == 127) { + // Button pushed. + BehringerCMDStudio4a.fxAssignPushed = true; + BehringerCMDStudio4a.fxAssignShiftUsed = false; + BehringerCMDStudio4a.fxAssignLastGroup = group; + } + else + { + // Button released. + BehringerCMDStudio4a.fxAssignPushed = false; + // Only toggle the effect on release if the "shift" function wasn't used. + if (!BehringerCMDStudio4a.fxAssignShiftUsed) { + script.toggleControl(group,"group_[Channel"+(channel+1)+"]_enable"); + } + } +} + +// Function to deal with the browse left/right buttons, (because they have an "FX Assign mode" behaviour). +BehringerCMDStudio4a.browseLR = function (channel, control, value, status, group) { + if (BehringerCMDStudio4a.fxAssignPushed) { + BehringerCMDStudio4a.fxAssignShiftUsed = true; + if (control == 0x2) { + // Left. + engine.setValue(BehringerCMDStudio4a.fxAssignLastGroup,"prev_chain", 1); + } else { + // Right. + engine.setValue(BehringerCMDStudio4a.fxAssignLastGroup,"next_chain", 1); + } + } else { + if (control == 0x2) { + // Left. + engine.setValue(group, "SelectPrevPlaylist",1) + } else { + // Right. + engine.setValue(group, "SelectNextPlaylist",1) + } + } +} + +// Functions to deal with the hot-cue buttons, (because they have a DEL-mode behaviour). +BehringerCMDStudio4a.hotcue = function (channel, control, value, status, group) { + // Translate the button to the actual hotcue. + var hotcue = control-0x21; // Hotcue buttons on left deck go from 0x22 to 0x29 + if (hotcue>8) { + // Right deck, buttons are 0x20 higher so we need to compensate. + hotcue = hotcue-0x20; + } + if (BehringerCMDStudio4a.delPushed) { + // DEL button is being held so delete the hotcue. + engine.setValue(group, "hotcue_"+hotcue+"_clear", 1); + BehringerCMDStudio4a.delShiftUsed = true; + } else { + // DEL button is not being held down. + if (BehringerCMDStudio4a.delButtonState[channel]) { + // DEL-mode is active, lets do auto-loops. + engine.setValue(group, "beatloop_"+(1/8)*Math.pow(2,hotcue-1)+"_toggle", 1); + if (value == 0) { + // Button is being released. Disable then re-enable slip if it + // is active. This "re-syncs" the playback after every + // auto-loop in slip-mode which is a nice effect and probably + // what you want most of the time if slip is on. + if (engine.getValue(group, "slip_enabled") == 1) { + engine.setValue(group, "slip_enabled", 0); + // It seems we can't just flip a param off and on in the + // same call! Since we've just turned slip off, I can't now + // turn it on directly here, the only work-around I could + // think of was to create a (very short) timed call-back + // to turn it off! + // Raised bug about this: + // https://bugs.launchpad.net/mixxx/+bug/1538200 + // Changed timer from 50 to 100 after the pathology of this + // bug was explined in the bug report. + engine.beginTimer(100, function() { engine.setValue(group, "slip_enabled", 1); }, 1); + } + } + } else { + // DEL-mode is not active so do the set/jump-to hotcue function as normal. + engine.setValue(group, "hotcue_"+hotcue+"_activate", (value == 127) ? 1 : 0); + } + } +} + +// Functions to deal with the pitch inc/dec buttons, (because they have a DEL-mode behaviour). +BehringerCMDStudio4a.pitch = function (channel, control, value, status, group) { + // Work out the direction. + var direction = ((control & 0x01) == 0) ? "down" : "up"; + // Work out the type (and join) by looking at the DEL button state. + var type = BehringerCMDStudio4a.delButtonState[channel] ? "pitch" : "rate"; + var join = BehringerCMDStudio4a.delButtonState[channel] ? "" : "_perm"; + // Pushed or released? + if (value == 127) { + // Button pushed. + BehringerCMDStudio4a.pitchPushed[control & 0x01][channel] = true; + // Is the other button pushed too? + if (BehringerCMDStudio4a.pitchPushed[(~control) & 0x01][channel]) { + engine.setValue(group, type, 0); // Yep! reset the control. + } else { + engine.setValue(group, type+join+"_"+direction, 1); + } + } else { + // Button released. + BehringerCMDStudio4a.pitchPushed[control & 0x01][channel] = false; + engine.setValue(group, "rate_perm_"+direction, 0); // Keeps the UI in sync with the button state. + } +} + +// Functions to deal with the wheel (i.e. scratcing and jog). +// Why is there no (XML) support in Mixxx for this most basic of functions? +// I suspect the vast majority of controller mappings use the same code +// (provided in the Wiki). +BehringerCMDStudio4a.wheelTouch = function (channel, control, value, status, group) { + channel = channel+1; + if (value > 0) { + // We're touching the wheel. + var alpha = 1.0/8; + var beta = alpha/32; + engine.scratchEnable(channel, 600, 33+1/3, alpha, beta); + } else { + // We've released the wheel. + engine.scratchDisable(channel); + } +}; +BehringerCMDStudio4a.wheelTurn = function (channel, control, value, status, group) { + var deck = channel+1; + var newValue = value-64; + if (BehringerCMDStudio4a.scratchButtonState[channel]){ + if (engine.isScratching(deck)){ + engine.scratchTick(deck,newValue); // Scratch! + } + } else { + engine.setValue(group, "jog", newValue); // Jog. + } +}; |