diff --git a/res/controllers/Behringer CMD MM1.midi.xml b/res/controllers/Behringer CMD MM1.midi.xml index 50302e628c33..f2ef597384c5 100644 --- a/res/controllers/Behringer CMD MM1.midi.xml +++ b/res/controllers/Behringer CMD MM1.midi.xml @@ -4,7 +4,7 @@ ]> - + Behringer CMD MM-1 Swiftb0y @@ -14,12 +14,15 @@ + + + [MixerEQ] - CMDMM.knob + CMDMM.Decks[1].knobUnit.knobs[2].input knob[2,3] &CC; 0x0F @@ -29,7 +32,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[3].knobUnit.knobs[0].input knob[4,1] &CC; 0x09 @@ -39,7 +42,7 @@ [Channel4] - CMDMM.cue + CMDMM.Decks[3].buttonCue.input pfl ¬eOn; 0x33 @@ -49,7 +52,7 @@ [EffectRack1_EffectUnit1] - CMDMM.fxButton + CMDMM.Decks[1].button1.input group_[Channel2]_enable ¬eOn; 0x17 @@ -59,7 +62,7 @@ [Channel1] - CMDMM.fader + CMDMM.Decks[0].fader.input volume &CC; 0x30 @@ -69,7 +72,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[2].knobUnit.knobs[3].input knob[3,4] &CC; 0x14 @@ -79,7 +82,7 @@ [Master] - CMDMM.unshift + CMDMM.shiftButton.input shiftOff ¬eOff; 0x10 @@ -89,7 +92,7 @@ [Library] - CMDMM.libraryEncoder + CMDMM.libraryEncoder.input left/right library select encoder &CC; 0x03 @@ -100,7 +103,7 @@ [Master] - CMDMM.ctrl + CMDMM.ctrlButton.input ctrlOn ¬eOn; 0x11 @@ -110,7 +113,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[0].knobUnit.knobs[2].input knob[1,3] &CC; 0x0E @@ -120,7 +123,7 @@ [EffectRack1_EffectUnit2] - CMDMM.fxButton + CMDMM.Decks[2].button2.input group_[Channel3]_enable ¬eOn; 0x1C @@ -130,17 +133,17 @@ [Master] - crossfader - native/direct crossfader mapping + CMDMM.crossfader.input + crossfader &CC; 0x40 - + [MixerEQ] - CMDMM.knob + CMDMM.Decks[2].knobUnit.knobs[0].input knob[3,1] &CC; 0x08 @@ -150,7 +153,7 @@ [Channel3] - CMDMM.cue + CMDMM.Decks[2].buttonCue.input pfl ¬eOn; 0x32 @@ -160,7 +163,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[1].knobUnit.knobs[3].input knob[2,4] &CC; 0x13 @@ -170,7 +173,7 @@ [EffectRack1_EffectUnit2] - CMDMM.out2 + CMDMM.out2.input Master Gain &CC; 0x02 @@ -180,7 +183,7 @@ [Master] - CMDMM.shift + CMDMM.shiftButton.input shiftOn ¬eOn; 0x10 @@ -190,7 +193,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[3].knobUnit.knobs[1].input knob[4,2] &CC; 0x0D @@ -200,7 +203,7 @@ [EffectRack1_EffectUnit1] - CMDMM.fxButton + CMDMM.Decks[2].button1.input group_[Channel3]_enable ¬eOn; 0x1B @@ -210,7 +213,7 @@ [Channel2] - CMDMM.cue + CMDMM.Decks[1].buttonCue.input pfl ¬eOn; 0x31 @@ -220,7 +223,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[1].knobUnit.knobs[0].input knob[2,1] &CC; 0x07 @@ -230,7 +233,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[0].knobUnit.knobs[3].input knob[1,4] &CC; 0x12 @@ -240,7 +243,7 @@ [EffectRack1_EffectUnit2] - CMDMM.fxButton + CMDMM.Decks[3].button2.input group_[Channel4]_enable ¬eOn; 0x20 @@ -250,7 +253,7 @@ [Master] - CMDMM.out1 + CMDMM.out1.input Master balance &CC; 0x01 @@ -260,7 +263,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[2].knobUnit.knobs[1].input knob[3,2] &CC; 0x0C @@ -270,7 +273,7 @@ [Channel4] - CMDMM.fader + CMDMM.Decks[3].fader.input volume &CC; 0x33 @@ -280,7 +283,7 @@ [Channel1] - CMDMM.cue + CMDMM.Decks[0].buttonCue.input pfl ¬eOn; 0x30 @@ -290,7 +293,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[0].knobUnit.knobs[0].input knob[1,1] &CC; 0x06 @@ -300,7 +303,7 @@ [EffectRack1_EffectUnit2] - CMDMM.fxButton + CMDMM.Decks[0].button2.input group_[Channel1]_enable ¬eOn; 0x14 @@ -310,7 +313,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[3].knobUnit.knobs[2].input knob[4,3] &CC; 0x11 @@ -320,7 +323,7 @@ [EffectRack1_EffectUnit1] - CMDMM.fxButton + CMDMM.Decks[3].button1.input group_[Channel4]_enable ¬eOn; 0x1F @@ -330,7 +333,7 @@ [Library] - CMDMM.libraryButton + CMDMM.libraryButton.input Middle click libraryEncoder ¬eOn; 0x03 @@ -338,9 +341,19 @@ + + [Library] + CMDMM.libraryButton.input + Middle click libraryEncoder + ¬eOff; + 0x03 + + + + [MixerEQ] - CMDMM.knob + CMDMM.Decks[1].knobUnit.knobs[1].input knob[2,2] &CC; 0x0B @@ -350,7 +363,7 @@ [Channel3] - CMDMM.fader + CMDMM.Decks[2].fader.input volume &CC; 0x32 @@ -360,17 +373,17 @@ [Master] - headMix - native/direct pfl mix + CMDMM.cueMix.input + script pfl mix &CC; 0x05 - + [EffectRack1_EffectUnit1] - CMDMM.fxButton + CMDMM.Decks[0].button1.input group_[Channel1]_enable ¬eOn; 0x13 @@ -380,7 +393,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[2].knobUnit.knobs[2].input knob[3,3] &CC; 0x10 @@ -390,7 +403,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[0].knobUnit.knobs[1].input knob[1,2] &CC; 0x0A @@ -400,7 +413,7 @@ [EffectRack1_EffectUnit2] - CMDMM.fxButton + CMDMM.Decks[1].button2.input group_[Channel2]_enable ¬eOn; 0x18 @@ -410,7 +423,7 @@ [Channel2] - CMDMM.fader + CMDMM.Decks[1].fader.input volume &CC; 0x31 @@ -420,7 +433,7 @@ [MixerEQ] - CMDMM.knob + CMDMM.Decks[3].knobUnit.knobs[3].input knob[4,4] &CC; 0x15 @@ -430,8 +443,8 @@ [Master] - CMDMM.unctrl - ctrlOff + CMDMM.ctrlButton.input + ctrl ¬eOff; 0x11 @@ -440,17 +453,17 @@ [Master] - headGain - native/direct pfl volume + CMDMM.cueVol.input + inscript pfl volume &CC; 0x04 - + [Master] - CMDMM.middleButton + CMDMM.middleButton.input Button in the Middle (shift on other mappings) ¬eOn; 0x12 diff --git a/res/controllers/Behringer-CMD-MM1-scripts.js b/res/controllers/Behringer-CMD-MM1-scripts.js index ce735df3b2e5..1c18c3811c51 100644 --- a/res/controllers/Behringer-CMD-MM1-scripts.js +++ b/res/controllers/Behringer-CMD-MM1-scripts.js @@ -1,566 +1,558 @@ - +var CMDMM = new components.ComponentContainer(); //GLOBAL VARS var channelNumber = 5; var invertColor = true; //false=(off=orange,on=blue);true=(off=blue,on=orange); + var defaultChannelSequence = [3, 1, 2, 4]; var channelMode = [true, true, true, true]; //true=deck;false=fxChannel -var standardKnobBehavior = 0; // 0 = [High,Mid,Low,Quickeffect]; 1 = [Gain,High,Mid,Low]; 2 = [Effect1Meta,Effect2Meta,Effect3Meta,mix]; +var faderMode = [true, true, true, true]; // true=super;false=rate (only affects fxMode Channels) - -CMDMM = {}; //controller itself -MIDI = {}; //midi related constants -CALLBACK = {}; //Every callback function -FUNCTIONS = {}; //misc for assigning controls +var standardKnobBehavior = 0; // 0 = [High,Mid,Low,Quickeffect]; 1 = [Gain,High,Mid,Low]; 2 = [Effect1Meta,Effect2Meta,Effect3Meta,mix]; +var navEncoderScale = 5; // The amount of steps mixxx will scroll within the library while pressing the encoder; -//takes functions as arguments and executes them based on the current state of shift and control; -CMDMM.modes = function(normal, shift, ctrl, thirdLevel) { - switch (CMDMM.getLevel()) { - case 0: - if (normal !== undefined) { - normal(); - } - break; - case 1: - if (shift !== undefined) { - shift(); - } - break; - case 2: - if (ctrl !== undefined) { - ctrl(); - } - break; - case 3: - if (thirdLevel !== undefined) { - thirdLevel(); +//0x00 = orange; 0x01 = blue; +components.Button.prototype.on=(invertColor ? 0x00 : 0x01); +components.Button.prototype.off=(invertColor ? 0x01 : 0x00); + + +components.ComponentContainer.prototype.layer = function (layer) { + this.forEachComponent(function (component) { + if (component.before !== undefined && typeof component.before === "function") {component.before();} + if (typeof component["layer"+layer] === 'function') { + if (component instanceof components.Button + && (component.type === components.Button.prototype.types.push + || component.type === undefined) + && component.input === components.Button.prototype.input + && typeof component.inKey === 'string' + && typeof component.group === 'string') { + if (engine.getValue(component.group, component.inKey) !== 0) { + engine.setValue(component.group, component.inKey, 0); + } + } + // component.layer(layer); + component["layer"+layer](); } - break; - default: - print("invalid Level: " + CMDMM.getLevel()); - break; - } + if (component.after !== undefined && typeof component.after === "function") {component.after();} + // Set isShifted for child ComponentContainers forEachComponent is iterating through recursively + this.isShifted = (layer!==1); + }); + CMDMM.reconnectComponents(function (component) { + if (component.group === undefined) { + component.group = this.group; + } + }); }; - - +components.Button.prototype.before=function () { + this.output=components.Button.prototype.output; + this.input=components.Button.prototype.input; +}; +components.Button.prototype.after=function () { + this.outKey=this.inKey; +}; +var MIDI = {}; MIDI.noteOn = 0x90 + (channelNumber - 1); MIDI.noteOff = 0x80 + (channelNumber - 1); MIDI.CC = 0xB0 + (channelNumber - 1); - -//0x00 = orange; 0x01 = blue; -CMDMM.on = (invertColor ? 0x00 : 0x01); -CMDMM.off = (invertColor ? 0x01 : 0x00); -CMDMM.blink = 0x02; - - -CMDMM.buttons = [0x12, 0x13, 0x14, 0x17, 0x18, 0x1B, 0x1C, 0x1F, 0x20, 0x30, 0x31, 0x32, 0x33, ]; -// ^ ^Fx1 ^Fx2 ^Fx1 ^Fx2 ^Fx1 ^Fx2 ^Fx1 ^Fx2 ^CUE1^CUE2^CUE3^CUE4 -// | ^Channel1 ^Channel2 ^Channel3 ^Channel4 -// ^middlebutton - -CMDMM.varStorage = { - level: 0, //stores the current level (shift/ctrl/thirdlevel) - knobAssignment: standardKnobBehavior, - channelSequence: defaultChannelSequence, - channelKind: channelMode, //true=deck,false=fxUnit - ChannelAssignmentStatus: [ - [0, 0], - [0, 0], - [0, 0], - [0, 0] - ], -}; - -CMDMM.getShift = function() { - return CMDMM.varStorage.level === 1; -}; -CMDMM.shift = function() { - CMDMM.varStorage.level++; - CMDMM.updateLEDs(); - FUNCTIONS.ignoreNextValue(); -}; -CMDMM.unshift = function() { - CMDMM.varStorage.level--; - CMDMM.updateLEDs(); - FUNCTIONS.ignoreNextValue(); -}; - -CMDMM.getCtrl = function() { - return CMDMM.varStorage.level === 2; -}; -CMDMM.ctrl = function() { - CMDMM.varStorage.level += 2; - CMDMM.updateLEDs(); - FUNCTIONS.ignoreNextValue(); -}; -CMDMM.unctrl = function() { - CMDMM.varStorage.level -= 2; - CMDMM.updateLEDs(); - FUNCTIONS.ignoreNextValue(); -}; - -CMDMM.getThird = function() { - return (CMDMM.varStorage.level == 3 ? true : false); -}; -CMDMM.getLevel = function() { - return CMDMM.varStorage.level; -}; - - -CMDMM.cue = function(channel, control, value, status, group) { - var cueChannel = CMDMM.varStorage.channelSequence[control - 0x30]; - if (CMDMM.varStorage.channelKind[control - 0x30]) { - CMDMM.modes( - function() { - script.toggleControl("[Channel" + cueChannel + "]", "pfl"); - }, - function() { - //load track into selected channel - engine.setParameter("[Channel" + cueChannel + "]", "LoadSelectedTrack", 1); - }, - function() { - /* - //enable pfl for EffectN N = number of channel (a bit weird, but it works) - script.toggleControl("[EffectRack1_EffectUnit"+cueChannel+"]", "group_[Headphone]_enable"); - //OBSOLETE - */ - }, - function() { - CMDMM.varStorage.channelKind[control - 0x30] = !CMDMM.varStorage.channelKind[control - 0x30]; - CALLBACK.cue(); - CALLBACK.fxButton(); - }); - } else { - CMDMM.modes( - function() { - script.toggleControl("[EffectRack1_EffectUnit" + cueChannel + "_Effect3]", "enabled"); - }, - function() { - script.toggleControl("[EffectRack1_EffectUnit" + cueChannel + "]", "group_[Headphone]_enable"); - }, - function() { - script.toggleControl("[EffectRack1_EffectUnit" + cueChannel + "]", "group_[Master]_enable"); - }, - function() { - CMDMM.varStorage.channelKind[control - 0x30] = !CMDMM.varStorage.channelKind[control - 0x30]; - CALLBACK.cue(); - CALLBACK.fxButton(); - } - ); +MIDI.ControllerDump = [0xF0,0x00,0x20,0x7F,0x03,0x01,0xF7]; + +CMDMM.currentLayer=1; +// Abstract: +// The Mapping consist of the following Objects: +// CMDMM: +// - EQAndGain (generic Template) +// - EQAndQuickEffect (generic Template) +// - FXKnobs (generic Template) +// - deckChannel (generic Template) +// - knobUnit = EQAndGain || EQAndQuickEffect +// - button1 (specific functionality for the deckchannel) +// - button2 (see button1) +// - buttonCue (see button1) +// - fader (volume || pitch) +// - FXChannel (generic Template) +// - knobUnit = FXKnobs +// - button1 (specific functionality for the fxChannel) +// - button2 (see button1) +// - buttonCue (see button1) +// - fader (FxUnitMix) +// - Decks[4] +// - four instances of the decktype indicated by CMMDMM.channelMode (can be set at the top) +// - middleButton +// - shiftButton +// - ctrlButton +// - VUMeters +// - CFader +// - library encoder knob +// - HeadGain +// - HeadMix +// - out1 (masterBalance) +// - out2 (MasterGain) + +// The Component name usually match with the corresponding label on the Controller. +// ButtonCue, Button1 and Button2 are derived from their label on a channel. +// Layout on the Controller: +// +-------------------+ +// | | +// | +---+ +---+ | +// | | 1 | | 2 | | +// | +---+ +---+ | +// | | +// | +-----------+ | +// | | Cue | | +// | +-----------+ | +// | | +// +-------------------+ + +// the Shiftbuttons will correspond to the layers in the following combination: +// unpressed/default: layer1 +// shift: layer2 +// ctrl: layer3 +// shift+ctrl: layer4 + +CMDMM.EQAndGain = function (channel, baseAddress) { + this.knobs = []; + this.knobs[0] = new components.Pot({ + midi: [MIDI.CC, baseAddress], + group: "[Channel"+channel+"]", + inKey: "pregain", + }); + for (var i = 1; i <= 3; i++) { + this.knobs[i] = new components.Pot({ + midi: [MIDI.CC, baseAddress + 4*(i-1)], + group: '[EqualizerRack1_[Channel'+channel+']_Effect1]', + inKey: 'parameter' + (4-i), + // parameter has to be assigned in reverse. + }); } }; - -CMDMM.fxButton = function(channel, control, value, status, group) { - var button = CMDMM.buttons.indexOf(control); //returns integers from 1 to 8 - var realChannel = Math.floor((button - 1) / 2); //realchannelNumbers (0to3) - var mixxxChannel = CMDMM.varStorage.channelSequence[realChannel]; - if (CMDMM.varStorage.channelKind[realChannel]) { - CMDMM.modes( - function() { - var channelButton = button % 2 === 0 ? 2 : 0; - if (engine.getValue("[Channel" + mixxxChannel + "]", "orientation") === channelButton) { - engine.setValue("[Channel" + mixxxChannel + "]", "orientation", 1); - } else { - engine.setValue("[Channel" + mixxxChannel + "]", "orientation", channelButton); //checks if buttonnumber is even, if true, return Left if false, return right; - } - - }, - function() { - var effectUnit = button % 2 === 0 ? 2 : 1; //checks if buttonnumber is even, if true, return effectUnit 2 if false, return effectUnit 1; - // maps button to range [0;7], divides and floors it (result: [0;3]). That value is being used to lookup the right channel. - script.toggleControl("[EffectRack1_EffectUnit" + effectUnit + "]", "group_[Channel" + mixxxChannel + "]_enable"); - }, - function() { - var effectUnit = button % 2 === 0 ? 4 : 3; //checks if buttonnumber is even, if true, return effectUnit 4 if false, return effectUnit 3; - script.toggleControl("[EffectRack1_EffectUnit" + effectUnit + "]", "group_[Channel" + mixxxChannel + "]_enable"); - }, - function() { - var left_right = button % 2 === 0 ? 2 : 1; - CMDMM.varStorage.ChannelAssignmentStatus[realChannel][left_right - 1] = CMDMM.varStorage.ChannelAssignmentStatus[realChannel][left_right - 1] === 0 ? 1 : 0; - //basically inverting the one bit ^^ - CMDMM.varStorage.channelSequence[realChannel] = CMDMM.varStorage.ChannelAssignmentStatus[realChannel][0] + CMDMM.varStorage.ChannelAssignmentStatus[realChannel][1] * 2 + 1; - CALLBACK.fxButton(); - /* - var buttonSet = CMDMM.varStorage.ChannelAssignmentStatus[realChannel]; - var whichButton = button%2===0 ? 1:0; - var isActive = buttonSet[whichButton]; - var value = whichButton*(isActive?-1:1); - CMDMM.varStorage.channelSequence[realChannel] +=value; - CMDMM.varStorage.ChannelAssignmentStatus[realChannel][whichButton] = !isActive; - CALLBACK.fxButton();*/ - } - ); - } else { - CMDMM.modes( - function() { - var effectUnit = button % 2 === 0 ? 2 : 1; - script.toggleControl("[EffectRack1_EffectUnit" + mixxxChannel + "_Effect" + effectUnit + "]", "enabled"); - }, - function() { - var effectUnit = button % 2 === 0 ? 2 : 1; //checks if buttonnumber is even, if true, return effectUnit 2 if false, return effectUnit 1; - // maps button to range [0;7], divides and floors it (result: [0;3]). That value is being used to lookup the right channel. - script.toggleControl("[EffectRack1_EffectUnit" + mixxxChannel + "]", "group_[Channel" + effectUnit + "]_enable"); - }, - function() { - var effectUnit = button % 2 === 0 ? 4 : 3; //checks if buttonnumber is even, if true, return effectUnit 4 if false, return effectUnit 3; - // maps button to range [0;7], divides and floors it (result: [0;3]). That value is being used to lookup the right channel. - script.toggleControl("[EffectRack1_EffectUnit" + mixxxChannel + "]", "group_[Channel" + effectUnit + "]_enable"); - }, - function() { - var left_right = button % 2 === 0 ? 2 : 1; - CMDMM.varStorage.ChannelAssignmentStatus[realChannel][left_right - 1] = CMDMM.varStorage.ChannelAssignmentStatus[realChannel][left_right - 1] === 0 ? 1 : 0; - //basically inverting the one bit ^^ - CMDMM.varStorage.channelSequence[realChannel] = CMDMM.varStorage.ChannelAssignmentStatus[realChannel][0] + CMDMM.varStorage.ChannelAssignmentStatus[realChannel][1] * 2 + 1; - CALLBACK.fxButton(); - } - ); +CMDMM.EQAndGain.prototype = new components.ComponentContainer(); + +CMDMM.EQAndQuickEffect = function (channel, baseAddress) { + this.knobs=[]; + for (var i = 1; i <= 3; i++) { + this.knobs[i-1] = new components.Pot({ + midi: [MIDI.CC, baseAddress + 4*(i-1)], + group: '[EqualizerRack1_[Channel'+channel+']_Effect1]', + inKey: 'parameter' + (4-i), + // parameter has to be assigned in reverse. + }); } -}; -FUNCTIONS.assignKnobsWithQuickEffect = function() { - CMDMM.knob = function(channel, control, value, status, group) { - var realChannel = (control - 0x06) % 4; - var mixxxChannel = CMDMM.varStorage.channelSequence[realChannel]; - if (CMDMM.varStorage.channelKind[realChannel]) { - var parameterNum = -(Math.floor((control - 0x06) / 4) - 3); //get the horizontal row of the button and translates it to the number - var parameter = (parameterNum === 0 ? "super1" : ("parameter" + parameterNum)); - var mixxxGroup = (parameterNum === 0) ? ("[QuickEffectRack1_[Channel" + mixxxChannel + "]]") : "[EqualizerRack1_[Channel" + mixxxChannel + "]_Effect1]"; - engine.setParameter(mixxxGroup, parameter, value / 127); - } else { - var parameterNum = Math.floor((control - 0x06) / 4) + 1; - var parameter = (parameterNum === 4) ? "super1" : "meta"; - var mixxxGroup = ("[EffectRack1_EffectUnit" + mixxxChannel + ((parameterNum === 4) ? "" : ("_Effect" + parameterNum)) + "]"); - engine.setParameter(mixxxGroup, parameter, value / 127); - } - }; -}; -FUNCTIONS.assignKnobsWithGain = function() { - CMDMM.knob = function(channel, control, value, status, group) { - var realChannel = (control - 0x06) % 4; - var mixxxChannel = CMDMM.varStorage.channelSequence[realChannel]; - if (CMDMM.varStorage.channelKind[realChannel]) { - var parameterNum = -(Math.floor((control - 0x06) / 4) - 2) + 2; //get the horizontal row of the button and translates it to the number - var parameter = (parameterNum === 4 ? "pregain" : ("parameter" + parameterNum)); - var mixxxGroup = (parameterNum === 4) ? ("[Channel" + mixxxChannel + "]") : "[EqualizerRack1_[Channel" + mixxxChannel + "]_Effect1]"; - engine.setParameter(mixxxGroup, parameter, value / 127); - } else { - var parameterNum = Math.floor((control - 0x06) / 4) + 1; - var parameter = (parameterNum === 4) ? "super1" : "meta"; - var mixxxGroup = ("[EffectRack1_EffectUnit" + mixxxChannel + ((parameterNum === 4) ? "" : ("_Effect" + parameterNum)) + "]"); - engine.setParameter(mixxxGroup, parameter, value / 127); - } - }; -}; -FUNCTIONS.assignKnobsEffectOnly = function() { - CMDMM.knob = function(channel, control, value, status, group) { - var realChannel = (control - 0x06) % 4; - var mixxxChannel = CMDMM.varStorage.channelSequence[realChannel]; - var parameterNum = Math.floor((control - 0x06) / 4) + 1; - var parameter = (parameterNum === 4) ? "mix" : "meta"; - var mixxxGroup = ("[EffectRack1_EffectUnit" + mixxxChannel + ((parameterNum === 4) ? "" : ("_Effect" + parameterNum)) + "]"); - engine.setParameter(mixxxGroup, parameter, value / 127); - }; -}; -CMDMM.updateLEDs = function() { - //could be better implemented, but its easy and it works. - CALLBACK.middleButton(); - CALLBACK.fxButton(); - CALLBACK.cue(); -}; -FUNCTIONS.ignoreNextValue = function() { - for (var i = 1; i <= 4; i++) { - engine.softTakeoverIgnoreNextValue("[QuickEffectRack1_[Channel" + i + "]]", "super1", true); - engine.softTakeoverIgnoreNextValue("[Channel" + i + "]", "rate", true); - engine.softTakeoverIgnoreNextValue("[Channel" + i + "]", "volume", true); - engine.softTakeoverIgnoreNextValue("[EffectRack1_EffectUnit" + i + "]", "mix", true); - engine.softTakeoverIgnoreNextValue("[EffectRack1_EffectUnit" + i + "]", "super1", true); - for (var ii = 1; ii <= 3; ii++) { - engine.softTakeoverIgnoreNextValue("[EqualizerRack1_[Channel" + i + "]_Effect1]", "parameter" + ii, true); - engine.softTakeoverIgnoreNextValue("[EffectRack1_EffectUnit" + i + "_Effect" + ii + "]", "meta", true); - } + this.knobs[3] = new components.Pot({ + midi: [MIDI.CC, baseAddress+3*4], + // (third knob of channel (zero-based)) * (offset of knobs to one another) + group: "[QuickEffectRack1_[Channel"+channel+"]]", + inKey: "super1", + }); +}; +CMDMM.EQAndQuickEffect.prototype = new components.ComponentContainer(); + +CMDMM.FXKnobs = function (channel, baseAddress) { + this.knobs = []; + for (var i = 1; i <= 3; i++) { + this.knobs[i-1] = new components.Pot({ + midi: [MIDI.CC, baseAddress + 4*(i-1)], + group: '[EffectRack1_EffectUnit'+channel+'_Effect'+i+']', + inKey: 'meta', + }); } -}; - -FUNCTIONS.cycleKnobAssignment = function() { - // 0 = [High,Mid,Low,Quickeffect]; 1 = [Gain,High,Mid,Low]; - switch (CMDMM.varStorage.knobAssignment) { - case 2: - CMDMM.varStorage.knobAssignment = 0; - FUNCTIONS.assignKnobsEffectOnly(); + this.knobs[3] = new components.Pot({ + midi: [MIDI.CC, baseAddress+3*4], + // (third knob of channel (zero-based)) * (offset of knobs to one another) + group: '[EffectRack1_EffectUnit'+channel+']', + inKey: "mix", + }); +}; +CMDMM.FXKnobs.prototype = new components.ComponentContainer(); + +CMDMM.deckChannel = function (physicalChannel,virtualChannel) { + var baseAddress=0x06+physicalChannel; + var theDeck = this; + this.currentDeck="[Channel"+virtualChannel+"]"; + this.virtualChannel=virtualChannel; + this.binaryChannel=virtualChannel-1; + switch (standardKnobBehavior) { + case 0: + this.knobUnit = new CMDMM.EQAndQuickEffect(virtualChannel,baseAddress); break; case 1: - CMDMM.varStorage.knobAssignment++; - FUNCTIONS.assignKnobsWithGain(); - break; - case 0: - CMDMM.varStorage.knobAssignment++; - FUNCTIONS.assignKnobsWithQuickEffect(); + this.knobUnit = new CMDMM.EQAndGain(virtualChannel,baseAddress); break; default: - print("INVALID KNOB ASSIGNMENT (" + CMDMM.varStorage.knobAssignment + ")!"); - break; - } -}; - -CMDMM.fader = function(channel, control, value, status, group) { - if (CMDMM.varStorage.channelKind[control - 0x30]) { - CMDMM.modes(function() { - engine.setParameter("[Channel" + CMDMM.varStorage.channelSequence[control - 0x30] + "]", "volume", value / 127); - }, - function() { - engine.setParameter("[Channel" + CMDMM.varStorage.channelSequence[control - 0x30] + "]", "rate", value / 127); - }, - function() { - //empty so fadermovement can be ignored while pressing ctrl - } - ); - } else { - CMDMM.modes( - function() { - engine.setParameter("[EffectRack1_EffectUnit" + CMDMM.varStorage.channelSequence[(control - 0x30)] + "]", "mix", value / 127); - } - ); - } -}; - -CMDMM.out1 = function(channel, control, value, status, group) { - engine.setParameter("[Master]", "balance", value / 127); -}; -CMDMM.out2 = function(channel, control, value, status, group) { - engine.setParameter("[Master]", "gain", value / 127); -}; - -FUNCTIONS.resetColor = function() { - for (var i = CMDMM.buttons.length - 1; i >= 0; i--) { - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[i], CMDMM.off); + print("WRONG KNOBUNIT TYPE!\nfalling back to EQAndQuickEffect"); + standardKnobBehavior=0; + this.knobUnit = new CMDMM.EQAndQuickEffect(virtualChannel,baseAddress); } -}; - -CMDMM.libraryEncoder = function(channel, control, value, status, group) { - CMDMM.modes( - function() { - //print("using deprecated SelectTrackKnob as long there is no way to select from just the tracks!") - engine.setValue("[Playlist]", "SelectTrackKnob", value > 0x40 ? 1 : -1); + this.button1 = new components.Button({ + midi: [MIDI.noteOn,0x0D+baseAddress+physicalChannel*3], + type: components.Button.prototype.types.toggle, + mask: 1 << 0, + layer1: function () { + // this will only set the control to the left side or center + // button2 will assign it to to the right side / center + this.inKey="orientation"; + this.group=theDeck.currentDeck; + this.output = function (value, group, control) { + this.send(this.outValueScale(value===0)); + }; + this.input = function (channel, control, value, status, group) { + this.inSetValue(this.inGetValue()!==0?0:1); + }; }, - function() { - //navigate preview track - engine.setParameter("[PreviewDeck1]", "beatjump", (value > 0x40) ? 16 : -16); + layer2: function () { + this.inKey="group_"+theDeck.currentDeck+"_enable"; + this.group="[EffectRack1_EffectUnit1]"; }, - function() { - - } - ); -}; -CMDMM.libraryButton = function(channel, control, value, status, group) { - CMDMM.modes( - function() { - engine.setParameter("[PreviewDeck1]", "LoadSelectedTrack", 1); + layer3: function () { + this.inKey="group_"+theDeck.currentDeck+"_enable"; + this.group="[EffectRack1_EffectUnit3]"; }, - function() { - engine.setParameter("[PreviewDeck1]", "play", 1); + layer4: function () { + this.inKey=""; + this.group=""; + this.input = function (channel, control, value, status, group) { + theDeck.binaryChannel^=this.mask; + this.output(theDeck.binaryChannel&this.mask); + theDeck.virtualChannel=theDeck.binaryChannel+1; + theDeck.knobUnit.currentDeck="[Channel"+theDeck.virtualChannel+"]"; + theDeck.setCurrentDeck("[Channel"+theDeck.virtualChannel+"]"); + }; + this.output(theDeck.binaryChannel&this.mask); } - ); -}; - -CMDMM.middleButton = function(channel, control, value, status, group) { - CMDMM.modes(function() { - script.toggleControl("[Master]", "maximize_library"); - //engine.setValue("[Master]","maximize_library", 1); - //maximize Library + }); + this.button2 = new components.Button({ + midi: [MIDI.noteOn,0x0E+baseAddress+physicalChannel*3], + type: components.Button.prototype.types.toggle, + mask: 1 << 1, + layer1: function () { + // this will only set the control to the right side or center + // button1 will assign it to to the left side / center + this.inKey="orientation"; + this.group=theDeck.currentDeck; + this.output = function (value, group, control) { + this.send(this.outValueScale(value===2)); + }; + this.input = function (channel, control, value, status, group) { + this.inSetValue(this.inGetValue()!==2?2:1); + }; }, - function() { - engine.setValue("[Master]", "crossfader", 0); + layer2: function () { + this.inKey="group_"+theDeck.currentDeck+"_enable"; + this.group="[EffectRack1_EffectUnit2]"; }, - function() { - FUNCTIONS.cycleKnobAssignment(); - CALLBACK.middleButton(); + layer3: function () { + this.inKey="group_"+theDeck.currentDeck+"_enable"; + this.group="[EffectRack1_EffectUnit4]"; }, - function() { - CMDMM.varStorage.channelSequence = defaultChannelSequence; - CMDMM.updateLEDs(); + layer4: function () { + this.inKey=""; + this.group=""; + this.input = function (channel, control, value, status, group) { + theDeck.binaryChannel^=this.mask; + this.output(theDeck.binaryChannel&this.mask); + theDeck.virtualChannel=theDeck.binaryChannel+1; + theDeck.knobUnit.currentDeck="[Channel"+theDeck.virtualChannel+"]"; + theDeck.setCurrentDeck("[Channel"+theDeck.virtualChannel+"]"); + }; + this.output(theDeck.binaryChannel&this.mask); } - ); -}; - -CALLBACK.vuMeterL = function(value, group, control) { - midi.sendShortMsg(MIDI.CC, 80, (value * 15) + 48); -}; -CALLBACK.vuMeterR = function(value, group, control) { - midi.sendShortMsg(MIDI.CC, 81, (value * 15) + 48); -}; - - -CALLBACK.registerCallbacks = function() { - //VuMeters - engine.makeConnection("[Master]", "VuMeterL", CALLBACK.vuMeterL); - engine.makeConnection("[Master]", "VuMeterR", CALLBACK.vuMeterR); - //engine.makeConnection("[Master]","maximize_library",CALLBACK.middleButton);// doesn't work, help? - //cueButtons (pfl) - for (var i = 1; i <= 4; i++) { - engine.makeConnection("[Channel" + i + "]", "pfl", CALLBACK.cue); - engine.makeConnection("[Channel" + i + "]", "play", CALLBACK.cue); - engine.makeConnection("[Channel" + i + "]", "orientation", CALLBACK.fxButton); - for (var ii = 1; ii <= 4; ii++) { - engine.makeConnection("[EffectRack1_EffectUnit" + i + "]", "group_[Channel" + ii + "]_enable", CALLBACK.fxButton); + }); + this.buttonCue = new components.Button({ + midi: [MIDI.noteOn,0x2A+baseAddress], + group: theDeck.currentDeck, + layer1: function () { + this.inKey="pfl"; + this.type=components.Button.prototype.types.toggle; + }, + layer2: function () { + this.inKey="LoadSelectedTrack"; + this.type=components.Button.prototype.types.push; + }, + layer3: function () { + this.inKey="sync_enabled"; + this.type=components.Button.prototype.types.push; + }, + layer4: function () { + this.inKey=""; + this.output(this.on); + this.input = function () { + CMDMM.Decks[physicalChannel] = new CMDMM.fxChannel(physicalChannel,theDeck.virtualChannel); + this.output(this.off); + theDeck.reconnectComponents(); + }; } - for (var ii = 1; ii <= 2; ii++) { - engine.makeConnection("[EffectRack1_EffectUnit" + i + "_Effect" + ii + "]", "enabled", CALLBACK.fxButton); + }); + this.fader = new components.Pot({ + midi: [MIDI.CC,0x2A+baseAddress], + inKey: "volume", + group: theDeck.currentDeck, + after: function () {this.input=components.Pot.prototype.input;}, + layer4: function () { + this.input = function (channel, control, value, status, group) { + if (value>42&&value<=84) { + this.inKey="rate"; + } else { + this.inKey="volume"; + } + }; + }, + }); +}; +CMDMM.deckChannel.prototype = new components.Deck(); + +CMDMM.fxChannel = function (physicalChannel,virtualChannel) { + var baseAddress=0x06+physicalChannel; + var theDeck=this; + this.currentDeck="[Channel"+virtualChannel+"]"; + this.virtualChannel=virtualChannel; + this.binaryChannel=virtualChannel-1; + this.knobUnit = new CMDMM.FXKnobs(virtualChannel,baseAddress); + this.button1 = new components.Button({ + midi: [MIDI.noteOn,0x0D+baseAddress+physicalChannel*3], + type: components.Button.prototype.types.toggle, + mask: 1 << 0, + layer1: function () { + this.inKey="enabled"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"_Effect1]"; + }, + layer2: function () { + this.inKey="group_[Channel1]_enable"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer3: function () { + this.inKey="group_[Channel3]_enable"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer4: function () { + this.inKey=""; + this.group=""; + this.input = function (channel, control, value, status, group) { + theDeck.binaryChannel^=this.mask; + this.output(theDeck.binaryChannel&this.mask); + theDeck.virtualChannel=theDeck.binaryChannel+1; + // creating a new Unit is easier than changing the groups via Regexp + theDeck.knobUnit = new CMDMM.FXKnobs(theDeck.virtualChannel,baseAddress); + // the fader doesnt get changed if it is set to controll the fxunit + // (look at components.Deck.setCurrentDeck for more explanation) + if (theDeck.fader.inKey==="super1") { + theDeck.fader.group='[EffectRack1_EffectUnit'+theDeck.virtualChannel+']'; + } + theDeck.setCurrentDeck("[Channel"+theDeck.virtualChannel+"]"); + }; + this.output(theDeck.binaryChannel&this.mask); + }, + }); + this.button2 = new components.Button({ + midi: [MIDI.noteOn,0x0E+baseAddress+physicalChannel*3], + mask: 1 << 1, + type: components.Button.prototype.types.toggle, + layer1: function () { + this.inKey="enabled"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"_Effect2]"; + }, + layer2: function () { + this.inKey="group_[Channel2]_enable"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer3: function () { + this.inKey="group_[Channel4]_enable"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer4: function () { + this.inKey=""; + this.group=""; + this.input = function (channel, control, value, status, group) { + theDeck.binaryChannel^=this.mask; + this.output(theDeck.binaryChannel&this.mask); + theDeck.virtualChannel=theDeck.binaryChannel+1; + // creating a new Unit is easier than changing the groups via Regexp + theDeck.knobUnit = new CMDMM.FXKnobs(theDeck.virtualChannel,baseAddress); + // the fader doesnt get changed if it is set to control the fxunit + // (look at components.Deck.setCurrentDeck for more explanation) + if (theDeck.fader.inKey==="super1") { + theDeck.fader.group='[EffectRack1_EffectUnit'+theDeck.virtualChannel+']'; + } + theDeck.setCurrentDeck("[Channel"+theDeck.virtualChannel+"]"); + }; + this.output(theDeck.binaryChannel&this.mask); + }, + }); + this.buttonCue = new components.Button({ + midi: [MIDI.noteOn,0x2A+baseAddress], + type: components.Button.prototype.types.toggle, + layer1: function () { + this.inKey="enabled"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"_Effect3]"; + }, + layer2: function () { + this.inKey="group_[Headphone]_enable"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer3: function () { + this.inKey="mix_mode"; + this.group="[EffectRack1_EffectUnit"+theDeck.virtualChannel+"]"; + }, + layer4: function () { + this.inKey=""; + this.group=""; + this.output(this.off); + this.input = function () { + CMDMM.Decks[physicalChannel] = new CMDMM.deckChannel(physicalChannel,theDeck.virtualChannel); + this.output(this.on); + theDeck.reconnectComponents(); + }; } - engine.makeConnection("[EffectRack1_EffectUnit" + i + "_Effect3]", "enabled", CALLBACK.cue); - engine.makeConnection("[EffectRack1_EffectUnit" + i + "]", "group_[Headphone]_enable", CALLBACK.cue); - engine.makeConnection("[EffectRack1_EffectUnit" + i + "]", "group_[Master]_enable", CALLBACK.cue); - } -}; -CALLBACK.middleButton = function() { - switch (CMDMM.getLevel()) { - case 0: - //midi.sendShortMsg(MIDI.noteOn,CMDMM.buttons[0],engine.getParameter("[Master]","maximize_library")?CMDMM.on:CMDMM.off); break; - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[0], CMDMM.off); - break; - case 1: - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[0], engine.getValue("[Master]", "crossfader") ? CMDMM.on : CMDMM.off); - break; - case 2: - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[0], CMDMM.varStorage.knobAssignment); - break; //[High,Mid,Low,Quickeffect]=orange, [Gain,High,Mid,Low] = blue; - case 3: - //midi.sendShortMsg(MIDI.noteOn,CMDMM.buttons[0],CMDMM.varStorage.channelSequence===[3,1,2,4]?0x01:0x00); break; //[3,1,2,4]ChannelAssignment = blue; [1,2,3,4] = orange; - } + }); + this.fader = new components.Pot({ + midi: [MIDI.CC,0x2A+baseAddress], + inKey: (faderMode[physicalChannel]?"super1":"rate"), + group: (faderMode[physicalChannel]?'[EffectRack1_EffectUnit'+theDeck.virtualChannel+']':"[Channel"+theDeck.virtualChannel+"]"), + before: function () { + this.input=components.Pot.prototype.input; + }, + layer4: function () { + this.input = function (channael, control, value, status, group) { + if (value>42&&value<=84) { + this.inKey="rate"; + this.group="[Channel"+theDeck.virtualChannel+"]"; + } else { + this.inKey="super1"; + this.group='[EffectRack1_EffectUnit'+theDeck.virtualChannel+']'; + } + }; + }, + }); }; -CALLBACK.fxButton = function() { - for (var channel = 1; channel <= 4; channel++) { - if (CMDMM.varStorage.channelKind[channel - 1]) { - switch (CMDMM.getLevel()) { - case 0: - var orientationButton = engine.getValue("[Channel" + CMDMM.varStorage.channelSequence[channel - 1] + "]", "orientation"); - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[(channel) * 2 - 1], orientationButton === 0 ? CMDMM.on : CMDMM.off); - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[(channel) * 2 - 0], orientationButton === 2 ? CMDMM.on : CMDMM.off); - break; - case 1: - for (var fxUnit = 1; fxUnit <= 2; fxUnit++) { - var effectUnitValue = engine.getValue("[EffectRack1_EffectUnit" + fxUnit + "]", "group_[Channel" + CMDMM.varStorage.channelSequence[channel - 1] + "]_enable"); - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[(channel - 1) * 2 + fxUnit], effectUnitValue ? CMDMM.on : CMDMM.off); - // ^strange but working solution to get values from 1 to 8 - } - break; - case 2: - for (var fxUnit = 3; fxUnit <= 4; fxUnit++) { - var effectUnitValue = engine.getValue("[EffectRack1_EffectUnit" + fxUnit + "]", "group_[Channel" + CMDMM.varStorage.channelSequence[channel - 1] + "]_enable"); - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[(channel - 1) * 2 + fxUnit - 2], effectUnitValue ? CMDMM.on : CMDMM.off); - // ^strange but working solution to get values from 1 to 8 - } - break; - case 3: - for (var i = 1; i <= 2; i++) { - midi.sendShortMsg(MIDI.noteOn, CMDMM.buttons[(channel - 1) * 2 + i], CMDMM.varStorage.ChannelAssignmentStatus[channel - 1][i - 1] ? CMDMM.on : CMDMM.off); - } - break; - } +CMDMM.fxChannel.prototype = new components.Deck(); + +CMDMM.init = function () { + CMDMM.Decks=[]; + for (i=0;i= 3 ? 1 : 0; + }); } -}; -FUNCTIONS.enableSoftTakeover = function() { - for (var i = 1; i <= 4; i++) { - engine.softTakeover("[QuickEffectRack1_[Channel" + i + "]]", "super1", true); - //engine.softTakeover("[Channel"+i+"]","rate",true); - engine.softTakeover("[Channel" + i + "]", "volume", true); - engine.softTakeover("[EffectRack1_EffectUnit" + i + "]", "mix", true); - engine.softTakeover("[EffectRack1_EffectUnit" + i + "]", "super1", true); - for (var ii = 1; ii <= 3; ii++) { - engine.softTakeover("[EqualizerRack1_[Channel" + i + "]_Effect1]", "parameter" + ii, true); - engine.softTakeover("[EffectRack1_EffectUnit" + i + "_Effect" + ii + "]", "meta", true); + CMDMM.shiftButton = new components.Button({ + midi: [MIDI.noteOn,0x10], + before: undefined, + after: undefined, + input: function (channel, control, value, status, group) { + CMDMM.currentLayer += this.isPress(channel, control, value, status)?1:-1; + CMDMM.layer(CMDMM.currentLayer); + CMDMM.reconnectComponents(); + }, + }); + CMDMM.ctrlButton = new components.Button({ + midi: [MIDI.noteOn,0x11], + before: undefined, + after: undefined, + input: function (channel, control, value, status, group) { + CMDMM.currentLayer += this.isPress(channel, control, value, status)?2:-2; + CMDMM.layer(CMDMM.currentLayer); + CMDMM.reconnectComponents(); } + }); + CMDMM.crossfader = new components.Pot({ + midi: [MIDI.CC,0x40], + inKey: "crossfader", + group: "[Master]", + }); + CMDMM.middleButton = new components.Button({ + midi:[MIDI.noteOn,0x12], + key: "crossfader", + group: "[Master]", + layer1: function () { + this.input = function () {this.inSetParameter(0.5);}; + this.output = function () {this.send(this.inGetParameter()===0.5);}; + }, + layer2: function () { + this.input = function () { + for (var i = 0; i