329 lines
12 KiB
JavaScript
329 lines
12 KiB
JavaScript
|
const config = require('../config.json');
|
||
|
const util = require('./util.js');
|
||
|
const constants = require('./constants.js');
|
||
|
const logger = require('./logger.js');
|
||
|
const path = require('path');
|
||
|
const fs = require('fs');
|
||
|
const { spawn } = require('child_process')
|
||
|
const ttl2jsonld = require('@frogcat/ttl2jsonld').parse;
|
||
|
|
||
|
var banks = undefined;
|
||
|
var pedalboards = undefined;
|
||
|
var defaultPedalboard = undefined;
|
||
|
var currentPedalboard = undefined;
|
||
|
var currentPedals = undefined;
|
||
|
|
||
|
function reset() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
util.httpGET(config.modep.host, config.modep.port, '/reset')
|
||
|
.then(resolve)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getBanks() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (banks) {
|
||
|
return resolve(banks);
|
||
|
}
|
||
|
// FAKE DATA
|
||
|
var fake = [{ "title": "The Button", "pedalboards": [{ "valid": true, "broken": false, "uri": "file:///var/modep/pedalboards/default.pedalboard/default.ttl", "bundle": "/var/modep/pedalboards/default.pedalboard", "title": "Default", "version": 0 }, { "valid": true, "broken": false, "uri": "file:///var/modep/pedalboards/FUZZ.pedalboard/FUZZ.ttl", "bundle": "/var/modep/pedalboards/FUZZ.pedalboard", "title": "FUZZ", "version": 1 }] }];
|
||
|
for (var index = 0; index < fake.length; index++) {
|
||
|
fake.id = index;
|
||
|
}
|
||
|
banks = util.sortById(fake);
|
||
|
return resolve(fake);
|
||
|
|
||
|
util.httpGET(config.modep.host, config.modep.port, '/banks')
|
||
|
.then(resolve)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getPedalboards() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (pedalboards) {
|
||
|
return resolve(pedalboards);
|
||
|
}
|
||
|
// FAKE DATA
|
||
|
var fake = [{ "valid": true, "broken": false, "uri": "file:///var/modep/pedalboards/FUZZ.pedalboard/FUZZ.ttl", "bundle": "/var/modep/pedalboards/FUZZ.pedalboard", "title": "FUZZ", "version": 1 }, { "valid": true, "broken": false, "uri": "file:///var/modep/pedalboards/default.pedalboard/default.ttl", "bundle": "/var/modep/pedalboards/default.pedalboard", "title": "Default", "version": 0 }];
|
||
|
var id = 1;
|
||
|
for (var index = 0; index < fake.length; index++) {
|
||
|
var pedalboard = fake[index];
|
||
|
if (pedalboard.bundle == constants.PEDALBOARD_DEFAULT) {
|
||
|
pedalboard.id = 0;
|
||
|
defaultPedalboard = pedalboard;
|
||
|
continue;
|
||
|
}
|
||
|
pedalboard.id = id;
|
||
|
id++;
|
||
|
}
|
||
|
pedalboards = util.sortById(fake);
|
||
|
return resolve(fake);
|
||
|
|
||
|
util.httpGET(config.modep.host, config.modep.port, '/pedalboard/list')
|
||
|
.then(function (pedalboards) {
|
||
|
|
||
|
})
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getDefaultPedalboard() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (defaultPedalboard) {
|
||
|
return resolve(defaultPedalboard);
|
||
|
}
|
||
|
getPedalboardByBundle(constants.PEDALBOARD_DEFAULT)
|
||
|
.then(resolve)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getCurrentPedalboard() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (currentPedalboard && currentPedalboard.id) {
|
||
|
return resolve(currentPedalboard);
|
||
|
}
|
||
|
// FAKE DATA
|
||
|
var fake = '/var/modep/pedalboards/FUZZ.pedalboard';
|
||
|
getPedalboardByBundle(fake)
|
||
|
.then(function (pedalboard) {
|
||
|
currentPedalboard = pedalboard;
|
||
|
return resolve(pedalboard);
|
||
|
})
|
||
|
.catch(reject);
|
||
|
|
||
|
// PRODUCTION
|
||
|
// util.httpGET(config.modep.host, config.modep.port, '/pedalboard/current')
|
||
|
// .then(getPedalboardByBundle)
|
||
|
// .then(resolve)
|
||
|
// .catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getPedalboardById(pedalboardId) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
getPedalboards()
|
||
|
.then(function (pedalboards) {
|
||
|
for (var index = 0; index < pedalboards.length; index++) {
|
||
|
if (pedalboards[index].id != pedalboardId) {
|
||
|
continue;
|
||
|
}
|
||
|
return resolve(pedalboards[index]);
|
||
|
}
|
||
|
return reject('error: could not find pedalboard by id \'' + controlId + '\'');
|
||
|
})
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getPedalboardByBundle(pedalboardBundle) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
getPedalboards()
|
||
|
.then(function (pedalboards) {
|
||
|
for (var index = 0; index < pedalboards.length; index++) {
|
||
|
if (pedalboards[index].bundle != pedalboardBundle) {
|
||
|
continue;
|
||
|
}
|
||
|
return resolve(pedalboards[index]);
|
||
|
}
|
||
|
return reject('error: could not find pedalboard by bundle \'' + pedalboardBundle + '\'');
|
||
|
})
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getPedalControlById(pedalId, controlId) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
getCurrentPedalById(pedalId)
|
||
|
.then(function (pedal) {
|
||
|
for (var index = 0; index < pedal.controls.length; index++) {
|
||
|
if (pedal.controls[index].id != controlId) {
|
||
|
continue;
|
||
|
}
|
||
|
return resolve(pedal.controls[index]);
|
||
|
}
|
||
|
return reject('error: could not find control for pedal \'' + pedalId + '\' by id \'' + controlId + '\'');
|
||
|
})
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getCurrentPedalById(id) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
getCurrentPedals()
|
||
|
.then(function () {
|
||
|
for (var index = 0; index < currentPedals.length; index++) {
|
||
|
if (currentPedals[index].id != id) {
|
||
|
continue;
|
||
|
}
|
||
|
return resolve(currentPedals[index]);
|
||
|
}
|
||
|
return reject('error: could not find current pedal by id \'' + id + '\'');
|
||
|
})
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function getCurrentPedals() {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (currentPedals) {
|
||
|
return resolve(currentPedals);
|
||
|
}
|
||
|
getCurrentPedalboard()
|
||
|
.then(parseCurrentPedalboard)
|
||
|
.then(resolve)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function parseCurrentPedalboard(pedalboardBundle) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var startTime = new Date();
|
||
|
logger.debug('parsing current pedalboard...');
|
||
|
if (!currentPedalboard || !currentPedalboard.uri) {
|
||
|
for (var index = 0; index < pedalboards.length; index++) {
|
||
|
var pedalboard = pedalboards[index];
|
||
|
if (!pedalboard.bundle || pedalboardBundle != pedalboard.bundle) {
|
||
|
continue;
|
||
|
}
|
||
|
currentPedalboard = pedalboard;
|
||
|
break;
|
||
|
};
|
||
|
}
|
||
|
if (!currentPedalboard.uri) {
|
||
|
reject('error: could not determine current pedalboard config file');
|
||
|
}
|
||
|
// FAKE DATA
|
||
|
var file = path.resolve('./dev/FUZZ.ttl');
|
||
|
// var file = path.resolve(currentPedalboard.uri.replace('file://', ''));
|
||
|
fs.readFile(file, function (err, data) {
|
||
|
if (err) {
|
||
|
return reject('error: could not parse current pedalboard file \'' + file + '\' >>> ' + err);
|
||
|
}
|
||
|
currentPedals = [];
|
||
|
var json = ttl2jsonld(data.toString())['@graph'];
|
||
|
var id = 0;
|
||
|
for (var index = 0; index < json.length; index++) {
|
||
|
var tmp = json[index];
|
||
|
if (!tmp['lv2:prototype']) {
|
||
|
continue;
|
||
|
}
|
||
|
var name = tmp['@id'];
|
||
|
currentPedals.push({ id: id, name: name, controls: [] });
|
||
|
id++;
|
||
|
}
|
||
|
for (var index = 0; index < json.length; index++) {
|
||
|
var tmp = json[index];
|
||
|
var name = tmp['@id'];
|
||
|
var value = tmp['ingen:value'];
|
||
|
if (value == undefined) {
|
||
|
continue;
|
||
|
}
|
||
|
var pedal = undefined;
|
||
|
for (var pedalIndex = 0; pedalIndex < currentPedals.length; pedalIndex++) {
|
||
|
if (!name.startsWith(currentPedals[pedalIndex].name)) {
|
||
|
continue;
|
||
|
}
|
||
|
pedal = currentPedals[pedalIndex];
|
||
|
break;
|
||
|
}
|
||
|
if (!pedal) {
|
||
|
continue;
|
||
|
}
|
||
|
id = pedal.controls.length;
|
||
|
name = name.replace(pedal.name + '/', '');
|
||
|
if (name == ':bypass') {
|
||
|
value = value;
|
||
|
} else {
|
||
|
value = value['@value'];
|
||
|
}
|
||
|
var control = { id: id, name: name, value: value };
|
||
|
pedal.controls.push(control);
|
||
|
id++;
|
||
|
var midi = tmp['midi:binding'];
|
||
|
if (!midi) {
|
||
|
continue;
|
||
|
}
|
||
|
control.midi = { channel: midi['midi:channel'], controller: midi['midi:controllerNumber'] }
|
||
|
}
|
||
|
logger.debug('parsing current pedalboard file \'' + file + '\' took ' + util.timeDiff(startTime) + 'ms')
|
||
|
resolve(currentPedals);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function sendValueToControl(value, control) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (!control || !control.midi) {
|
||
|
return reject('error: control \'' + control.name + '\' with id \'' + control.id + '\' has no midi bindings');
|
||
|
}
|
||
|
if (value > 127) {
|
||
|
value = 127;
|
||
|
} else if (value < 0) {
|
||
|
value = 0;
|
||
|
}
|
||
|
value = '00' + util.toHex(value) + '0' + util.toHex(control.midi.controller) + 'b' + util.toHex(control.midi.channel);
|
||
|
var cmd = 'oscsend';
|
||
|
var args = [config.osc.host, config.osc.port, config.osc.address, 'm', value];
|
||
|
logger.debug('executing command \'' + cmd + '\' with args \'' + args + '\'...');
|
||
|
var spawned = spawn(cmd, args);
|
||
|
spawned.stdout.on('data', function (data) {
|
||
|
logger.debug(data);
|
||
|
});
|
||
|
spawned.stderr.on('data', function (data) {
|
||
|
logger.error(data);
|
||
|
});
|
||
|
spawned.on('close', function (code) {
|
||
|
logger.debug('command \'' + cmd + '\' with args \'' + args + '\' finished with exit code ' + code);
|
||
|
resolve();
|
||
|
});
|
||
|
spawned.on('error', function (err) {
|
||
|
logger.error('command \'' + cmd + '\' with args \'' + args + '\' encountered an error >>> ' + err);
|
||
|
reject(err);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function setPedalboardById(pedalboardId) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (!pedalboardId) {
|
||
|
return reject('error: no pedalboard id given');
|
||
|
}
|
||
|
getPedalboardById(pedalboardId)
|
||
|
.then(setPedalboard)
|
||
|
.then(resolve)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function setPedalboard(pedalboard) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (!pedalboard || !pedalboard.bundle) {
|
||
|
return reject('error: no bundle set for pedalboard');
|
||
|
}
|
||
|
if (pedalboard.id == currentPedalboard.id) {
|
||
|
return resolve('pedalboard \'' + pedalboard.id + '\' is already active');
|
||
|
}
|
||
|
reset()
|
||
|
.then(function () {
|
||
|
util.httpPOST(config.modep.host, config.modep.port, '/pedalboard/load_bundle/?bundlepath=' + pedalboard.bundle)
|
||
|
})
|
||
|
.then(getCurrentPedalboard)
|
||
|
.catch(reject);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
getBanks,
|
||
|
getPedalboards,
|
||
|
getDefaultPedalboard,
|
||
|
getCurrentPedalboard,
|
||
|
getCurrentPedals,
|
||
|
getCurrentPedalById,
|
||
|
getPedalControlById,
|
||
|
sendValueToControl,
|
||
|
setPedalboard,
|
||
|
setPedalboardById,
|
||
|
}
|