Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added mackie/c4/MIDI_Remote_for_the_Mackie_C4.pdf
Binary file not shown.
102 changes: 102 additions & 0 deletions mackie/c4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# MIDI Remote for the Mackie C4 (Version 1.03)

This script has been tested on an eLogic Mackie C4 that has version 1.02 firmware installed, and using Cubase Professional 12.0.20 and the E-mu 1x1 midi interface.

It has not been tested on a Mackie C4-Pro but since the protocol is the same, then other than potential detection issues, it should work.

## Installation

- Create folder structure \"mackie/c4\" inside \"../MIDI Remote/Driver
Scripts/Local\" folder.

- Copy the mackie_c4.js, mackie_c4_elements.js, mackie_c4_surface.js and
mackie_c4_page_eqmix.js files inside c4 folder.

- Connect your device.

- Start Cubase/Nuendo.

Since the midi name will likely be different for other users, the
.expectInputNameEquals and .expectOutputNameEquals were commented out of
the mackie_c4.js script and the user may want to uncomment them and
change for their own interface as seen below:

```
this.deviceDriver.makeDetectionUnit().detectPortPair(this.midiInput,this.midiOutput)

      .expectInputNameEquals(\'E-MU XMidi1X1\')

      .expectOutputNameEquals(\'E-MU XMidi1X1\')
```

As of Cubase version 12.0.10, the script can be added via the \"+\"
button, and MIDI ports can be assigned manually.

When your unit its detected, the serial number and version of the
firmware should print out in the MIDI Remote Script Console.

## Mackie C4 Pages

As of version 1.03, the following pages have been implemented:

- Equalizer Mixer Mode Page

### Equalizer Mixer Mode Page

This page implements the ability to control the parameters of the four
equalizer bands on each of the mixer channels as pictured in Figure 1.

#### Controls

- Row 1 Knobs -- Change the gain in decibels of the selected equalizer
on the selected channel.

- Row 2 Knobs -- Change the frequency in Hz of the selected equalizer
on the selected channel.

- Row 3 Knobs -- Change the Q factor of the selected equalizer on the
selected channel.

- Row 3 Knobs -- Change the Q filter type of the selected equalizer on
the selected channel.

- Row 3 Buttons -- Toggles the on/off state of the selected equalizer
on the selected channel.

- Next Bank – Select the next bank of 8 channels.

- Previous Bank - Select the previous bank of 8 channels.

- Next Channel (Single Right) – Shift by one to the next channel.

- Previous Channel (Single Left) - Shift by one to the previous channel.

- Next Equalizer Band (Slot Up) – Select the next equalizer band.

- Previous Equalizer Band (Slot Down) – Select the previous equalizer band.

![](images/media/mackie_c4_eqmix.jpg)

Figure 1 - Mackie C4 Equalizer Mixer Page

## Known Issues:

- When a value is changed withing Cubase, the LED updates to the
correct position but the display value on the Mackie C4 does not. It
the corresponding knob is nudged (one click to the right then left)
the values will sync up. A fix is being investigated.
- As of 12.0.20, after the script is refreshed, the first bank change will
result in empty display values. Subsequent bank changes will operate normally.

## Changelog (see github for detailed changes):

- V 1.00 4/22/2022 -- Initial Release
- V 1.01 4/26/2022 -- Fixed issue making updates more responsive.
- V 1.02 5/05/2022 – Fixed startup issue introduced with Cubase 12.0.20
- V 1.03 5/08/2022 – Swapped frequency and gain rows to align with the Cubase GUI

Script written by Ron Garrison

Contact: <[email protected]>

https://github.com/rwgarrison/midiremote-userscripts
Binary file added mackie/c4/images/media/mackie_c4_eqmix.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions mackie/c4/mackie_c4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var sw_rev = '1.03'

//-----------------------------------------------------------------------------
// 0. INCLUDE common functions
//-----------------------------------------------------------------------------

var mackieSurface = require('./mackie_c4_surface.js');
var MackieC4 = mackieSurface.MackieC4;

var mackiePageEqMix = require('./mackie_c4_page_eqmix.js');
var makeEqMixPage = mackiePageEqMix.makeEqMixPage;

//-----------------------------------------------------------------------------
// 1. DRIVER SETUP - create driver object, midi ports and detection information
//-----------------------------------------------------------------------------

var midiremote_api = require('midiremote_api_v1')
var deviceDriver = midiremote_api.makeDeviceDriver('mackie', 'c4', 'Ron Garrison')

//----------------------------------------------------------------------------------------------------------------------
// 2. SURFACE LAYOUT - create control elements and midi bindings
//----------------------------------------------------------------------------------------------------------------------

var mackieC4 = new MackieC4(deviceDriver, sw_rev);

//----------------------------------------------------------------------------------------------------------------------
// 3. HOST MAPPING - create mapping pages and host bindings
//----------------------------------------------------------------------------------------------------------------------

// Equalizer Mix Page

var eqMixPage = makeEqMixPage(deviceDriver, mackieC4);

eqMixPage.mOnActivate = function(context) {
//mackieC4.clearAll(context)
mackieC4.setLedStripText(1, 0, 'Band 1 ---------------Frequncy (Hz)---------------------');
//mackieC4.setLedStripText(1, 0, 'EQ1--------------------Gain (dB)------------------------');
mackieC4.setLedStripText(2, 0, 'Band 1 ----------------Q Factor-------------------------');
mackieC4.setLedStripText(3, 0, 'Band 1 --------Filter Type-(Push=on/off)----------------');
mackieC4.setLedStrip(context, 1, 0);
mackieC4.setLedStrip(context, 2, 0);
mackieC4.setLedStrip(context, 3, 0);
}

194 changes: 194 additions & 0 deletions mackie/c4/mackie_c4_elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/**
* PushEncoder class
*
* @constructor
* @param {MR_DeviceSurface} surface
* @param {MR_DeviceMidiInput} midiInput
* @param {MR_DeviceMidiOutput} midiOutput
* @param {number} x - x location of the push encoder in the gui
* @param {Number} y - y location of the push encoder in the gui
* @param {Number} w - width of the push encoder.
* @param {Number} h - height of the push encoder.
* @param {Number} instance - instance of the push encoder.
*/
function PushEncoder(surface, midiInput, midiOutput, x, y, w, h, instance) {

// Position on GUI
this.surface = surface;
this.midiInput = midiInput;
this.midiOutput = midiOutput;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.instance = instance;
this.row = Math.floor(this.instance/8);
this.column = this.instance % 8;

this.ident = function() {
return("Class pushEncoder");
}

// Mackie Pushencoder State
this.switchId = 32 + this.instance;
this.switchState = 0; // on, off
this.ledId = 0;
this.ledMode = 0; // on, off, flashing
this.vPotId = this.instance;
this.vPotValue = 0;
this.vPotLedRingId = 0;
this.vPotLedMode = 0; // singleDot, boostCut, wrap, spread
this.vPotLedOn = 0;
this.lcdId = 0;

this.labelText = ['------|', '------|'];

this.pushEncoder = this.surface.makePushEncoder(x, y, w, h)

// Bind push switches & encoders to note/control codes
this.pushEncoder.mEncoderValue.mMidiBinding
.setInputPort(midiInput)
.bindToControlChange (0, this.vPotId)
.setTypeRelativeSignedBit();

this.pushEncoder.mPushValue.mMidiBinding
.setInputPort(midiInput)
.bindToNote (0, this.switchId);
}

PushEncoder.prototype.setVPotLed = function(value) {
this.vPotValue = value;
}

PushEncoder.prototype.setVPotLedMode = function(mode) {
this.vPotLedMode = mode;
//var value = this.vPotValue + 16*this.vPotLedMode + 64*this.vPotLedOn
//this.midiOutput.sendMidi(context , [0xb0, this.instance + 32, 0]);
this.vPotLedMode = mode;
}

PushEncoder.prototype.setVPotCenterLed = function(on) {
this.vPotLedOn = on
}

PushEncoder.prototype.sendVPotLedMidi = function(context) {
var val = Math.round(1 + this.vPotValue*9.99) + 16*this.vPotLedMode + 64*this.vPotLedOn;
this.midiOutput.sendMidi(context , [0xb0, this.instance + 32, val]);
}

PushEncoder.prototype.clearVPotLed = function(context) {
this.midiOutput.sendMidi(context , [0xb0, this.instance + 32, 0]);
//this.vPotValue = 0;
}

PushEncoder.prototype.setLabelText = function(context, lower, labelText) {
// Need tom ove sysex to it's own class
var hdr = [0xF0, 0x00, 0x00, 0x66, 0x17];
var strip = (0x30 + Math.floor(this.instance/8));
var offset = ((this.instance % 8) * 7) + 56*lower;
var label = []
for (var i = 0; i < 7; i++) {
label = label.concat(labelText.charCodeAt(i));
}
var sysex = hdr.concat(strip, offset, label, 0xF7);
this.midiOutput.sendMidi(context, sysex);
}


/**
* Button class
*
* @constructor
* @param {MR_DeviceSurface} surface
* @param {MR_DeviceMidiInput} midiInput
* @param {MR_DeviceMidiOutput} midiOutput
* @param {number} x - x location of the push encoder in the gui
* @param {Number} y - y location of the push encoder in the gui
* @param {Number} w - width of the push encoder.
* @param {Number} h - height of the push encoder.
* @param {Number} id - instance of the push encoder.
*/
function Button(surface, midiInput, midiOutput, x, y, w, h, id) {

this.surface = surface;
this.midiInput = midiInput;
this.midiOutput = midiOutput;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.id = id;

this.buttonState = 0;

this.ident = function() {
return("Class Button");
}

// Bind button to note
this.button = this.surface.makeButton(x, y, w, h).setShapeCircle()

this.button.mSurfaceValue.mMidiBinding
.setInputPort(this.midiInput)
.bindToNote (0, this.id);
}

// Used to track the button state for buttons without an associated LED
Button.prototype.toggleButtonState = function(context) {
this.buttonState = 1 - this.buttonState;
}

// Used to track the button state and toggle the associated LED accordingly
Button.prototype.toggleButtonStateLed = function(context) {
this.buttonState = 1 - this.buttonState;
var value = this.buttonState *0x7F;
this.midiOutput.sendMidi(context , [0x90, this.id, value]);
}

// Used for teh split button. Cycles through 4 states and lights the LEDs accordingly
Button.prototype.cycleButtonStateLed = function(context) {
this.buttonState = (this.buttonState + 1) % 4;
switch (this.buttonState) {
case 0:
this.midiOutput.sendMidi(context , [0x90, this.id, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+1, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+2, 0]);
break;
case 1:
this.midiOutput.sendMidi(context , [0x90, this.id, 0x7F]);
this.midiOutput.sendMidi(context , [0x90, this.id+1, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+2, 0]);
break;
case 2:
this.midiOutput.sendMidi(context , [0x90, this.id, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+1, 0x7F]);
this.midiOutput.sendMidi(context , [0x90, this.id+2, 0]);
break;
case 3:
this.midiOutput.sendMidi(context , [0x90, this.id, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+1, 0]);
this.midiOutput.sendMidi(context , [0x90, this.id+2, 0x7F]);
break;
}
}

Button.prototype.setLedOn = function(context) {
this.midiOutput.sendMidi(context , [0x90, this.id, 0x7F]);
}

Button.prototype.setLedOff = function(context) {
this.midiOutput.sendMidi(context , [0x90, this.id, 0x00]);
}

Button.prototype.setLedFlashing = function(context) {
this.midiOutput.sendMidi(context , [0x90, this.id, 0x01]);
}





module.exports = {
PushEncoder,
Button
}
Loading