Skip to content

Commit

Permalink
Support for Mixxx 2.4 hotcue loops.
Browse files Browse the repository at this point in the history
  • Loading branch information
illusori committed Jul 11, 2023
1 parent 6e319ec commit b60d216
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 12 deletions.
58 changes: 55 additions & 3 deletions Behringer-CMDStudio2a-Enhanced-scripts.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// ****************************************************************************
// * Mixxx mapping script file for the Behringer CMD Studio 2a.
// * Author: Sam Graham, based on Rafael Ferran, Barney Garrett and Xxx previous works
// * Version 0.2 (Nov 2020)
// * Version 0.3 (Jul 2023)
// * Forum: http://www.mixxx.org/forums/viewtopic.php?f=7&t=7868
// * Wiki: http://www.mixxx.org/wiki/doku.php/behringer_cmd_studio_4a
// ****************************************************************************
Expand Down Expand Up @@ -91,6 +91,9 @@ controller.vinylButton = false;
// Status: pushed/not pushed of minus and plus buttons.
controller.minusPlusPushed = [{ plus: false, minus: false }, { plus: false, minus: false }];

// Status: pushed/not pushed of assign B buttons.
controller.assignBState = [{ pushed: false, ignoreRelease: false, timer: null }, { pushed: false, ignoreRelease: false, timer: null }];

// File and Folder buttons for library navigation
controller.folderButton = true; // Default is ON
controller.fileButton = false;
Expand Down Expand Up @@ -342,7 +345,7 @@ controller.cycleEditMode = function (deck) {
}

// Assign A button: cycle through edit modes: OFF/MODE1/MODE2
controller.assignButtonsPush = function (channel, control, value, status, group) {
controller.assignAButtonsPush = function (channel, control, value, status, group) {
if (value === 127) {
// Button pushed
if (this.debug) {
Expand All @@ -354,6 +357,39 @@ controller.assignButtonsPush = function (channel, control, value, status, group)
}
}

// Assign B button:
// PRESS: toggle loop
// shift+PRESS: remove loop
// HOLD+hotcue: save to loop hotcue if unset, load from hotcue if set
controller.assignBButtonsPush = function (channel, control, value, status, group) {
var deck = script.deckFromGroup(group);
var buttonState = this.assignBState[deck - 1];

buttonState.pushed = (value === 127);
if (value === 127) { // Button pushed
buttonState.ignoreRelease = false;
// set delay timer to set ignoreRelease after 500ms
buttonState.timer = engine.beginTimer(500, function () {
buttonState.ignoreRelease = true;
engine.stopTimer(buttonState.timer);
buttonState.timer = null;
});
} else {
if (!buttonState.ignoreRelease) {
if (this.modeShifted()) {
engine.setValue(group, "loop_remove", 1);
} else {
engine.setValue(group, "reloop_toggle", 1);
}
}
if (buttonState.timer) {
engine.stopTimer(buttonState.timer);
buttonState.timer = null;
}
}
buttonState.ignoreRelease = false;
}



// Vinyl button ON/OFF
Expand Down Expand Up @@ -585,8 +621,24 @@ controller.hotCueButtons = function (channel, control, value, status, group) {
var deck = script.deckFromGroup(group);
var deckName = this.deckNames[deck - 1];
var button = control - this.controls[deckName + 'Hotcue1'] + 1;
var bState = this.assignBState[deck - 1];

if (this.editMode[deck - 1] === this.editModes.loop) {
if (bState.pushed) {
// Loop button (Assign B) is held.
// SHIFT: clear hotcue
// set: activate loop from hotcue
// unset: save loop to hotcue
if (!this.modeShifted()) {
if (engine.getValue(group, "hotcue_" + button + "_status")) {
engine.setValue(group, "hotcue_" + button + "_activateloop", 1);
} else {
engine.setValue(group, "hotcue_" + button + "_setloop", 1);
}
} else {
engine.setValue(group, "hotcue_" + button + "_clear", 1);
}
bState.ignoreRelease = true;
} else if (this.editMode[deck - 1] === this.editModes.loop) {
var beats = this.beatLoops[button - 1];
if (!this.modeShifted()) {
// Not mode Shift
Expand Down
36 changes: 28 additions & 8 deletions Behringer-CMDStudio2a-Enhanced.midi.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<MixxxControllerPreset schemaVersion="1" mixxxVersion="2.0.0+">
<MixxxControllerPreset schemaVersion="1" mixxxVersion="2.4.0+">
<info>
<name>Behringer CMD STUDIO 2a (Enhanced)</name>
<author>Sam Graham, based on Barney Garrett, LucidityCrash, and Rafael Ferran previous works</author>
<description>Controller mapping for the Behringer CMD STUDIO 2a. V 0.2 Created Nov 2020 for Mixxx 2.3.0</description>
<description>Controller mapping for the Behringer CMD STUDIO 2a. V 0.3 Created Jul 2023 for Mixxx 2.4.0</description>
<forums>https://www.mixxx.org/forums/viewtopic.php?f=7&amp;t=9359</forums>
<wiki>https://www.mixxx.org/wiki/doku.php/behringer_cmd_studio_2a</wiki>
</info>
Expand Down Expand Up @@ -351,7 +351,7 @@
</control>
<control>
<group>[Channel1]</group>
<key>BehringerCMDStudio2a.assignButtonsPush</key>
<key>BehringerCMDStudio2a.assignAButtonsPush</key>
<description>Deck 1, Assign A button</description>
<status>0x90</status>
<midino>0x08</midino>
Expand All @@ -361,17 +361,27 @@
</control>
<control>
<group>[Channel1]</group>
<key>reloop_exit</key>
<key>BehringerCMDStudio2a.assignBButtonsPush</key>
<description>Deck 1, Assign B button</description>
<status>0x90</status>
<midino>0x09</midino>
<options>
<normal/>
<script-binding/>
</options>
</control>
<control>
<group>[Channel1]</group>
<key>BehringerCMDStudio2a.assignBButtonsPush</key>
<description>Deck 1, Assign B button release</description>
<status>0x80</status>
<midino>0x09</midino>
<options>
<script-binding/>
</options>
</control>
<control>
<group>[Channel2]</group>
<key>BehringerCMDStudio2a.assignButtonsPush</key>
<key>BehringerCMDStudio2a.assignAButtonsPush</key>
<description>Deck 2, Assign A button</description>
<status>0x90</status>
<midino>0x38</midino>
Expand All @@ -381,12 +391,22 @@
</control>
<control>
<group>[Channel2]</group>
<key>reloop_exit</key>
<key>BehringerCMDStudio2a.assignBButtonsPush</key>
<description>Deck 2, Assign B button</description>
<status>0x90</status>
<midino>0x39</midino>
<options>
<normal/>
<script-binding/>
</options>
</control>
<control>
<group>[Channel2]</group>
<key>BehringerCMDStudio2a.assignBButtonsPush</key>
<description>Deck 2, Assign B button release</description>
<status>0x80</status>
<midino>0x39</midino>
<options>
<script-binding/>
</options>
</control>
<control>
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Behringer CMD Studio 2a controller
# Behringer CMD Studio 2a controller, version 0.3 (July 2023)

Updated controller mappings for Mixxx for the Behringer CMD Studio 2a controller.

Placeholder repo until I update it for merge to upstream.

## New in 0.3 (July 2023)

* Loop saving controls. (Requires Mixxx 2.4 or greater.)

# Control scheme

Based off https://github.com/mixxxdj/mixxx/wiki/behringer_cmd_studio_2a, refer to those docs for a starter.
Expand Down Expand Up @@ -42,6 +46,8 @@ The *Vinyl* button will toggle between vinyl mode on/off, unless you're mode-shi

With mode-shift or mode-lock on, pressing the *Vinyl* button will toggle recording mode.

This keybind doesn't make a whole lotta logical sense, but I wanted to have recording toggleable from just the controller and this was the least-confusing place to put it.

### Sync Button.

With mode-shift or mode-lock on, pressing the *Sync* button will disable sync lock and reset the deck playback rate to default.
Expand Down Expand Up @@ -95,3 +101,14 @@ This is the default behaviour from the old controller mapping.
Intent of this mode is to help you prepare or cue up a track.

How you make use of the hotcues is up to you, but I like to stick the start/end of the beat or the melody (whichever makes sense for the track) on hotcue 5 and 7, and colour them Green for Groove; then stick start/end vocals on 6 and 8, colouring them Violet for Vocals.

### Assign B button

The *Assign B* button is your loop enable/disable/remove and save/load button.

* Press once to toggle whether your current loop is enabled or disabled.
* With mode-shift or mode-lock active *Assign B* will delete the current loop.
* If you hold *Assign B* down, pressing the hotcue 1-4 buttons will save the current loop to the hotcue or load it if one is already saved.
* Holding *Assign B* while mode-shifted or mode-locked and pressing hotcue 1-4 will clear the hotcue. This finger-twister is provided to preserve expected button combo behaviours, but you may find it easier to just use the regular hotcue clearing controls from within sample editing mode.

For simplicity, hotcues 5-8 aren't reachable for now to save loops to. This may change in a future version.

0 comments on commit b60d216

Please sign in to comment.