const config = require('../config.json'); const util = require('./util.js'); const constants = require('./constants.js'); const logger = require('./logger.js'); const cache = require('./cache.js'); const path = require('path'); const fs = require('fs'); const { spawn } = require('child_process'); const ttl2jsonld = require('@frogcat/ttl2jsonld').parse; 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) { var banks = cache.getBanks(); if (banks != undefined) { 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(function (banks) { for (var index = 0; index < banks.length; index++) { var bank = banks[index]; bank.id = index; } banks = util.sortById(banks); cache.setBanks(banks); return resolve(banks); }) .catch(reject); }); } function getBankById(bankId) { return new Promise(function (resolve, reject) { getBanks() .then(function (banks) { for (var index = 0; index < banks.length; index++) { if (banks[index].id != bankId) { continue; } return resolve(banks[index]); } return reject('error: could not find bank by id \'' + bankId + '\''); }) .catch(reject); }); } function getPedalboards() { return new Promise(function (resolve, reject) { var pedalboards = cache.getPedalboards(); if (pedalboards != undefined) { 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) { var id = 1; for (var index = 0; index < pedalboards.length; index++) { var pedalboard = pedalboards[index]; if (pedalboard.bundle == constants.PEDALBOARD_DEFAULT) { pedalboard.id = 0; defaultPedalboard = pedalboard; continue; } pedalboard.id = id; id++; } pedalboards = util.sortById(pedalboards); cache.setPedalboards(pedalboards); return resolve(pedalboards); }) .catch(reject); }); } function getDefaultPedalboard() { return new Promise(function (resolve, reject) { var defaultPedalboard = cache.getDefaultPedalboard(); if (defaultPedalboard != undefined) { return resolve(defaultPedalboard); } getPedalboardByBundle(constants.PEDALBOARD_DEFAULT) .then(function (defaultPedalboard) { cache.setDefaultPedalboard(defaultPedalboard); return resolve(defaultPedalboard); }) .catch(reject); }); } function getCurrentPedalboard() { return new Promise(function (resolve, reject) { var currentPedalboard = cache.getCurrentPedalboard(); if (currentPedalboard != undefined && currentPedalboard.id != undefined) { 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(function (currentPedalboard) { cache.setCurrentPedalboard(currentPedalboard); return resolve(currentPedalboard) }) .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 \'' + pedalboardId + '\''); }) .catch(reject); }); } function getPedalboardByBundle(pedalboardBundle) { return new Promise(function (resolve, reject) { if (pedalboardBundle == undefined) { getDefaultPedalboard() .then(resolve) .catch(reject); return; } 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 (currentPedals) { 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) { var currentPedals = cache.getCurrentPedals(); if (currentPedals) { return resolve(currentPedals); } getCurrentPedalboard() .then(parseCurrentPedalboard) .then(function (pedals) { cache.setCurrentPedals(pedals); return resolve(pedals); }) .catch(reject); }); } function parseCurrentPedalboard(currentPedalboard) { return new Promise(function (resolve, reject) { getDefaultPedalboard() .then(function (defaultPedalboard) { test = defaultPedalboard; currentPedals = []; if (defaultPedalboard.id == currentPedalboard.id) { return resolve(currentPedals); } var startTime = new Date(); logger.debug('parsing current pedalboard...'); if (!currentPedalboard.uri) { reject('error: could not determine current pedalboard config file'); } // FAKE DATA var file = path.resolve(path.dirname(__dirname) + '/dev/' + currentPedalboard.uri.substring(currentPedalboard.uri.lastIndexOf('/') + 1)); // 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); } 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); }); }).catch(reject); }); } function setControlValue(pedalId, requestParams) { return new Promise(function (resolve, reject) { var controlId = requestParams.get('id'); if (controlId == undefined) { reject('error: could not handle POST - missing parameter \'id\'', 400); } var value = parseInt(requestParams.get('value')); if (value == undefined) { reject('error: could not handle POST - missing parameter \'value\'', 400); } else if (Number.isNaN(value)) { reject('error: parameter \'value\' is not a number', 400); } getPedalControlById(pedalId, controlId) .then(function (control) { 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); }); }) .catch(reject); }); } function setPedalboardById(pedalboardId) { return new Promise(function (resolve, reject) { if (pedalboardId == undefined) { 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'); } var tmpPedalboard; getCurrentPedalboard() .then(function (currentPedalboard) { if (pedalboard.id == currentPedalboard.id) { return Promise.reject('pedalboard \'' + pedalboard.id + '\' is already active'); } tmpPedalboard = currentPedalboard; }) .then(function () { return reset() }) .then(function () { return util.httpPOST(config.modep.host, config.modep.port, '/pedalboard/load_bundle/?bundlepath=' + pedalboard.bundle) }) .then(function () { parseCurrentPedalboard(tmpPedalboard); }) .then(resolve) .catch(reject); }); } module.exports = { getBanks, getBankById, getPedalboards, getPedalboardById, getDefaultPedalboard, getCurrentPedalboard, getCurrentPedals, getCurrentPedalById, getPedalControlById, setPedalboard, setPedalboardById, setControlValue, }