Xone K2 with 3 decks + 1 effect unit

Hello everyone,

I am working on a mapping for the Xone K2 using Mixxx 2.2.4.

Instead of using the standard configurations with either 2 decks and 2 effect units, or 4 decks/effect units, I want to customise the mapping to have 3 decks on the first 3 columns and an effect unit on the fourth.

I would like to leave the top part of the column as it is, and just change the 4 bottom buttons to assign the effects to Channel1, Channel2, Channel3 and Master (+eventually headphones by pressing shift).

I started by adding an extra configuration at the beginning of the script and setting the Xone to that channel (G):

 XoneK2.oneEffectUnitRight123EMidiChannel = 0x6;

In the init section I also add the corresponding lines to map 3 decks and an effect unit (note the extra parameter in the effect unit, see below)

channel = XoneK2.oneEffectUnitRight123EMidiChannel;
XoneK2.controllers[channel].columns[1] = new XoneK2.Deck(1, 1, channel);
XoneK2.controllers[channel].columns[2] = new XoneK2.Deck(2, 2, channel);
XoneK2.controllers[channel].columns[3] = new XoneK2.Deck(3, 3, channel);
XoneK2.controllers[channel].columns[4] = new XoneK2.EffectUnit(4, 1, channel, false,     true);
XoneK2.decksLayerButton(channel, null, null, 0x90 + channel, null);

I also adapted the EffectUnit to take the 3 decks into account:

this.bottomButtons = new components.ComponentContainer();
var channelString;
libraryEffectUnit.enableOnChannelButtons.addButton('Channel1');
this.bottomButtons[1] = libraryEffectUnit.enableOnChannelButtons.Channel1;
libraryEffectUnit.enableOnChannelButtons.addButton('Channel2');
this.bottomButtons[2] = libraryEffectUnit.enableOnChannelButtons.Channel2;

if (twoDeck === true) {
    print('2 DECKS 2 EFFECT UNITS')
    libraryEffectUnit.enableOnChannelButtons.addButton('Master');
    this.bottomButtons[3] = libraryEffectUnit.enableOnChannelButtons.Master;
    libraryEffectUnit.enableOnChannelButtons.addButton('Headphone');
    this.bottomButtons[4] = libraryEffectUnit.enableOnChannelButtons.Headphone;
} 
else if (threeDeck == true) {
    print('3 DECKS ACTIVE ONE EFFECT UNIT')

    this.bottomButtons[3] = new components.Button({
        group: unitString,
        unshift: function () {
            this.disconnect();
            this.inKey = 'group_[Channel3]_enable';
            this.outKey = 'group_[Channel3]_enable';
            this.color = XoneK2.color.red;
            this.connect();
            this.trigger();
        },
        shift: function () {
       
         },
        type: components.Button.prototype.types.toggle,
    });
    this.bottomButtons[4] = new components.Button({
        group: unitString,
        unshift: function () {
            this.disconnect();
            this.inKey = 'group_[Headphone]_enable';
            this.outKey = 'group_[Headphone]_enable';
            this.color = XoneK2.color.red;
            this.connect();
            this.trigger();
        },
        shift: function () {
            this.disconnect();
            this.inKey = 'group_[Master]_enable';
            this.outKey = 'group_[Master]_enable';
            this.color = XoneK2.color.amber;
            this.connect();
            this.trigger();
        },
        type: components.Button.prototype.types.toggle,
    });
}
else {
    print('ELSE')
    this.bottomButtons[3] = new components.Button({
        group: unitString,
        unshift: function () {
            this.disconnect();
            this.inKey = 'group_[Channel3]_enable';
            this.outKey = 'group_[Channel3]_enable';
            this.color = XoneK2.color.red;
            this.connect();
            this.trigger();
        },
        shift: function () {
            this.disconnect();
            this.inKey = 'group_[Master]_enable';
            this.outKey = 'group_[Master]_enable';
            this.color = XoneK2.color.amber;
            this.connect();
            this.trigger();
        },
        type: components.Button.prototype.types.toggle,
    });
    this.bottomButtons[4] = new components.Button({
        group: unitString,
        unshift: function () {
            this.disconnect();
            this.inKey = 'group_[Channel4]_enable';
            this.outKey = 'group_[Channel4]_enable';
            this.color = XoneK2.color.red;
            this.connect();
            this.trigger();
        },
        shift: function () {
            this.disconnect();
            this.inKey = 'group_[Headphone]_enable';
            this.outKey = 'group_[Headphone]_enable';
            this.color = XoneK2.color.amber;
            this.connect();
            this.trigger();
        },
        type: components.Button.prototype.types.toggle,
    });
}

I have been playing around for a while with this but something isn’t still quite right. Is this the right way to go or am I missing something important?

Any hints will be greatly appreciated :slight_smile:

Thanks a lot!

attached the .js file for more information

Allen-and-Heath-Xone-K2-scripts.js (39.9 KB)

Hello everybody,

is there any news regarding this? For me just knowing if I am pointed in the right direction would be more than enough

Thanks!

Hi, sorry for the delayed response. At a glance the code seems fine. If it works, it works.

Hello Be,

thanks for your reply, any help is greatly appreciated.

I am getting the following warning on my terminal when running Mixxx in Debug Mode:

“Failed to disconnect ([EffectRack1_EffectUnit4], group_[Channel4]_enable) from connection {10a4d15c-8618-4954-a410-06e9c84624f4}”

It seems to me that the FocusUnit, and more specifically the part where the containers are being reassigned, is trying to work with an EffectUnit4 where I only want to have one. Is this possible? Is there an elegant way to fix this? (see code below as provided in your code)

        // The containers must be reassigned to new objects before reassigning
        // the Components within them. Otherwise, the Components in
        // libraryEffectUnit will get reassigned too.
            this.knobs = new components.ComponentContainer();
            this.topButtons = new components.ComponentContainer();
            for (var k = 1; k <= 3; k++) {
                this.knobs[k] = new components.Pot({
                    group: '[EffectRack1_EffectUnit' + focusedUnitNumber + '_Effect' + k + ']',
                    inKey: 'parameter' + column,
                    unshift: function () {
                        this.input = function (channel, control, value, status, group) {
                            this.inSetParameter(this.inValueScale(value));

                            if (this.previousValueReceived === undefined) {
                                engine.softTakeover(this.group, this.inKey, true);
                            }
                            this.previousValueReceived = value;
                        };
                    },
                    shift: function () {
                        engine.softTakeoverIgnoreNextValue(this.group, this.inKey);
                        this.valueAtLastEffectSwitch = this.previousValueReceived;
                        // Floor the threshold to ensure that every effect can be selected
                        this.changeThreshold = Math.floor(this.max /
                            engine.getValue('[Master]', 'num_effectsavailable'));

                        this.input = function (channel, control, value, status, group) {
                            var change = value - this.valueAtLastEffectSwitch;
                            if (Math.abs(change) >= this.changeThreshold
                                // this.valueAtLastEffectSwitch can be undefined if
                                // shift was pressed before the first MIDI value was received.
                                || this.valueAtLastEffectSwitch === undefined) {
                                engine.setValue(this.group, 'effect_selector', change);
                                this.valueAtLastEffectSwitch = value;
                            }

                            this.previousValueReceived = value;
                        };
                    },
                });

                if (column === 1) {
                    this.topButtons[k] = new components.Button({
                        group: '[EffectRack1_EffectUnit' + focusedUnitNumber + '_Effect' + k + ']',
                        key: 'enabled',
                        type: components.Button.prototype.types.powerWindow,
                        color: XoneK2.color.amber,
                        outConnect: false, // midi is not defined yet
                    });
                } else {
                    this.topButtons[k] = new components.Button({
                        group: '[EffectRack1_EffectUnit' + focusedUnitNumber + '_Effect' + k + ']',
                        key: 'button_parameter' + (column-1),
                        type: components.Button.prototype.types.powerWindow,
                        color: XoneK2.color.green,
                        outConnect: false, // midi is not defined yet
                    });
                }
            }

Thanks a lot in advance

I don’t think I can answer that without seeing the whole script. But if it works, I’d suggest not worrying about the warning.

It is not working. There is no reaction when pushing buttons on the fourth channel, which is meant to be the effect unit, but also no error.

I attached the script for more information

Allen-and-Heath-Xone-K2-scripts.js (40.7 KB)

Hi @uriwilbury, did you manage to get any further with this script? I’ve just moved to Mixxx from Traktor and I find the integration with the K2 to be great, the only thing missing is the option for 3 decks + 1 effect which is the setup I used with Traktor, so i’m very interested in seeing if this works out. Let me know if there is anything I can help with testing, I’m on Big Sur + Mixxx 2.3 beta. Cheers.

Hi @slurred!

No, unfortunately I didn’t have the time to keep working on it.

The problem seems to be related to the Focus Unit.

Did you test the script on Mixxx 2.3? I am still using 2.2x but would like to switch to the 2.3 :slight_smile: