From da670aa186951a39b416469d48e1543b9c968653 Mon Sep 17 00:00:00 2001 From: Luciano Iam Date: Mon, 13 Apr 2020 09:05:30 +0200 Subject: WebSockets: improve support for callbacks in JS client lib --- share/web_surfaces/builtin/mixer-demo/js/main.js | 38 +++++++++--------- share/web_surfaces/shared/ardour.js | 50 ++++++++++++++++-------- share/web_surfaces/shared/callback.js | 31 +++++++++++++++ share/web_surfaces/shared/channel.js | 22 ++++------- 4 files changed, 92 insertions(+), 49 deletions(-) create mode 100644 share/web_surfaces/shared/callback.js diff --git a/share/web_surfaces/builtin/mixer-demo/js/main.js b/share/web_surfaces/builtin/mixer-demo/js/main.js index 451f55ac62..832316e43e 100644 --- a/share/web_surfaces/builtin/mixer-demo/js/main.js +++ b/share/web_surfaces/builtin/mixer-demo/js/main.js @@ -38,26 +38,28 @@ import { Switch, DiscreteSlider, ContinuousSlider, LogarithmicSlider, main(); function main () { - ardour.messageCallback = (msg) => { - log(`↙ ${msg}`, 'message-in'); - - if (msg.node == 'strip_desc') { - createStrip (msg.addr, ...msg.val); - } else if (msg.node == 'strip_plugin_desc') { - createStripPlugin (msg.addr, ...msg.val); - } else if (msg.node == 'strip_plugin_param_desc') { - createStripPluginParam (msg.addr, ...msg.val); - } else if (FEEDBACK_NODES.includes(msg.node)) { - if (widgets[msg.hash]) { - widgets[msg.hash].value = msg.val[0]; + ardour.addCallback({ + onMessage: (msg) => { + log(`↙ ${msg}`, 'message-in'); + + if (msg.node == 'strip_desc') { + createStrip (msg.addr, ...msg.val); + } else if (msg.node == 'strip_plugin_desc') { + createStripPlugin (msg.addr, ...msg.val); + } else if (msg.node == 'strip_plugin_param_desc') { + createStripPluginParam (msg.addr, ...msg.val); + } else if (FEEDBACK_NODES.includes(msg.node)) { + if (widgets[msg.hash]) { + widgets[msg.hash].value = msg.val[0]; + } } - } - }; - - ardour.errorCallback = () => { - log('Client error', 'error'); - }; + }, + onError: () => { + log('Client error', 'error'); + } + }); + ardour.open(); } diff --git a/share/web_surfaces/shared/ardour.js b/share/web_surfaces/shared/ardour.js index ce0bb2069b..77e6bf49b9 100644 --- a/share/web_surfaces/shared/ardour.js +++ b/share/web_surfaces/shared/ardour.js @@ -22,36 +22,39 @@ import { MessageChannel } from './channel.js'; export class Ardour { constructor () { - this._channel = new MessageChannel(location.host); - this._channel.errorCallback = (error) => this.errorCallback(); - this._channel.messageCallback = (msg) => this._onChannelMessage(msg); + this._callbacks = []; this._pendingRequest = null; + this._channel = new MessageChannel(location.host); + + this._channel.onError = (error) => { + this._fireCallbacks('error', error); + }; + + this._channel.onMessage = (msg) => { + this._onChannelMessage(msg); + }; + } + + addCallback (callback) { + this._callbacks.push(callback); } async open () { - this._channel.closeCallback = () => { - this.errorCallback(new Error('Message channel unexpectedly closed')); + this._channel.onClose = () => { + this._fireCallbacks('error', new Error('Message channel unexpectedly closed')); }; await this._channel.open(); } close () { - this._channel.closeCallback = () => {}; + this._channel.onClose = () => {}; this._channel.close(); } send (msg) { this._channel.send(msg); } - - errorCallback (error) { - // empty - } - - messageCallback (msg) { - // empty - } // Surface metadata API over HTTP @@ -73,7 +76,8 @@ export class Ardour { const xmlDoc = new DOMParser().parseFromString(xmlText, 'text/xml'); return { name: xmlDoc.getElementsByTagName('Name')[0].getAttribute('value'), - description: xmlDoc.getElementsByTagName('Description')[0].getAttribute('value') + description: xmlDoc.getElementsByTagName('Description')[0].getAttribute('value'), + version: xmlDoc.getElementsByTagName('Version')[0].getAttribute('value') } } else { throw this._fetchResponseStatusError(response.status); @@ -151,7 +155,21 @@ export class Ardour { this._pendingRequest.resolve(msg.val); this._pendingRequest = null; } else { - this.messageCallback(msg); + this._fireCallbacks('message', msg); + this._fireCallbacks(msg.node, ...msg.addr, ...msg.val); + } + } + + _fireCallbacks (name, ...args) { + // name_with_underscores -> onNameWithUnderscores + const method = 'on' + name.split('_').map((s) => { + return s[0].toUpperCase() + s.slice(1).toLowerCase(); + }).join(''); + + for (const callback of this._callbacks) { + if (method in callback) { + callback[method](...args) + } } } diff --git a/share/web_surfaces/shared/callback.js b/share/web_surfaces/shared/callback.js new file mode 100644 index 0000000000..1328f49ffb --- /dev/null +++ b/share/web_surfaces/shared/callback.js @@ -0,0 +1,31 @@ +/* + * Copyright © 2020 Luciano Iam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + export class ArdourCallback { + + onTempo (bpm) {} + onStripGain (stripId, db) {} + onStripPan (stripId, value) {} + onStripMute (stripId, value) {} + onStripPluginEnable (stripId, pluginId, value) {} + onStripPluginParamValue (stripId, pluginId, paramId, value) {} + + onMessage (msg) {} + onError (error) {} + + } diff --git a/share/web_surfaces/shared/channel.js b/share/web_surfaces/shared/channel.js index bb67c3bec4..bc5ce704c5 100644 --- a/share/web_surfaces/shared/channel.js +++ b/share/web_surfaces/shared/channel.js @@ -29,19 +29,19 @@ export class MessageChannel { return new Promise((resolve, reject) => { this._socket = new WebSocket(`ws://${this._host}`); - this._socket.onclose = () => this.closeCallback(); + this._socket.onclose = () => this.onClose(); - this._socket.onerror = (error) => this.errorCallback(error); + this._socket.onerror = (error) => this.onError(error); this._socket.onmessage = (event) => { - this.messageCallback (Message.fromJsonText(event.data)); + this.onMessage (Message.fromJsonText(event.data)); }; this._socket.onopen = resolve; }); } - async close () { + close () { this._socket.close(); } @@ -53,16 +53,8 @@ export class MessageChannel { } } - closeCallback () { - // empty - } - - errorCallback (error) { - // empty - } - - messageCallback (msg) { - // empty - } + onClose () {} + onError (error) {} + onMessage (msg) {} } -- cgit v1.2.3