Skip to content

Instantly share code, notes, and snippets.

@pateketrueke
Created June 11, 2015 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pateketrueke/36416022019783f05ba0 to your computer and use it in GitHub Desktop.
Save pateketrueke/36416022019783f05ba0 to your computer and use it in GitHub Desktop.
Custom build for ReLoop KeyPad on BitWig
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
/* global loadAPI, sendSysex, host */
loadAPI(1);
var RL;
var KeyPad = require('./keypad');
var exports = new Function('return this')();
var defaultActions = require('./default/actions'),
defaultMappings = require('./default/mappings');
exports.DEBUG = false;
exports.init = function() {
sendSysex(KeyPad.ID3);
var keys = host.getMidiInPort(0).createNoteInput('Keys', '?0????', '?1????', '?2????'),
pads = host.getMidiInPort(0).createNoteInput('Pads', '?4????');
keys.setShouldConsumeEvents(false);
pads.setShouldConsumeEvents(false);
RL = new KeyPad()
.initialize()
.add(defaultActions)
.set(defaultMappings);
};
exports.exit = function() {
RL.teardown();
};
host.defineMidiPorts(1, 1);
host.defineController(KeyPad.VENDOR, KeyPad.PRODUCT, KeyPad.VERSION, KeyPad.GUID);
host.addDeviceNameBasedDiscoveryPair([KeyPad.ID1], [KeyPad.ID1]);
host.addDeviceNameBasedDiscoveryPair([KeyPad.ID2], [KeyPad.ID2]);
host.defineSysexIdentityReply(KeyPad.ID4);
},{"./default/actions":2,"./default/mappings":3,"./keypad":8}],2:[function(require,module,exports){
'use strict';
/* global sendMidi */
module.exports = {
scenePlay: function(e) {
this.trackBank.launchScene(e.scene);
this.set('currentScene', e);
this.all.forEach(function(cc) {
sendMidi(cc.channel, cc.index, cc.scene === e.scene ? 127 : 0);
});
e.notify = 'Scene ' + (e.scene + 1);
},
setDevice: function(e) {
this.cursorDevice[e.range > 0 ? 'selectNext' : 'selectPrevious']();
e.notify = this.get('primaryDevice');
},
setTrack: function(e) {
var track = this.get('activeTrack'),
total = this.get('currentTracks.length') - 1;
if (e.range > 0) {
track += 1;
} else {
track -= 1;
}
var index = Math.min(total, Math.max(0, track));
this.trackBank.getTrack(index).select();
e.notify = this.get('currentTracks', index);
},
sendLevel: function(e) {
this.trackBank.getTrack(e.track).getSend(e.send).set(e.value, 128);
e.notify = e.value ? Math.round(e.value / 1.27) + '%' : 'OFF';
},
volumeLevel: function(e) {
this.trackBank.getTrack(e.track).getVolume().set(e.value, 128);
},
toggleMute: function(e) {
this.trackBank.getTrack(e.track).getMute().set(e.toggle);
},
toggleSolo: function(e) {
if (e.toggle) {
this.trackBank.getTrack(e.track).getSolo().toggle();
}
},
toggleArm: function(e) {
if (e.toggle) {
this.trackBank.getTrack(e.track).getArm().toggle();
}
},
onStop: function() {
var cc = this.get('currentScene');
if (cc) {
sendMidi(cc.channel, cc.index, 0);
}
}
};
},{}],3:[function(require,module,exports){
'use strict';
var PAGE_1 = [
[
{ channel: 177, index: 57, type: 'encoder', command: 'setTrack' },
{ channel: 177, index: 89, type: 'knob' },
{ channel: 177, index: 97, type: 'knob' },
{ channel: 177, index: 8, type: 'button', inverted: true, command: 'toggleMute', track: 0, shift: { channel: 177, index: 16, grouped: true, command: 'scenePlay', scene: 0 } },
{ channel: 177, index: 24, type: 'button', command: 'toggleSolo', track: 0 },
{ channel: 177, index: 40, type: 'button', command: 'toggleArm', track: 0 },
{ channel: 177, index: 0, type: 'fader' }
],
[
{ channel: 177, index: 58, type: 'encoder', command: 'setDevice' },
{ channel: 177, index: 90, type: 'knob' },
{ channel: 177, index: 98, type: 'knob' },
{ channel: 177, index: 9, type: 'button', inverted: true, command: 'toggleMute', track: 1, shift: { channel: 177, index: 17, grouped: true, command: 'scenePlay', scene: 1 } },
{ channel: 177, index: 25, type: 'button', command: 'toggleSolo', track: 1 },
{ channel: 177, index: 41, type: 'button', command: 'toggleArm', track: 1 },
{ channel: 177, index: 1, type: 'fader' }
],
[
{ channel: 177, index: 59, type: 'encoder' },
{ channel: 177, index: 91, type: 'knob' },
{ channel: 177, index: 99, type: 'knob' },
{ channel: 177, index: 10, type: 'button', inverted: true, command: 'toggleMute', track: 2, shift: { channel: 177, index: 18, grouped: true, command: 'scenePlay', scene: 2 } },
{ channel: 177, index: 26, type: 'button', command: 'toggleSolo', track: 2 },
{ channel: 177, index: 42, type: 'button', command: 'toggleArm', track: 2 },
{ channel: 177, index: 2, type: 'fader' }
],
[
{ channel: 177, index: 60, type: 'encoder' },
{ channel: 177, index: 92, type: 'knob' },
{ channel: 177, index: 100, type: 'knob' },
{ channel: 177, index: 11, type: 'button', inverted: true, command: 'toggleMute', track: 3, shift: { channel: 177, index: 19, grouped: true, command: 'scenePlay', scene: 3 } },
{ channel: 177, index: 27, type: 'button', command: 'toggleSolo', track: 3 },
{ channel: 177, index: 43, type: 'button', command: 'toggleArm', track: 3 },
{ channel: 177, index: 3, type: 'fader' }
],
[
{ channel: 177, index: 61, type: 'encoder' },
{ channel: 177, index: 93, type: 'knob' },
{ channel: 177, index: 101, type: 'knob' },
{ channel: 177, index: 12, type: 'button', inverted: true, command: 'toggleMute', track: 4, shift: { channel: 177, index: 20, grouped: true, command: 'scenePlay', scene: 4 } },
{ channel: 177, index: 28, type: 'button', command: 'toggleSolo', track: 4 },
{ channel: 177, index: 44, type: 'button', command: 'toggleArm', track: 4 },
{ channel: 177, index: 4, type: 'fader' }
],
[
{ channel: 177, index: 62, type: 'encoder' },
{ channel: 177, index: 94, type: 'knob' },
{ channel: 177, index: 102, type: 'knob' },
{ channel: 177, index: 13, type: 'button', inverted: true, command: 'toggleMute', track: 5, shift: { channel: 177, index: 21, grouped: true, command: 'scenePlay', scene: 5 } },
{ channel: 177, index: 29, type: 'button', command: 'toggleSolo', track: 5 },
{ channel: 177, index: 45, type: 'button', command: 'toggleArm', track: 5 },
{ channel: 177, index: 5, type: 'fader' }
],
[
{ channel: 177, index: 63, type: 'encoder' },
{ channel: 177, index: 95, type: 'knob' },
{ channel: 177, index: 103, type: 'knob' },
{ channel: 177, index: 14, type: 'button', inverted: true, command: 'toggleMute', track: 6, shift: { channel: 177, index: 22, grouped: true, command: 'scenePlay', scene: 6 } },
{ channel: 177, index: 30, type: 'button', command: 'toggleSolo', track: 6 },
{ channel: 177, index: 46, type: 'button', command: 'toggleArm', track: 6 },
{ channel: 177, index: 6, type: 'fader' }
],
[
{ channel: 177, index: 64, type: 'encoder' },
{ channel: 177, index: 96, type: 'knob' },
{ channel: 177, index: 104, type: 'knob' },
{ channel: 177, index: 15, type: 'button', inverted: true, command: 'toggleMute', track: 7, shift: { channel: 177, index: 23, grouped: true, command: 'scenePlay', scene: 7 } },
{ channel: 177, index: 31, type: 'button', command: 'toggleSolo', track: 7 },
{ channel: 177, index: 47, type: 'button', command: 'toggleArm', track: 7 },
{ channel: 177, index: 7, type: 'fader' }
]
];
var PAGE_2 = [];
module.exports = [PAGE_1, PAGE_2];
},{}],4:[function(require,module,exports){
'use strict';
/* global host, println, DEBUG */
function dump(obj) {
if (obj === null) {
return 'null';
}
if (obj === true) {
return 'true';
}
if (obj === false) {
return 'false';
}
if (typeof obj === 'function') {
return obj.toString().replace(/[\r\n\t\s]+/g, ' ');
}
if (typeof obj !== 'object') {
return obj;
}
var out = [];
for (var k in obj) {
var v = dump(obj[k]);
out.push(obj instanceof Array ? v : (k + ': ' + v));
}
if (obj instanceof Array) {
return '[ ' + out.join(', ') + ' ]';
}
return '{ ' + out.join(', ') + ' }';
}
module.exports.copy = function(obj) {
if (obj instanceof Array) {
return obj.slice();
}
if (typeof obj !== 'object') {
return obj;
}
var target = {};
for (var key in obj) {
target[key] = obj[key];
}
return target;
};
module.exports.debug = function() {
if (typeof DEBUG !== 'undefined' && DEBUG === true) {
var out = [];
for (var i = 0, a; typeof (a = arguments[i]) !== 'undefined'; i += 1) {
out.push(dump(a));
}
println('> ' + out.join(' '));
}
};
module.exports.notify = function(action) {
var text = '';
switch (action.type) {
case 'encoder':
text += action.level;
break;
case 'fader':
case 'knob':
text += (action.level ? Math.round(action.level / 1.27) + '%' : 'OFF');
break;
case 'pad':
if (action.toggle) {
text += action.level;
} else if (typeof action.toggle === 'undefined') {
if (action.level === 127) {
text += 'ON';
} else {
text += 'OFF';
}
}
break;
case 'play':
if (action.toggle) {
text += !action.state ? 'PLAY' : 'PAUSE';
}
break;
case 'record':
case 'overdub':
if (action.toggle) {
text += action.type.toUpperCase() + ' ' + (!action.state ? 'ON' : 'OFF');
}
break;
default:
switch (action.command) {
case 'mute':
if (action.toggle) {
text += 'MUTE';
} else {
text += 'UNMUTE';
}
break;
case 'solo':
case 'arm':
if (action.toggle) {
text += action.command.toUpperCase() + ' ' + (!action.state ? 'ON' : 'OFF');
}
break;
default:
if (action.toggle) {
text += action.type.replace(/-/g, ' ').toUpperCase();
}
break;
}
break;
}
if (text) {
if (typeof action.offset === 'number') {
text = 'CC' + (action.offset + 1) + ' ' + text;
}
host.showPopupNotification(text);
}
};
},{}],5:[function(require,module,exports){
'use strict';
module.exports = function(status, data1, data2) {
var on = data2 > 65;
if (data1 === this.PLAY) {
return { type: 'play', toggle: on, state: this.IS_PLAYING };
} if (data1 === this.PLAYS) {
return { type: 'play-all', toggle: on };
} else if (data1 === this.STOP) {
return { type: 'stop', toggle: on };
} else if (data1 === this.STOPS) {
return { type: 'stop-all', toggle: on };
} else if (data1 === this.RECORD) {
return { type: 'record', toggle: on, state: this.IS_RECORDING };
} else if (data1 === this.RECORDS) {
return { type: 'overdub', toggle: on, state: this.OVERDUB };
}
if (this.CC_MAPPINGS[status + '#' + data1]) {
var ref = this.CC_MAPPINGS[status + '#' + data1],
copy = {};
for (var k in ref) {
copy[k] = ref[k];
}
return copy;
}
};
},{}],6:[function(require,module,exports){
'use strict';
var initActions = require('./util/init-actions');
module.exports = function(actions) {
initActions(this, actions);
return this;
};
},{"./util/init-actions":13}],7:[function(require,module,exports){
'use strict';
/* global sendMidi, host */
var $ = require('../helpers');
module.exports = function(action) {
if (typeof action.value === 'undefined') {
action.value = [127, 0][+action.toggle] || action.level || 0;
}
switch (action.type) {
case 'overdub':
if (action.toggle) {
this.host.transport.toggleOverdub();
}
break;
case 'record':
if (action.toggle) {
this.host.transport.record();
this.IS_RECORDING = !this.IS_RECORDING;
}
break;
case 'play':
if (action.toggle) {
this.host.transport.play();
}
break;
case 'play-all':
for (var i = 0; i < 8; i += 1) {
this.host.trackBank.getClipLauncherScenes().launch(i);
}
break;
case 'stop':
if (action.toggle) {
if (this.IS_RECORDING) {
this.host.transport.record();
}
this.IS_RECORDING = false;
this.IS_PLAYING = false;
this.host.transport.stop();
}
break;
case 'stop-all':
this.host.trackBank.getClipLauncherScenes().stop();
break;
default:
if (typeof action.offset === 'number') {
this.host.userControls.getControl(action.offset).set(action.value, 128);
}
break;
}
var callback = this.CC_USER_ACTIONS[action.command];
if (!callback) {
var proxy = ('on-' + action.type).replace(/-[a-z]/g, function(match) {
return match.substr(1).toUpperCase();
});
callback = this.CC_USER_ACTIONS[proxy];
}
if (typeof callback === 'function') {
var api = $.copy(this.host);
if (action.grouped) {
api.all = this.CC_STATE.commonMappings[action.command].map($.copy);
}
callback.call(api, action);
if (typeof this.CC_STATE.commonValues[action.channel + '#' + action.index] !== 'undefined') {
action.state = this.CC_STATE.commonValues[action.channel + '#' + action.index];
}
if (!action.toggle && action.state && action.command) {
sendMidi(action.channel, action.index, 127);
}
}
if (typeof action.notify === 'string') {
host.showPopupNotification(action.notify);
} else if (action.notify !== false) {
$.notify(action);
}
return this;
};
},{"../helpers":4}],8:[function(require,module,exports){
'use strict';
var KeyPad = module.exports = function() {
this.PLAY = 105;
this.PLAYS = 108;
this.STOP = 106;
this.STOPS = 109;
this.RECORD = 107;
this.RECORDS = 110;
this.OCTAVE_DOWNS = 111;
this.OCTAVE_UPS = 112;
this.CHANNEL1 = 177;
this.TRACKS = 16;
this.OVERDUB = false;
this.IS_PLAYING = false;
this.IS_RECORDING = false;
this.CC_STATE = {};
this.CC_TRACKS = [];
this.CC_MAPPINGS = {};
this.CC_USER_STATE = {};
this.CC_USER_ACTIONS = {};
};
KeyPad.VENDOR = 'Reloop';
KeyPad.PRODUCT = 'KeyPad';
KeyPad.VERSION = '1.0';
KeyPad.ID1 = 'Reloop KeyPad';
KeyPad.ID2 = 'Reloop KeyPad MIDI 1';
KeyPad.ID3 = 'F0 AD F5 01 11 02 F7';
KeyPad.ID4 = 'F0 7E ?? 06 02 AD F5 ?? ?? F7';
KeyPad.GUID = 'BD3405A8-9C77-449F-BA6D-2E91D9873878';
KeyPad.prototype.actionFor = require('./action-for');
KeyPad.prototype.execute = require('./execute');
KeyPad.prototype.initialize = require('./initialize');
KeyPad.prototype.teardown = require('./teardown');
KeyPad.prototype.add = require('./add');
KeyPad.prototype.set = require('./set');
},{"./action-for":5,"./add":6,"./execute":7,"./initialize":9,"./set":10,"./teardown":11}],9:[function(require,module,exports){
'use strict';
/* global println, printSysex, host */
var $ = require('../helpers');
var makeHost = require('./util/make-host'),
initTracks = require('./util/init-tracks');
module.exports = function() {
println('CONNECTED');
var RL = this;
makeHost(RL);
initTracks(RL);
host.getMidiInPort(0).setMidiCallback(function(status, data1, data2) {
var action = RL.actionFor(status, data1, data2);
if (!action) {
$.debug('MIDI', status, data1, data2);
} else {
if (action.inverted) {
if (typeof action.toggle === 'boolean') {
action.toggle = !action.toggle;
}
data2 = 127 - data2;
delete action.inverted;
}
switch (action.type) {
case 'button':
action.toggle = data2 > 65;
break;
case 'encoder':
if (!RL.CC_STATE.encoderValues) {
RL.CC_STATE.encoderValues = {};
}
var old = RL.CC_STATE.encoderValues[action.channel + '#' + action.index] || 0;
if (old !== data2) {
action.range = data2 < old ? -1 : 1;
}
if (data2 === 0 || data2 === 127) {
action.range = data2 ? 1 : -1;
}
RL.CC_STATE.encoderValues[action.channel + '#' + action.index] = data2;
default:
action.level = data2;
}
$.debug('CC', action);
RL.execute(action);
}
});
host.getMidiInPort(0).setSysexCallback(function(data) {
println('SYSEX');
printSysex(data);
});
host.getMidiOutPort(0).setShouldSendMidiBeatClock(true);
return this;
};
},{"../helpers":4,"./util/init-tracks":15,"./util/make-host":16}],10:[function(require,module,exports){
'use strict';
var $ = require('../helpers');
var initMappings = require('./util/init-mappings');
function reduce(set, fn) {
if (!(set instanceof Array)) {
fn(set);
} else {
set.forEach(function(value) {
if (value !== null) {
reduce(value, fn);
}
});
}
}
module.exports = function(mappings) {
var map = [],
count = 0;
function push(data) {
if (typeof data.channel === 'number' && typeof data.index === 'number') {
if (!data.command) {
data.offset = count;
count += 1;
}
if (data.shift) {
var copy = $.copy(data.shift);
copy.type = data.type;
copy.shift = true;
delete data.shift;
push(copy);
}
map.push(data);
}
}
reduce(mappings, push);
initMappings(this, map, count);
return this;
};
},{"../helpers":4,"./util/init-mappings":14}],11:[function(require,module,exports){
'use strict';
/* global println */
module.exports = function() {
println('DISCONNECTED');
};
},{}],12:[function(require,module,exports){
'use strict';
module.exports = function(RL, key) {
return function() {
return RL[key];
};
};
},{}],13:[function(require,module,exports){
'use strict';
module.exports = function(RL, map) {
for (var key in map) {
RL.CC_USER_ACTIONS[key] = map[key];
}
};
},{}],14:[function(require,module,exports){
'use strict';
/* global host */
var stateObserver = require('./state-observer');
module.exports = function(RL, set, length) {
RL.host.userControls = host.createUserControls(length);
RL.CC_STATE.commonMappings = {};
RL.CC_STATE.commonValues = {};
RL.CC_MAPPINGS = {};
set.forEach(function(e) {
RL.CC_MAPPINGS[e.channel + '#' + e.index] = e;
if (e.grouped && e.command) {
if (!RL.CC_STATE.commonMappings[e.command]) {
RL.CC_STATE.commonMappings[e.command] = [];
}
RL.CC_STATE.commonMappings[e.command].push(e);
}
switch (e.command) {
case 'toggleMute': RL.CC_TRACKS[e.track].getMute().addValueObserver(stateObserver(RL, 'commonValues', e, 'io')); break;
case 'toggleSolo': RL.CC_TRACKS[e.track].getSolo().addValueObserver(stateObserver(RL, 'commonValues', e, 'io')); break;
case 'toggleArm': RL.CC_TRACKS[e.track].getArm().addValueObserver(stateObserver(RL, 'commonValues', e, 'io')); break;
}
if (typeof e.offset === 'number') {
var cc = RL.host.userControls.getControl(e.offset);
cc.setLabel('CC' + (e.offset + 1));
cc.setIndication(true);
}
});
};
},{"./state-observer":18}],15:[function(require,module,exports){
'use strict';
var stateObserver = require('./state-observer');
module.exports = function(RL) {
for (var i = 0, c = RL.TRACKS; i < c; i += 1) {
RL.CC_TRACKS[i] = RL.host.trackBank.getTrack(i);
RL.CC_TRACKS[i].addIsSelectedObserver(stateObserver(RL, 'activeTrack', i, 'scalar'));
RL.CC_TRACKS[i].addNameObserver(20, '', stateObserver(RL, 'currentTracks', i, 'list'));
}
};
},{"./state-observer":18}],16:[function(require,module,exports){
'use strict';
/* global sendMidi, host */
var stateObserver = require('./state-observer'),
stateGetter = require('./state-getter'),
stateSetter = require('./state-setter'),
getterFor = require('./getter-for');
module.exports = function(RL) {
RL.host = {
trackBank: host.createTrackBank(16, 2, 8),
transport: host.createTransport(),
cursorTrack: host.createCursorTrack(16, 2),
cursorDevice: host.createCursorDevice()
};
RL.host.cursorDevice.addNameObserver(20, '', stateObserver(RL, 'primaryDevice', false, 'scalar'));
RL.host.transport.addIsRecordingObserver(function (on) {
sendMidi(RL.CHANNEL1, RL.RECORD, (RL.IS_RECORDING = on) ? 127 : 0);
});
RL.host.transport.addIsPlayingObserver(function (on) {
sendMidi(RL.CHANNEL1, RL.PLAY, (RL.IS_PLAYING = on) ? 127 : 0);
});
RL.host.transport.addOverdubObserver(function(on) {
if (!RL.IS_RECORDING) {
sendMidi(RL.CHANNEL1, RL.RECORD, 0);
}
sendMidi(RL.CHANNEL1, RL.RECORDS, (RL.OVERDUB = on) ? 127 : 0);
});
RL.host.get = stateGetter(RL);
RL.host.set = stateSetter(RL);
RL.host.isPlaying = getterFor(RL, 'IS_PLAYING');
RL.host.isRecording = getterFor(RL, 'IS_RECORDING');
};
},{"./getter-for":12,"./state-getter":17,"./state-observer":18,"./state-setter":19}],17:[function(require,module,exports){
'use strict';
var $ = require('../../helpers');
module.exports = function(RL) {
return function(from, key) {
if (from.indexOf('.') > 0) {
key = from.split('.')[1];
from = from.split('.')[0];
}
var obj;
if (typeof RL.CC_STATE[from] !== 'undefined') {
obj = $.copy(RL.CC_STATE[from]);
}
if (typeof RL.CC_USER_STATE[from] !== 'undefined') {
obj = $.copy(RL.CC_USER_STATE[from]);
}
if (typeof key !== 'undefined') {
return obj ? obj[key] : null;
}
return obj;
};
};
},{"../../helpers":4}],18:[function(require,module,exports){
'use strict';
/* global sendMidi */
module.exports = function(RL, label, index, type) {
if (typeof RL.CC_STATE[label] === 'undefined') {
switch (type) {
case 'scalar': RL.CC_STATE[label] = index; break;
case 'list': RL.CC_STATE[label] = []; break;
default: RL.CC_STATE[label] = {}; break;
}
}
return function(value) {
if (type === 'io') {
if (index.inverted) {
value = !value;
}
RL.CC_STATE[label][index.channel + '#' + index.index] = value;
sendMidi(index.channel, index.index, value ? 127 : 0);
} else if (!value) {
switch (type) {
case 'list': Array.prototype.splice.call(RL.CC_STATE[label], index, 1); break;
case 'scalar':
if (typeof value === 'string') {
RL.CC_STATE[label] = index;
}
break;
}
} else {
switch (type) {
case 'scalar': RL.CC_STATE[label] = index !== false ? index : value; break;
default: RL.CC_STATE[label][index] = value; break;
}
}
};
};
},{}],19:[function(require,module,exports){
'use strict';
module.exports = function(RL) {
return function(key, value) {
RL.CC_USER_STATE[key] = value;
};
};
},{}]},{},[1]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment