Commit f39ab046 authored by TJ Horner's avatar TJ Horner

2.0.0

parent 2ab367e2
......@@ -4,42 +4,6 @@ A node module for interacting with the Launchpad MK2 and Launchpad Pro. Except t
If you're looking for a module to interact with the original Launchpad or Launchpad S, check [here](https://www.npmjs.com/package/midi-launchpad).
## Self-documenting example
# VERSION 2.0.0 HAS MAJOR BREAKING CHANGES
```javascript
var LaunchpadMK2 = require('launchpad-mk2'), // require the module
// create a new Launchpad instance
launchpad = new LaunchpadMK2.connect({
in: 0 // the input port of the launchpad
out: 0 // the output port
type: LaunchpadMK2.types.PRO // PRO/MK2 (PRO only works now)
});
// on button press
launchpad.on("press", function(button, velocity){
// a Button instance
console.log(button);
// the grid is set up where the bottom left pad is (1, 1)
console.log(button.x, button.y);
// set a button's color
// pass getColor an RGB value and it will find the closest color the launchpad can display
button.setColor(LaunchpadMK2.getColor(255, 0, 255));
// darken a button
button.darken();
// get the MIDI note for this button
console.log(button.getNote());
// since the pads are pressure-sensitive, velocity is passed as well
console.log(velocity);
});
// on button release
launchpad.on("release", function(button){
// a Button instance
console.log(button);
});
```
The entire module has been rewritten to be more modern and use ES6 features. The new API will be documented sometime in the future.
\ No newline at end of file
function Button(launchpad, note){
var self = this;
var noteAsString = note.toString().split("");
if(noteAsString[1] === "0"){
// left button
this.x = 0;
this.y = parseInt(noteAsString[0]);
}else if(!noteAsString[1]){
// bottom button
this.x = parseInt(noteAsString[0]);
this.y = 0;
}else{
// any other
this.x = parseInt(noteAsString[1]) || 0;
this.y = parseInt(noteAsString[0]) || 0;
class Button{
constructor(launchpad, note) {
this.launchpad = launchpad
this.note = note
var noteAsString = note.toString().split("")
if(noteAsString[1] === "0"){
// left button
this.x = 0
this.y = parseInt(noteAsString[0])
}else if(!noteAsString[1]){
// bottom button
this.x = parseInt(noteAsString[0])
this.y = 0
}else{
// any other
this.x = parseInt(noteAsString[1]) || 0
this.y = parseInt(noteAsString[0]) || 0
}
this.color = 0
}
this.note = note;
this.color = 0;
this.toNote = function(){
return self.note;
}
this.setColor = function(color){
launchpad._output.sendMessage([144, self.toNote(), color]);
setColor(color) {
this.launchpad._output.sendMessage([144, this.note, color])
}
this.pulseColor = function(color){
launchpad.sendSysEx([40, self.toNote(), color]);
pulseColor(color) {
this.launchpad.sendSysEx([40, this.note, color])
}
// rgb values 0-63
this.setRgbColor = function(r, g, b){
launchpad.sendSysEx([11, self.toNote(), r, g, b]);
setRgbColor(r, g, b) {
this.launchpad.sendSysEx([11, this.note, r, g, b])
}
this.getColor = function(){
return self.color;
darken() {
this.launchpad._output.sendMessage([144, this.note, 0])
}
this.darken = function(){
launchpad._output.sendMessage([144, self.toNote(), 0]);
}
return this;
}
module.exports = Button;
module.exports = Button
// TODO we don't need this anymore
// since I discovered sysex messages
var launchColors = require('./colors.json');
Array.min = function(array){
return Math.min.apply(Math, array);
};
module.exports = {
getLaunchpadColor: function(r, g, b){
var differenceArray = [ ];
launchColors.forEach(function(value, index){
var launchColorR = value[0];
var launchColorG = value[1];
var launchColorB = value[2];
differenceArray.push(Math.sqrt((r-launchColorR)*(r-launchColorR)+(g-launchColorG)*(g-launchColorG)+(b-launchColorB)*(b-launchColorB)));
});
var lowest = Array.min(differenceArray);
var index = differenceArray.indexOf(lowest);
return index;
}
}
[
[0, 0, 0],
[33, 33, 33],
[139, 139, 139],
[251, 251, 251],
[255, 100, 87],
[255, 41, 0],
[110, 10, 0],
[34, 1, 0],
[255, 197, 114],
[255, 108, 0],
[110, 36, 0],
[47, 26, 0],
[251, 247, 37],
[251, 247, 0],
[104, 102, 0],
[26, 25, 0],
[139, 246, 52],
[63, 245, 0],
[19, 101, 0],
[16, 52, 0],
[47, 245, 52],
[0, 245, 0],
[0, 101, 0],
[0, 25, 0],
[47, 246, 87],
[0, 245, 0],
[0, 101, 0],
[0, 25, 0],
[48, 246, 143],
[0, 245, 70],
[0, 101, 25],
[0, 32, 18],
[39, 247, 189],
[0, 247, 162],
[0, 102, 59],
[0, 25, 18],
[63, 202, 255],
[0, 182, 255],
[0, 77, 99],
[0, 18, 26],
[80, 152, 255],
[0, 108, 255],
[0, 38, 109],
[0, 4, 33],
[88, 100, 255],
[4, 51, 255],
[1, 16, 109],
[0, 2, 33],
[150, 101, 255],
[100, 53, 255],
[27, 18, 119],
[10, 6, 65],
[255, 106, 255],
[255, 64, 255],
[110, 22, 109],
[34, 3, 33],
[255, 102, 148],
[255, 43, 98],
[110, 11, 33],
[41, 2, 18],
[255, 52, 0],
[173, 68, 0],
[140, 98, 0],
[75, 117, 0],
[0, 69, 0],
[0, 97, 65],
[0, 100, 144],
[4, 51, 255],
[0, 82, 93],
[34, 42, 219],
[139, 139, 139],
[40, 40, 40],
[255, 40, 0],
[196, 246, 0],
[183, 235, 0],
[96, 246, 0],
[0, 149, 0],
[0, 246, 139],
[0, 182, 255],
[3, 61, 255],
[67, 51, 255],
[136, 54, 255],
[195, 48, 144],
[83, 41, 0],
[255, 94, 0],
[145, 226, 0],
[113, 246, 0],
[0, 245, 0],
[0, 245, 0],
[70, 246, 114],
[0, 248, 210],
[97, 153, 255],
[45, 11, 210],
[149, 144, 239],
[221, 63, 255],
[255, 44, 109],
[255, 145, 0],
[198, 186, 0],
[149, 246, 0],
[149, 108, 0],
[71, 53, 0],
[0, 91, 2],
[0, 97, 71],
[18, 20, 53],
[18, 44, 109],
[125, 77, 25],
[187, 24, 0],
[233, 103, 64],
[229, 125, 0],
[255, 228, 0],
[164, 226, 0],
[111, 189, 0],
[33, 34, 59],
[226, 247, 98],
[129, 248, 193],
[167, 170, 255],
[154, 123, 255],
[77, 77, 77],
[134, 134, 134],
[226, 251, 251],
[178, 23, 0],
[66, 3, 0],
[0, 209, 0],
[0, 75, 0],
[198, 186, 0],
[77, 59, 0],
[195, 110, 0],
[88, 27, 0]
]
var midi = require('midi'),
color = require('./helpers/color'),
Button = require('./helpers/button'),
EventEmitter = require('events'),
util = require('util');
var types = {
PRO: 0,
MK2: 1
};
function Launchpad(params){
EventEmitter.call(this);
var self = this;
const midi = require('midi'),
Button = require('./helpers/button'),
EventEmitter = require('events'),
util = require('util')
var layouts = {
NOTE: 0,
DRUM: 1,
FADE: 2,
PROGRAMMER: 3
}
this.type = params.type;
class Launchpad extends EventEmitter {
constructor(params) {
super()
this._input = new midi.input();
this._output = new midi.output();
this.buttons = [ ]
this._input = new midi.input()
this._output = new midi.output()
self._input.openPort(params.in);
this._input.openPort(params.in)
self._input.on("message", function(dTime, message){
if(message[0] === 176 || message[0] === 144){
// button message
if(message[2] > 0){
self.emit("press", self.buttons[message[1]], message[2]);
}else{
self.emit("release", self.buttons[message[1]]);
this._input.on("message", (dTime, message) => {
if(message[0] === 176 || message[0] === 144){
// button message
if(message[2] > 0)
this.emit("press", this.buttons[message[1]], message[2])
else
this.emit("release", this.buttons[message[1]])
}
}
});
})
self._output.openPort(params.out);
this._output.openPort(params.out)
this.buttons = [ ];
if(self.type === types.PRO){
for(var i=0;i<100;i++){
self.buttons.push(new Button(self, i));
}
}else{
throw new Error("// TODO: Implement MK2 support.");
for(var i=0;i<100;i++)
this.buttons.push(new Button(self, i))
}
// convenience method for adding the header and terminator to sysex messages
this.sendSysEx = function(bytes){
sendSysEx(bytes){
// sysex header
var message = [240, 0, 32, 41, 2, 16];
var message = [240, 0, 32, 41, 2, 16]
// sysex message
bytes.forEach(function(byte){
message.push(byte);
});
bytes.forEach(byte => message.push(byte))
// sysex terminator
message.push(247);
// console.log("sysex", message);
self._output.sendMessage(message);
message.push(247)
// console.log("sysex", message)
this._output.sendMessage(message)
}
this.getButton = function(x, y){
return self.buttons[(x.toString() === "0" ? "" : x.toString()) + y.toString()];
getButton(x, y) {
return this.buttons[(x.toString() === "0" ? "" : x.toString()) + y.toString()]
}
this.lightAll = function(color){
self.sendSysEx([14, color]);
// self.buttons.forEach(function(button){
// button.setColor(color);
// });
lightAll(color) {
this.sendSysEx([14, color])
}
this.lightAllRgb = function(r, g, b){
self.buttons.forEach(function(button){
button.setRgbColor(r, g, b);
});
lightAllRgb(r, g, b) {
this.buttons.forEach(button => button.setRgbColor(r, g, b))
}
this.darkAll = function(){
self.buttons.forEach(function(button){
button.setColor(0);
});
darkAll() {
this.buttons.forEach(button => button.setColor(0))
}
this.toLayout = function(layout){
self._output.sendMessage([240, 0, 32, 41, 2, 16, 44, layout, 247]);
toLayout(layout) {
this._output.sendMessage([240, 0, 32, 41, 2, 16, 44, layouts[layout], 247])
}
this.scrollText = function(text, color, loop, speed){
var message = [20, color, loop];
for(var i=0;i<text.length;i++){
message.push(text.charCodeAt(i));
}
self.sendSysEx(message);
if(speed) self.sendSysEx([20, color, loop, speed]);
}
scrollText(text, color, loop, speed) {
var message = [20, color, loop]
return this;
for(var i=0;i<text.length;i++)
message.push(text.charCodeAt(i))
this.sendSysEx(message)
if(speed) this.sendSysEx([20, color, loop, speed])
}
}
util.inherits(Launchpad, EventEmitter);
module.exports = {
connect: Launchpad,
types: types,
getColor: color.getLaunchpadColor,
layouts: {
NOTE: 0,
DRUM: 1,
FADE: 2,
PROGRAMMER: 3
}
};
module.exports = Launchpad
\ No newline at end of file
var midi = require('midi'),
color = require('./helpers/color'),
Button = require('./helpers/button'),
EventEmitter = require('events'),
util = require('util');
var types = {
PRO: 0,
MK2: 1
};
function Launchpad(params){
EventEmitter.call(this);
var self = this;
this.type = params.type;
this._input = new midi.input();
this._output = new midi.output();
self._input.openPort(params.in);
self._input.on("message", function(dTime, message){
if(message[0] === 176 || message[0] === 144){
// button message
if(message[2] > 0){
self.emit("press", self.buttons[message[1]], message[2]);
}else{
self.emit("release", self.buttons[message[1]]);
}
}
});
self._output.openPort(params.out);
this.buttons = [ ];
if(self.type === types.PRO){
for(var i=0;i<100;i++){
self.buttons.push(new Button(self, i));
}
}else{
throw new Error("// TODO: Implement MK2 support.");
}
// convenience method for adding the header and terminator to sysex messages
this.sendSysEx = function(bytes){
// sysex header
var message = [240, 0, 32, 41, 2, 16];
// sysex message
bytes.forEach(function(byte){
message.push(byte);
});
// sysex terminator
message.push(247);
// console.log("sysex", message);
self._output.sendMessage(message);
}
this.getButton = function(x, y){
return self.buttons[(x.toString() === "0" ? "" : x.toString()) + y.toString()];
}
this.lightAll = function(color){
self.sendSysEx([14, color]);
// self.buttons.forEach(function(button){
// button.setColor(color);
// });
}
this.lightAllRgb = function(r, g, b){
self.buttons.forEach(function(button){
button.setRgbColor(r, g, b);
});
}
this.darkAll = function(){
self.buttons.forEach(function(button){
button.setColor(0);
});
}
this.toLayout = function(layout){
self._output.sendMessage([240, 0, 32, 41, 2, 16, 44, layout, 247]);
}
this.scrollText = function(text, color, loop, speed){
var message = [20, color, loop];
for(var i=0;i<text.length;i++){
message.push(text.charCodeAt(i));
}
self.sendSysEx(message);
if(speed) self.sendSysEx([20, color, loop, speed]);
}
return this;
}
util.inherits(Launchpad, EventEmitter);
module.exports = {
connect: Launchpad,
types: types,
getColor: color.getLaunchpadColor,
layouts: {
NOTE: 0,
DRUM: 1,
FADE: 2,
PROGRAMMER: 3
}
};
{
"name": "launchpad-mk2",
"version": "1.0.4",
"version": "2.0.0",
"description": "Node module for interfacing with the Launchpad MK2 and Launchpad Pro",
"repository": "https://github.com/tjhorner/node-launchpad-mk2",
"main": "index.js",
......
// TODO: actual tests
var Launchpad = require('..'),
launchpad = new Launchpad.connect({
launchpad = new Launchpad({
in: 1,
out: 1,
type: Launchpad.types.PRO
});
out: 1
})
launchpad.toLayout(Launchpad.layouts.PROGRAMMER);
launchpad.toLayout("PROGRAMMER")
launchpad.darkAll();
launchpad.darkAll()
// launchpad.getButton(8, 1).setColor(Launchpad.getColor(255, 0, 0));
// launchpad.getButton(1, 1).setColor(Launchpad.getColor(0, 255, 0));
// launchpad.getButton(8, 8).setColor(Launchpad.getColor(255, 255, 0));
// launchpad.getButton(1, 8).setColor(Launchpad.getColor(0, 0, 255));
launchpad.scrollText("launchpad-mk2 node module", 50, 0, 6);
launchpad.scrollText("launchpad-mk2 node module", 50, 0, 6)
launchpad.on("press", function(button, velocity){
console.log("Button", button.x, button.y, "pressed with velocity", velocity);
// button.setColor(Math.floor((Math.random() * 127) + 1));
button.pulseColor(Math.floor((Math.random() * 127) + 1));
// button.setRgbColor(30, 10, 0);
if(button.x === 1 && button.y === 0) launchpad.darkAll();
});
console.log("Button", button.x, button.y, "pressed with velocity", velocity)
button.pulseColor(Math.floor((Math.random() * 127) + 1))
if(button.x === 1 && button.y === 0) launchpad.darkAll()
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment