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, }