Samson Conspiracy MIDI Controller working with QLC+
Posted: Tue Dec 24, 2019 10:03 pm
I got it working in my Linux 64 bits, after a long struggle battle.
What I did? I created a MIDI translator using NodeJs (which one I kindly called midi3po { qlc midi controllers relationship droid }).
I will share the code index.js I used and if can edit the "names" to match your system names..
If anyone got interested I can share more details about setup..
I am planning to use the matrix button colors to match the fixture selected (each matrix button is a par 54 leds).
This controller also has a x/y pad to setup moving heads.
(in case you think the 127 range to 254 range is an issue, I got some range selectors to help with this..)
// index.js
// and on package.json
// .nvmrc
npm i && npm start && echo "be happy"
What I did? I created a MIDI translator using NodeJs (which one I kindly called midi3po { qlc midi controllers relationship droid }).
I will share the code index.js I used and if can edit the "names" to match your system names..
If anyone got interested I can share more details about setup..
I am planning to use the matrix button colors to match the fixture selected (each matrix button is a par 54 leds).
This controller also has a x/y pad to setup moving heads.
(in case you think the 127 range to 254 range is an issue, I got some range selectors to help with this..)
// index.js
Code: Select all
/*
* Matrix Buttons COLORS
*
* 0 - off
* 1 - RED
* 2 - GREEN
* 3 - BLUE
* 4 - off
* 5 - off
* 6 - off
* 7 - off
* 8 - RED + GREEN = YELLOW
* 9 - RED + GREEN = YELLOW
* 10 - RED + GREEN = YELLOW
* 11 - RED + GREEN = YELLOW
* 12 - off
* 13 - RED + GREEN = YELLOW
* 14 - off
* 15 - off
* 16 - off
* 17 - off
* 18 - off
* 19 - RED + GREEN = YELLOW
* 20 - off
* 21 - RED
* 22 - GREEN
* 23 - RED + GREEN = YELLOW
* 24 - BLUE
* 25 - RED + BLUE = MAGENTA
* 26 - GREEN + BLUE = CYAN
* 27 - ALL = WHITE
* 28 - off
* 29 - RED
* 30 - GREEN
* 31 - YELLOW
* 32 - BLUE
* 33 - MAGENTA
* 34 - CYAN
* 35 - WHITE
* 36 - off
* 37 - RED
* 38 - GREEN
* 39 - YELLOW
* 40 - BLUE
*/
const easymidi = require("easymidi");
const inputs = easymidi.getInputs();
const outputs = easymidi.getOutputs();
console.log("Inputs: ");
console.log(inputs);
console.log("Outputs: ");
console.log(outputs);
const qlcIn = new easymidi.Input("MIDI 3PO QLC INPUT", true);
const qlcOut = new easymidi.Output("MIDI 3PO QLC OUTPUT", true);
const consIn = new easymidi.Input("Conspiracy:Conspiracy MIDI 1 20:0");
const consOut = new easymidi.Output("Conspiracy:Conspiracy MIDI 1 20:0");
console.log("Virtual QLC Input:");
console.log(qlcIn);
console.log("Virtual QLC Output:");
console.log(qlcOut);
console.log("Conspiracy Input:");
console.log(consIn);
console.log("Conspiracy Output:");
console.log(consOut);
/* CONS INPUT RACE */
// FOR CC
consIn.on("cc", msg => {
console.log("_____________________________________________________");
console.log("FROM Conspiracy INPUT");
console.log("cc", msg.controller, msg.value, msg.channel);
// Filter for F1 to F10 functions makes the SIGNAL
// on Release instead of on push
if (
msg.controller >= 20 &&
msg.controller <= 29 &&
(msg.channel === 1 || msg.channel === 2)
) {
msg.value = msg.value === 127 ? 0 : 127;
console.log("sent to qlc: ");
console.log("cc", msg);
qlcOut.send("cc", msg);
return;
}
// basic thru if no filters
qlcOut.send("cc", msg);
});
// FOR NOTEON // NOTEOFF
consIn.on("noteon", msg => {
// Matrix is noteon/off 36 ~ 60 channel 1
// should respond feedback is noteon/off 0 ~ 25 (transposed) channel 0
console.log("_____________________________________________________");
console.log("FROM Conspiracy INPUT");
console.log("noteon", msg.note, msg.velocity, msg.channel);
// basic thru if no filters
// qlcOut.send("noteon", msg); // ignore
});
consIn.on("noteoff", msg => {
console.log("_____________________________________________________");
console.log("FROM Conspiracy INPUT");
console.log("noteoff", msg.note, msg.velocity, msg.channel);
// change the velocity from the minimum to the max
msg.velocity = 127;
// basic thru if no filters
qlcOut.send("noteon", msg); // translates to the onRelease
});
// ____________________________________________________________________
/* QLC FEEDBACK RACE */
qlcIn.on("cc", msg => {
console.log("-----------------------------------------------------");
console.log("FROM QLC FEEDBACK");
console.log("cc", msg.controller, msg.value, msg.channel);
// Filter F1 ~ F9 functions buttons
if (msg.controller >= 20 && msg.controller <= 28 && msg.channel === 1) {
msg = filterToFunctionValue(msg);
const transNote = {
note: msg.controller + 5,
velocity: msg.value,
channel: msg.channel - 1
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// ENDOF Filter F1 ~ F9 functions buttons
// Filter F10 function button
if (msg.controller === 29 && msg.channel === 1) {
msg = filterToFunctionValue(msg);
const transNote = {
note: msg.controller + 12,
velocity: msg.value,
channel: msg.channel - 1
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// ENDOF Filter F10 function button
// Midia BUTTONS
// Filter Back Button
if (msg.controller == 20 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 34,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Next Button
if (msg.controller == 21 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 36,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Up Button
if (msg.controller == 22 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 35,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Down Button
if (msg.controller == 23 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 37,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Play Button
if (msg.controller == 24 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 38,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Stop Button
if (msg.controller == 25 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 39,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// Filter Record Button
if (msg.controller == 26 && msg.channel === 2) {
msg = filterToMidiaValue(msg);
const transNote = {
note: 40,
velocity: msg.value,
channel: 0
};
console.log("sent to conspiracy: ");
console.log("noteon", transNote);
consOut.send("noteon", transNote);
console.log(".................................................");
return;
}
// ENDOF Filter Play/Stop.. buttons
// basic thru if no filters
consOut.send("cc", msg);
});
const filterToFunctionValue = msg => {
// basic value fixes:
if (msg.value === 127) {
msg.value = 42;
}
if (msg.value === 0) {
msg.value = 43;
}
// ENDOF basic value fixes:
return msg;
};
const filterToMidiaValue = msg => {
// basic value fixes:
if (msg.value === 127) {
msg.value = 1;
}
if (msg.value === 0) {
msg.value = 2;
}
// ENDOF basic value fixes:
return msg;
};
/* QLC FEEDBACK RACE FOR NOTEON / NOTEOFF */
qlcIn.on("noteon", msg => {
console.log("-----------------------------------------------------");
console.log("FROM QLC FEEDBACK");
console.log("noteon", msg.note, msg.velocity, msg.channel);
// first botton line
if (msg.channel === 1 && msg.note >= 36 && msg.note <= 40) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 + 20;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// second botton line
if (msg.channel === 1 && msg.note >= 41 && msg.note <= 45) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 + 10;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// third botton line
if (msg.channel === 1 && msg.note >= 46 && msg.note <= 50) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// fourth botton line
if (msg.channel === 1 && msg.note >= 51 && msg.note <= 55) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 - 10;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// fifth botton line
if (msg.channel === 1 && msg.note >= 56 && msg.note <= 60) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 - 20;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// basic thru if no filters
consOut.send("noteon", msg);
});
qlcIn.on("noteoff", msg => {
console.log("-----------------------------------------------------");
console.log("FROM QLC FEEDBACK");
console.log("noteoff", msg.note, msg.velocity, msg.channel);
// first botton line
if (msg.channel === 1 && msg.note >= 36 && msg.note <= 40) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 + 20;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// second botton line
if (msg.channel === 1 && msg.note >= 41 && msg.note <= 45) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 + 10;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// first botton line
if (msg.channel === 1 && msg.note >= 46 && msg.note <= 50) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// first botton line
if (msg.channel === 1 && msg.note >= 51 && msg.note <= 55) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 - 10;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// first botton line
if (msg.channel === 1 && msg.note >= 56 && msg.note <= 60) {
msg = filterToMatrixValue(msg);
msg.channel = 0;
msg.note = msg.note - 36 - 20;
console.log("sent to conspiracy: ");
console.log("noteon", msg);
consOut.send("noteon", msg);
}
// basic thru if no filters
consOut.send("noteoff", msg);
});
const filterToMatrixValue = msg => {
// basic value fixes:
if (msg.velocity === 127) {
msg.velocity = 22;
}
if (msg.velocity === 0) {
msg.velocity = 23;
}
// ENDOF basic value fixes:
return msg;
};
Code: Select all
{
"name": "midi3po",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"author": "ssribeiro",
"license": "ISC",
"dependencies": {
"easymidi": "^1.0.3"
}
}
Code: Select all
v10.18.0