WS: make ArdourClient extend Component

This allows the client object to be observed using the on()
method just like with the mixer and transport components,
instead of passing separate callbacks.

See mixer-demo/js/main.js for an example.
This commit is contained in:
Luciano Iam 2020-06-14 12:34:27 +02:00 committed by Robin Gareus
parent 1369076c14
commit d65e1170b9
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
8 changed files with 51 additions and 66 deletions

View File

@ -27,29 +27,21 @@ import { Switch, DiscreteSlider, ContinuousSlider, LogarithmicSlider,
const ardour = new ArdourClient();
function main () {
ardour.handlers = {
onConnected: (connected) => {
if (connected) {
log('Client connected', 'info');
} else {
log('Client disconnected', 'error');
}
},
onMessage: (message, inbound) => {
if (inbound) {
log(`${message}`, 'message-in');
} else {
log(`${message}`, 'message-out');
}
async function main () {
ardour.on('connected', (connected) => {
if (connected) {
log('Client connected', 'info');
} else {
log('Client disconnected', 'error');
}
};
});
ardour.getSurfaceManifest().then((manifest) => {
const div = document.getElementById('manifest');
div.innerHTML = manifest.name.toUpperCase()
+ ' v' + manifest.version + ' — ' + manifest.description;
ardour.on('message', (msg, inbound) => {
if (inbound) {
log(`${msg}`, 'message-in');
} else {
log(`${msg}`, 'message-out');
}
});
ardour.mixer.on('ready', () => {
@ -59,7 +51,11 @@ import { Switch, DiscreteSlider, ContinuousSlider, LogarithmicSlider,
}
});
ardour.connect();
await ardour.connect();
const manifest = await ardour.getSurfaceManifest();
document.getElementById('manifest').innerHTML = manifest.name.toUpperCase()
+ ' v' + manifest.version + ' — ' + manifest.description;
}
function createStrip (strip, parentDiv) {

View File

@ -2,5 +2,5 @@
<WebSurface>
<Name value="Mixer Demo"/>
<Description value="Mixer control capabilities demo aimed at developers"/>
<Version value="0.1.1"/>
<Version value="0.1.2"/>
</WebSurface>

View File

@ -2,5 +2,5 @@
<WebSurface>
<Name value="Transport"/>
<Description value="Provides basic transport control"/>
<Version value="0.1.1"/>
<Version value="0.1.2"/>
</WebSurface>

View File

@ -16,36 +16,34 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import { Component } from './base/component.js';
import { StateNode } from './base/protocol.js';
import MessageChannel from './base/channel.js';
import Mixer from './components/mixer.js';
import Transport from './components/transport.js';
export default class ArdourClient {
function getOption (options, key, defaultValue) {
return options ? (key in options ? options[key] : defaultValue) : defaultValue;
}
constructor (handlers, options) {
this._options = options || {};
this._components = [];
this._connected = false;
export default class ArdourClient extends Component {
this._channel = new MessageChannel(this._getOption('host', location.host));
constructor (options) {
super(new MessageChannel(getOption(options, 'host', location.host)));
this._channel.onMessage = (msg, inbound) => {
this._handleMessage(msg, inbound);
};
if (this._getOption('components', true)) {
this._mixer = new Mixer(this._channel);
this._transport = new Transport(this._channel);
this._components.push(this._mixer, this._transport);
if (getOption(options, 'components', true)) {
this._mixer = new Mixer(this.channel);
this._transport = new Transport(this.channel);
this._components = [this._mixer, this._transport];
} else {
this._components = [];
}
this.handlers = handlers;
}
this._autoReconnect = getOption(options, 'autoReconnect', true);
this._connected = false;
set handlers (handlers) {
this._handlers = handlers || {};
this._channel.onError = this._handlers.onError || console.log;
this.channel.onMessage = (msg, inbound) => this._handleMessage(msg, inbound);
this.channel.onError = (err) => this.notifyObservers('error', err);
}
// Access to the object-oriented API (enabled by default)
@ -61,12 +59,12 @@ export default class ArdourClient {
// Low level control messages flow through a WebSocket
async connect () {
this._channel.onClose = async () => {
this.channel.onClose = async () => {
if (this._connected) {
this._setConnected(false);
}
if (this._getOption('autoReconnect', true)) {
if (this._autoReconnect) {
await this._sleep(1000);
await this._connect();
}
@ -76,17 +74,17 @@ export default class ArdourClient {
}
disconnect () {
this._channel.onClose = () => {};
this._channel.close();
this.channel.onClose = () => {};
this.channel.close();
this._connected = false;
}
send (msg) {
this._channel.send(msg);
this.channel.send(msg);
}
async sendAndReceive (msg) {
return await this._channel.sendAndReceive(msg);
return await this.channel.sendAndReceive(msg);
}
// Surface metadata API goes over HTTP
@ -126,22 +124,17 @@ export default class ArdourClient {
}
async _connect () {
await this._channel.open();
await this.channel.open();
this._setConnected(true);
}
_setConnected (connected) {
this._connected = connected;
if (this._handlers.onConnected) {
this._handlers.onConnected(this._connected);
}
this.notifyPropertyChanged('connected');
}
_handleMessage (msg, inbound) {
if (this._handlers.onMessage) {
this._handlers.onMessage(msg, inbound);
}
this.notifyObservers('message', msg, inbound);
if (inbound) {
for (const component of this._components) {
@ -156,8 +149,4 @@ export default class ArdourClient {
return new Error(`HTTP response status ${status}`);
}
_getOption (key, defaultValue) {
return key in this._options ? this._options[key] : defaultValue;
}
}

View File

@ -34,7 +34,7 @@ export class Component extends Observable {
this.addObserver(event, callback);
}
notify (property) {
notifyPropertyChanged (property) {
this.notifyObservers(property, this['_' + property]);
}
@ -52,7 +52,7 @@ export class Component extends Observable {
updateLocal (property, value) {
this['_' + property] = value;
this.notify(property);
this.notifyPropertyChanged(property);
}
updateRemote (property, value, node, addr) {

View File

@ -45,7 +45,7 @@ export default class Mixer extends Component {
if (node.startsWith('strip')) {
if (node == StateNode.STRIP_DESCRIPTION) {
this._strips[addr] = new Strip(this, addr, val);
this.notify('strips');
this.notifyPropertyChanged('strips');
return true;
} else {
const stripAddr = [addr[0]];

View File

@ -53,7 +53,7 @@ export default class Plugin extends AddressableComponent {
if (node.startsWith('strip_plugin_param')) {
if (node == StateNode.STRIP_PLUGIN_PARAM_DESCRIPTION) {
this._parameters[addr] = new Parameter(this, addr, val);
this.notify('parameters');
this.notifyPropertyChanged('parameters');
return true;
} else {
if (addr in this._parameters) {

View File

@ -84,7 +84,7 @@ export default class Strip extends AddressableComponent {
if (node.startsWith('strip_plugin')) {
if (node == StateNode.STRIP_PLUGIN_DESCRIPTION) {
this._plugins[addr] = new Plugin(this, addr, val);
this.notify('plugins');
this.notifyPropertyChanged('plugins');
return true;
} else {
const pluginAddr = [addr[0], addr[1]];