UNPKG

x32-osc

Version:

X32/M32 interface to all OSC parameters and meters

1,050 lines 89.8 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.X32 = void 0; ///<reference path="x32-osc.d.ts" /> var events_1 = require("events"); var dgram = __importStar(require("dgram")); var x32definitions_1 = require("./x32definitions"); var fs = __importStar(require("fs")); var x32branches = [ 'config', 'ch', 'auxin', 'fxrtn', 'bus', 'mtx', 'main', 'dca', 'fx', 'outputs', 'headamp', ]; var X32 = /** @class */ (function (_super) { __extends(X32, _super); /** * * @param address - IP address or url to the x32 * @param x32UpdateFrequency - number of milliseconds between meter updates. Between ? and ? * */ function X32(address, x32UpdateFrequency) { var _this = _super.call(this) || this; _this._serverVersion = ''; _this._model = ''; _this._firmwareVersion = ''; _this._connected = false; _this._ready = false; _this._x32Meta = { _address: [] }; _this._linkcfg = { hadly: true, eq: true, dyn: true, fdrmute: true, mono: false, }; _this._lastValidMessage = Date.now(); _this._x32UpdateFrequency = 10; _this._meterSubscriptions = []; _this._OSCProxy = { get: function (x32Node, property) { if (!property || typeof property == 'symbol') return null; var prop = x32Node[property]; if (!prop || Array.isArray(prop) || property[0] == '_') return null; if (!prop._type) { //@ts-ignore return new Proxy(prop, this); } else return prop._value; }, //set needs to be an arrow function so that "this" will be the X32 object set: function (x32Node, property, value) { if (!property || typeof property == 'symbol') return false; var prop = x32Node[property]; if (!prop || Array.isArray(prop) || property[0] == '_') return false; if (prop._type && typeof value == 'string') { var oscAddress = '/' + prop._address.join('/'); _this._send(oscAddress, [{ type: 's', data: value }]); return true; } if (!prop._type && typeof value == 'object' && value != null) { var properties = Object.getOwnPropertyNames(value); for (var i = 0; i < properties.length; i++) { _this._OSCProxy.set(prop, properties[i], value[properties[i]], 0); } return true; } return false; }, ownKeys: function (x32Node) { var rtn = []; var keys = Object.getOwnPropertyNames(x32Node); for (var i = 0; i < keys.length; i++) { if (keys[i][0] != '_') rtn.push(keys[i]); } return rtn; }, defineProperty: function () { return false; }, deleteProperty: function () { return false; }, }; _this._nodeEmitter = new events_1.EventEmitter(); _this._leafEmitter = new events_1.EventEmitter(); if (x32UpdateFrequency) { _this._x32UpdateFrequency = x32UpdateFrequency / 50; if (_this._x32UpdateFrequency > 99) { _this.emit('info', 'Lowering X32 update frequency to highest possible: 4950ms'); _this._x32UpdateFrequency = 99; } if (_this._x32UpdateFrequency < 1) { _this.emit('info', 'raising X32 update frequency to lowest possible: 50ms'); _this._x32UpdateFrequency = 1; } } //calculate frequency _this.address = address; _this._socket = dgram.createSocket({ type: 'udp4', reuseAddr: true }); _this._socket.on('close', function () { _this.emit('closed'); }); _this._socket.on('error', function (err) { _this.emit('error', err); }); _this._socket.on('connect', function () { _this._x32Verify(); }); _this._socket.on('message', function (buf) { _this._processDataFromX32(buf); }); _this._socket.bind(0, '0.0.0.0', function () { _this.emit('info', 'Connecting to X32 at ' + address); _this._socket.connect(10023, address); }); _this.on('connected', function () { _this._connected = true; _this.subscribe(); _this._subscription = setInterval(function () { if (_this.connected) _this.subscribe(); }, 9000); _this.refreshState(); /* this._getNode('ch/17/mix') .then((values) => { console.log('promise res:'); console.log(values); }) .catch((err) => { console.log('err:' + err); }); */ }); _this._heartbeat = setInterval(function () { var time = Math.round((Date.now() - _this._lastValidMessage) / 1000); if (time > 20) { if (_this.connected) { _this.emit('error', new Error('It has been ' + time + ' seconds since last valid message from X32. Closing connection')); } else _this.emit('error', new Error('Unable to connect to X32 at ' + _this.address)); _this.close(); } else if (time > 10 && _this.connected) { _this.emit('info', 'Warning: It has been ' + time + ' seconds since last valid message from X32'); } }, 5000); _this.on('closed', function () { _this.removeAllListeners(); }); return _this; } Object.defineProperty(X32.prototype, "serverVersion", { get: function () { return this._serverVersion; }, enumerable: false, configurable: true }); Object.defineProperty(X32.prototype, "model", { get: function () { return this._model; }, enumerable: false, configurable: true }); Object.defineProperty(X32.prototype, "firmwareVersion", { get: function () { return this._firmwareVersion; }, enumerable: false, configurable: true }); Object.defineProperty(X32.prototype, "connected", { get: function () { return this._connected; }, enumerable: false, configurable: true }); Object.defineProperty(X32.prototype, "ready", { get: function () { return this._ready; }, enumerable: false, configurable: true }); X32.prototype.close = function () { this.emit('info', 'Closing connection to X32'); this._connected = false; if (this._subscription) clearInterval(this._subscription); clearInterval(this._heartbeat); this._socket.close(); }; X32.prototype._send = function (cmd, args) { var _this = this; if (!this.connected && cmd != '/info') { this.emit('error', new Error('Cannot send message to X32 unless connected')); return; } if (args == undefined) args = []; var cmdBuf = stringToBuffer(cmd); var argTypes = ','; var argBufs = []; if (args.length > 0) { for (var i = 0; i < args.length; i++) { argTypes += args[i].type; argBufs.push(oscArgumentToBuffer(args[i])); } } var typesBuf = stringToBuffer(argTypes); var argsBuf = Buffer.concat(argBufs); this._socket.send(Buffer.concat([cmdBuf, typesBuf, argsBuf]), function (err) { if (err) _this.emit('error', err); }); }; X32.prototype.subscribe = function () { if (!this.connected) { this.emit('error', new Error('Cannot subscribe until X32 is connected.')); return; } this._send('/xremote'); if (this._meterSubscriptions.length) { for (var i = 0; i < this._meterSubscriptions.length; i++) { var sub = this._meterSubscriptions[i]; var meterArgs = void 0; if (typeof sub == 'number') { meterArgs = [sub, 0, 0]; } else if (sub.length == 2) { meterArgs = [sub[0], sub[1], 0]; } else meterArgs = sub; this._send('/meters', [ { type: 's', data: '/meters/' + meterArgs[0] }, { type: 'i', data: meterArgs[1] }, { type: 'i', data: meterArgs[2] }, { type: 'i', data: this._x32UpdateFrequency }, ]); } } else this._send('/status'); }; X32.prototype._processDataFromX32 = function (buf) { var split = buf.indexOf(0); var oscAddress = buf.slice(0, split).toString(); split++; split = Math.ceil(split / 4) * 4; buf = buf.slice(split); switch (oscAddress) { case 'node': this._lastValidMessage = Date.now(); var nodeArgs = oscFormatBufferToArguments(buf); if (Array.isArray(nodeArgs)) { if (nodeArgs.length == 1 && nodeArgs[0].type == 's') { var values = oscNodeStringToValueArray(nodeArgs[0].data); if (values.length) { var nodeAddress = values.shift(); this._nodeEmitter.emit(nodeAddress, values); //console.log('node' + ' ' + nodeAddress); } } else this.emit('error', new Error('Bad /node data from X32')); } else this.emit('error', new Error(nodeArgs.error)); break; case '/status': this._lastValidMessage = Date.now(); break; case '/info': this._lastValidMessage = Date.now(); var infoArgs = oscFormatBufferToArguments(buf); if (Array.isArray(infoArgs)) { if (infoArgs.length == 4 && infoArgs.every(function (x) { return x.type == 's'; })) { this._serverVersion = infoArgs[0].data; this._model = infoArgs[2].data; this._firmwareVersion = infoArgs[3].data; this.emit('info', 'Connected to X32. Model: ' + this.model + ', firmware version: ' + this.firmwareVersion); this.emit('connected'); } else this.emit('error', new Error('Bad console info from X32')); } else this.emit('error', new Error(infoArgs.error)); break; default: var possibleFirstNode = oscAddress.slice(1, oscAddress.indexOf('/', 1)); if (x32branches.indexOf(possibleFirstNode) != -1) { var args = oscFormatBufferToArguments(buf); if (Array.isArray(args) && args.length == 1) { this._lastValidMessage = Date.now(); this._processChangeFromX32(oscAddress, args[0]); if (args[0].type == 'f') this._leafEmitter.emit(oscAddress, args[0].data); } else if (!Array.isArray(args)) { this.emit('error', new Error(args.error)); } else this.emit('error', new Error('Unknown change type from X32: Multiple OSC arguments')); } else { if (possibleFirstNode == 'meters') { var args = oscFormatBufferToArguments(buf); if (Array.isArray(args)) { if (args.length == 1 && args[0].type == 'b' && args[0].data.length % 4 == 0) { this._lastValidMessage = Date.now(); var meterNumber = oscAddress.slice(oscAddress.indexOf('/', 1) + 1); var meterBuf = args[0].data.slice(4); var meterData = []; for (var i = 0; i < meterBuf.length; i += 4) { meterData.push(meterBuf.readFloatLE(i)); } this.emit('meter', { number: parseInt(meterNumber), meters: meterData, }); } else this.emit('error', new Error('Bad meter data from X32')); } else this.emit('error', new Error(args.error)); } else if (possibleFirstNode.slice(0, 1) == '-') { //console.log("Control info I don't care about from X32: " + oscAddress); } else this.emit('error', new Error('Unknown OSC address from x32: ' + oscAddress)); } break; } }; X32.prototype._x32Verify = function () { this._send('/info'); }; X32.prototype._getNode = function (address) { var _this = this; return new Promise(function (res, rej) { var nodeTimeout; var nodeListener = function (values) { _this._nodeEmitter.off(address, nodeListener); clearTimeout(nodeTimeout); res(values); }; nodeTimeout = setTimeout(function () { _this._nodeEmitter.off(address, nodeListener); _this.emit('error', new Error('Timeout on X32 node request for ' + address + '. Closing X32 connection.')); _this.close(); rej('timeout'); }, 5000); _this._nodeEmitter.on(address, nodeListener); _this._send('/node', [{ type: 's', data: address }]); }); }; X32.prototype.refreshState = function () { var _this = this; var start = Date.now(); this._refreshState() .then(function () { _this._markAllRedundant(); _this.emit('info', 'Received X32 state in ' + (Date.now() - start) + ' ms'); if (!_this._ready) { _this._ready = true; _this.emit('ready'); //fs.writeFile('./x32-obj.json', JSON.stringify(this.OSC), () => {}); } }) .catch(function (err) { _this.emit('error', err); }); }; X32.prototype._refreshState = function (node, prefix) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (res, rej) { if (!node) { node = x32definitions_1.x32NodeStructure; _this._x32Meta = { _address: [] }; _this._OSC = new Proxy(_this._x32Meta, _this._OSCProxy); } if (!prefix) prefix = ''; var nodeProperties = Object.getOwnPropertyNames(node); var i = -1; var getNextNode = function () { return __awaiter(_this, void 0, void 0, function () { var child, childName_1, childNode, hasLeavesNodesVar; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: i++; if (!(i < nodeProperties.length)) return [3 /*break*/, 7]; child = node[nodeProperties[i]]; childName_1 = nodeProperties[i]; if (childName_1[0] == "'") childName_1 = childName_1.slice(1); childNode = void 0; if (!child._type) return [3 /*break*/, 2]; return [4 /*yield*/, getNextNode()]; case 1: _a.sent(); return [2 /*return*/]; case 2: hasLeavesNodesVar = hasLeavesNodes(child); if (!hasLeavesNodesVar[0]) return [3 /*break*/, 4]; return [4 /*yield*/, this._getNode(prefix + childName_1) .then(function (values) { _this._populateX32Object(prefix + childName_1, values); }) .catch(function (err) { rej(err); })]; case 3: _a.sent(); _a.label = 4; case 4: if (!hasLeavesNodesVar[1]) return [3 /*break*/, 6]; return [4 /*yield*/, this._refreshState(child, prefix + childName_1 + '/').catch(function (err) { rej(err); })]; case 5: _a.sent(); _a.label = 6; case 6: getNextNode(); return [3 /*break*/, 8]; case 7: res(); _a.label = 8; case 8: return [2 /*return*/]; } }); }); }; getNextNode(); })]; }); }); }; X32.prototype._markAllRedundant = function () { if (isNode(this._x32Meta.config) && isNode(this._x32Meta.config.linkcfg)) { if (isMetaLeaf(this._x32Meta.config.linkcfg.hadly)) this._linkcfg.hadly = this._x32Meta.config.linkcfg.hadly._value == 'ON'; if (isMetaLeaf(this._x32Meta.config.linkcfg.eq)) this._linkcfg.eq = this._x32Meta.config.linkcfg.eq._value == 'ON'; if (isMetaLeaf(this._x32Meta.config.linkcfg.dyn)) this._linkcfg.dyn = this._x32Meta.config.linkcfg.dyn._value == 'ON'; if (isMetaLeaf(this._x32Meta.config.linkcfg.fdrmute)) this._linkcfg.fdrmute = this._x32Meta.config.linkcfg.fdrmute._value == 'ON'; } if (isNode(this._x32Meta.config) && isNode(this._x32Meta.config.mono)) { if (isMetaLeaf(this._x32Meta.config.mono.link)) this._linkcfg.mono = this._x32Meta.config.mono.link._value == 'ON'; } for (var i = 1; i <= 32; i += 2) { this._markRedundant('ch', i); } for (var i = 1; i <= 8; i += 2) { this._markRedundant('aux', i); } for (var i = 1; i <= 8; i += 2) { this._markRedundant('fx', i); } for (var i = 1; i <= 16; i += 2) { this._markRedundant('bus', i); } for (var i = 1; i <= 6; i += 2) { this._markRedundant('mtx', i); } }; X32.prototype._markRedundant = function (type, num) { num = num + (num % 2); var linked = false; var linkAddress = type + 'link'; var address = type; if (type == 'fx') { address = 'fxrtn'; } if (type == 'aux') { address = 'auxin'; } if (isNode(this._x32Meta.config)) { var linkNode = this._x32Meta.config[linkAddress]; if (isNode(linkNode)) { var linkLeaf = linkNode[num - 1 + '-' + num]; if (isMetaLeaf(linkLeaf)) linked = linkLeaf._value == 'ON'; } else console.error('Tried to mark redundant flags from nonexistent node ' + linkNode); } var _a = [ linked && this._linkcfg.hadly, linked && this._linkcfg.eq, linked && this._linkcfg.dyn, linked && this._linkcfg.fdrmute, ], hadly = _a[0], eq = _a[1], dyn = _a[2], fdrmute = _a[3]; var parentNode = this._x32Meta[address]; if (isNode(parentNode)) { var node = parentNode[num.toString().padStart(2, '0')]; if (isNode(node)) { if (isNode(node.preamp)) markRedundantTree(node.preamp, hadly); if (isNode(node.eq)) markRedundantTree(node.eq, eq); if (isNode(node.dyn)) markRedundantTree(node.dyn, dyn); if (isNode(node.gate)) markRedundantTree(node.gate, dyn); if (isNode(node.insert)) markRedundantTree(node.insert, dyn); if (isNode(node.mix)) markRedundantTree(node.mix, fdrmute); if (isNode(node.grp)) markRedundantTree(node.grp, fdrmute); } else console.error('Tried to mark redundant flags from nonexistent node ' + address + '/' + num.toString().padStart(2, '0')); } else console.error('Tried to mark redundant flags from nonexistent node ' + address); //hadly, eq, dyn, fdrmute }; X32.prototype._populateX32Object = function (address, values, leaves, node) { if (!leaves) { //assume root leaves = getLeafDefs(address); } if (leaves.length != values.length) { this.emit('error', new Error('X32 definitions do not match data from X32 for address: ' + address)); return; } if (!node) node = this._x32Meta; var index = address.indexOf('/'); var property; if (index == -1) { property = address; } else property = address.slice(0, index); if (!node[property]) node[property] = { _address: __spreadArray(__spreadArray([], node._address, true), [property], false) }; var nodeProperty = node[property]; if (nodeProperty._type) { this.emit('error', new Error('Corrupt X32 tree. Leaf where a node should be.')); } else { if (index == -1) { var nodeProperty_1 = node[property]; for (var i = 0; i < leaves.length; i++) { nodeProperty_1[leaves[i].name] = __assign({ _address: __spreadArray(__spreadArray([], nodeProperty_1._address, true), [leaves[i].name], false), _value: values[i] }, leaves[i].type); } } else { this._populateX32Object(address.slice(index + 1), values, leaves, node[property]); } } }; Object.defineProperty(X32.prototype, "OSC", { get: function () { //@ts-ignore /*I don't know how to tell typescript that _OSCProxy doesn't preserve type return this._OSC; }, set: function (value) { this.emit('error', new Error('Replacing the entire parameter tree is not yet coded')); }, enumerable: false, configurable: true }); Object.defineProperty(X32.prototype, "meterSubscriptions", { get: function () { return __spreadArray([], this._meterSubscriptions, true); }, set: function (value) { this._meterSubscriptions = value; if (this.ready) this.subscribe(); }, enumerable: false, configurable: true }); X32.prototype._setOSC = function (address, value, x32InNode, strAddress) { var _this = this; var x32Node; var arrayAddress; var stringAddress; if (typeof address == 'string') { if (address[0] == '/') address = address.slice(1); arrayAddress = address.split('/'); } else { arrayAddress = address; } if (x32InNode) { x32Node = x32InNode; } else x32Node = this._x32Meta; if (strAddress) { stringAddress = strAddress; } else stringAddress = '/' + arrayAddress.join('/'); return new Promise(function (res, rej) { if (arrayAddress.length == 1) { var leaf = x32Node[address[0]]; if (!Array.isArray(leaf) && leaf._type) { leaf._value = value; _this._sendDatawTimeout(stringAddress, value) .then(function () { res(); }) .catch(function (err) { rej(err); }); } else rej('Address ' + stringAddress + ' does not point to leaf'); } else { var nodeName = arrayAddress[0]; var nextNode = x32Node[nodeName]; if (!Array.isArray(nextNode) && !nextNode._type) { _this._setOSC(arrayAddress.slice(1), value, nextNode, stringAddress) .then(function () { res(); }) .catch(function (err) { rej(err); }); } else rej('Bad address or metatree: ' + stringAddress); } }); }; X32.prototype._sendDatawTimeout = function (address, value, int, timeout) { var _this = this; if (!timeout) timeout = 20; var arg; if (typeof value == 'string') { arg = [{ type: 's', data: value }]; } else arg = [{ type: 'f', data: value }]; if (int && typeof value == 'number') arg = [{ type: 'i', data: value }]; return new Promise(function (res, rej) { _this._send(address, arg); setTimeout(function () { res(); }, timeout); }); }; X32.prototype._learnTextFromNumber = function (address, node, valueIndex, steps, int, delay) { var _this = this; return new Promise(function (res, rej) { return __awaiter(_this, void 0, void 0, function () { var rtn, i, change, valueCount, lastVal, numToSend; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: rtn = []; i = -1; change = 0; valueCount = 0; lastVal = ''; _a.label = 1; case 1: if (!(i < steps)) return [3 /*break*/, 3]; i++; numToSend = i; if (!int) numToSend = i / steps; return [4 /*yield*/, this._sendDatawTimeout(address, numToSend, int, delay) .then(function () { return _this._getNode(node); }) .then(function (values) { rtn.push(values[valueIndex]); //console.log(i) //console.log(numToSend + ' ' + values[valueIndex]); if (values[valueIndex] != lastVal) { //console.log(i - change); valueCount++; //console.log('change:' + numToSend) change = i; } lastVal = values[valueIndex]; }) .catch(function (err) { rej(err); })]; case 2: _a.sent(); return [3 /*break*/, 1]; case 3: //console.log('valueCount: ' + valueCount); res(rtn); return [2 /*return*/]; } }); }); }); }; X32.prototype.testX32NodeStructure = function () { var _this = this; return new Promise(function (res, rej) { var startTime = Date.now(); var test = x32definitions_1.x32NodeStructure; _this._testTree(test) .then(function (rtn) { var seconds = Math.round((Date.now() - startTime) / 1000); var minutes = Math.floor(seconds / 60); seconds = seconds % 60; var hours = Math.floor(minutes / 60); minutes = minutes % 60; console.log('Testing finished in ' + hours + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0')); res(rtn); }) .catch(function (err) { rej(err); }); }); }; X32.prototype._testTree = function (node, inAddress, leaveKeys) { var _this = this; var address = ''; if (inAddress) address = inAddress; return new Promise(function (res, rej) { var rtn = []; var leavesNodes = hasLeavesNodes(node); if (leavesNodes[0] || leavesNodes[1]) { var properties_1 = Object.getOwnPropertyNames(node); var i_1 = -1; var checkLeaf_1 = function () { i_1++; if (i_1 == properties_1.length - 1 && properties_1[i_1][0] == "'") i_1 = properties_1.length; if (address == '/ch' && i_1 >= 6) i_1 = properties_1.length; if (address == '/fx' && i_1 >= 3) i_1 = properties_1.length; if (i_1 < properties_1.length) { if (properties_1[i_1][0] == "'" && i_1 < properties_1.length - 2 && !leaveKeys) { if (address.slice(-3) == '/eq') { i_1 = properties_1.length - 1; } else i_1 = properties_1.length - 2; } if (address == '/ch') i_1 = 6; if (address == '/fx') i_1 = 3; var maybeLeaf = node[properties_1[i_1]]; if (maybeLeaf._type) { var leafName_1 = properties_1[i_1]; if (leafName_1[0] == "'") leafName_1 = leafName_1.slice(1); console.log('Testing leaf: ' + address + '/' + leafName_1); if (maybeLeaf._type == 'conditional' && leaveKeys) { var key = getLeafValue(maybeLeaf._keyAddress, _this.OSC); if (typeof key == 'object') { rtn.push(key.error); } else { if (maybeLeaf._conditional[key]) { if (maybeLeaf._conditional[key][maybeLeaf._index]) { maybeLeaf = JSON.parse(JSON.stringify(maybeLeaf._conditional[key][maybeLeaf._index])); } else { i_1 = properties_1.length - 1; maybeLeaf = { _type: 'unused' }; } } else rtn.push('Incomplete conditional data'); } } switch (maybeLeaf._type) { case 'bitmap': var bitmapArray_1 = [ '%'.padEnd(maybeLeaf._size + 1, '0'), '%'.padEnd(maybeLeaf._size, '0') + '1', ]; _this._learnTextFromNumber(address + '/' + leafName_1, address.slice(1), i_1, 1, true) .then(function (values) { if (JSON.stringify(values) != JSON.stringify(bitmapArray_1)) { rtn.push(address + '/' + leafName_1); } checkLeaf_1(); }) .catch(function (err) { rej(err); }); break; case 'btnString': var btnStringArray_1 = ['X001', 'X002']; var btnReturnArray_1 = []; _this._sendDatawTimeout(address + '/' + leafName_1, btnStringArray_1[0]) .then(function () { return _this._getNode(address.slice(1)); }) .then(function (nodeValues) { btnReturnArray_1.push(nodeValues[i_1]); return _this._sendDatawTimeout(address + '/' + leafName_1, btnStringArray_1[1]); }) .then(function () { return _this._getNode(address.slice(1)); }) .then(function (nodeValues) { btnReturnArray_1.push(nodeValues[i_1]); if (JSON.stringify(btnReturnArray_1) != JSON.stringify(btnStringArray_1)) { //fs.writeFile('./test.json', JSON.stringify(btnReturnArray), () => {}); //fs.writeFile('./test2.json', JSON.stringify(btnStringArray), () => {}); rtn.push(address + '/' + leafName_1); } checkLeaf_1(); }) .catch(function (err) { rej(err); }); break; case 'encString': var encStringArray_1 = ['X001', 'X002']; var encReturnArray_1 = []; _this._sendDatawTimeout(address + '/' + leafName_1, encStringArray_1[0]) .then(function () { return _this._getNode(address.slice(1)); }) .then(function (nodeValues) { encReturnArray_1.push(nodeValues[i_1]); return _this._sendDatawTimeout(address + '/' + leafName_1, encStringArray_1[1]); }) .then(function () { return _this._getNode(address.slice(1)); }) .then(function (nodeValues) { encReturnArray_1.push(nodeValues[i_1]); if (JSON.stringify(encReturnArray_1) != JSON.stringify(encStringArray_1)) { //fs.writeFile('./test.json', JSON.stringify(encReturnArray), () => {}); //fs.writeFile('./test2.json', JSON.stringify(encStringArray), () => {}); rtn.push(address + '/' + leafName_1); } checkLeaf_1(); }) .catch(function (err) { rej(err); }); break; case 'enum': if (!leaveKeys || !maybeLeaf._isKey) { var isKey_1 = !!maybeLeaf._isKey; var enumArray_1 = maybeLeaf._enum; var enumDelay = 10; if (address.slice(-4) == 'link') enumDelay = 70; _this._learnTextFromNumber(address + '/' + leafName_1, address.slice(1), i_1, enumArray_1.length - 1, true, enumDelay) .then(function (values) { if (JSON.stringify(values) != JSON.stringify(enumArray_1)) { //fs.writeFile('./test.json', JSON.stringify(values), () => {}); //fs.writeFile('./test2.json', JSON.stringify(enumArray), () => {}); /* for (let i = 0; i < enumArray.length; i++) { if (values[i] != enumArray[i]) console.log(values[i] + ' ' + enumArray[i]); } */ rtn.push(address + '/' + leafName_1); checkLeaf_1(); } else { if (isKey_1 && !leaveKeys) { (function () { return __awaiter(_this, void 0, void 0, function () { var _loop_1, this_1, i_2; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: _loop_1 = function (i_2) { return __generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, this_1._setOSC(address + '/' + leafName_1, enumArray_1[i_2]) .then(function () { console.log('Testing leaf: ' + address + '/' + leafName_1 + ', setting: ' + enumArray_1[i_2]); return _this._testTree(node, address, true); }) .then(function (values) { var identifiedValues = values.map(function (x) { return enumArray_1[i_2] + ' ' + x; }); rtn = __spreadArray(__spreadArray([], rtn, true), identifiedValues, true); }) .catch(function (err) { rej(err); })]; case 1: _b.sent(); return [2 /*return*/]; } }); }; this_1 = this; i_2