@soundworks/core 3.0.4 → 3.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/client/Client.js +1 -1
- package/client/PluginManager.js +4 -3
- package/client/Socket.js +70 -39
- package/common/ParameterBag.js +561 -0
- package/common/SharedState.js +218 -50
- package/common/SharedStateManagerClient.js +7 -1
- package/common/SharedStateManagerServer.js +100 -17
- package/common/SharedStatePrivate.js +96 -55
- package/common/shared-state-utils.js +6 -5
- package/common/sockets-encoder-decoder.js +1 -1
- package/package.json +15 -14
- package/server/Client.js +2 -4
- package/server/PluginManager.js +4 -3
- package/server/Server.js +51 -7
- package/server/utils/Db.js +0 -67
package/README.md
CHANGED
|
@@ -56,6 +56,7 @@ The simplest way to start a new `soundworks` application is using the applicatio
|
|
|
56
56
|
|
|
57
57
|
## Academic Papers
|
|
58
58
|
|
|
59
|
+
- Benjamin Matuszewski. A Web-Based Framework for Distributed Music System Research and Creation. AES - Journal of the Audio Engineering Society Audio-Accoustics-Application, Audio Engineering Society Inc, 2020. <[hal-03033143](https://hal.archives-ouvertes.fr/hal-03033143)>
|
|
59
60
|
- Benjamin Matuszewski. Soundworks - A Framework for Networked Music Systems on the Web - State of Affairs and New Developments. Proceedings of the Web Audio Conference (WAC) 2019, Dec 2019, Trondheim, Norway. <[hal-02387783](https://hal.archives-ouvertes.fr/hal-02387783)>
|
|
60
61
|
- Benjamin Matuszewski, Norbert Schnell, Frédéric Bevilacqua. Interaction Topologies in Mobile-Based Situated Networked Music Systems. Wireless Communications and Mobile Computing, Hindawi Publishing Corporation, 2019, 2019, pp.9142490. ⟨10.1155/2019/9142490⟩. <[hal-02086673](https://hal.archives-ouvertes.fr/hal-02086673)>
|
|
61
62
|
- Norbert Schnell, Sébastien Robaszkiewicz. Soundworks – A playground for artists and developers to create collaborative mobile web performances. `Proceedings of the Web Audio Conference (WAC'15), 2015, Paris, France. <[hal-01580797](https://hal.archives-ouvertes.fr/hal-01580797)>
|
package/client/Client.js
CHANGED
|
@@ -118,7 +118,7 @@ class Client {
|
|
|
118
118
|
// url: '',
|
|
119
119
|
path: 'socket' // pingInterval: 5 * 1000,
|
|
120
120
|
|
|
121
|
-
}, config.env.websockets); // init communications
|
|
121
|
+
}, config.env.websockets); // init socket communications (string and binary)
|
|
122
122
|
|
|
123
123
|
await this.socket.init(this.type, this.config);
|
|
124
124
|
return Promise.resolve();
|
package/client/PluginManager.js
CHANGED
|
@@ -141,7 +141,8 @@ class PluginManager {
|
|
|
141
141
|
|
|
142
142
|
register(name, factory, options = {}, deps = []) {
|
|
143
143
|
if (this._registeredPlugins[name]) {
|
|
144
|
-
|
|
144
|
+
const ctor = factory(_AbstractPlugin.default);
|
|
145
|
+
throw new Error(`[soundworks:core] Plugin "${name}" of type "${ctor.name}" already registered`);
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
const ctor = factory(_AbstractPlugin.default);
|
|
@@ -164,7 +165,7 @@ class PluginManager {
|
|
|
164
165
|
|
|
165
166
|
get(name, _experienceRequired = false) {
|
|
166
167
|
if (!this._registeredPlugins[name]) {
|
|
167
|
-
throw new Error(`Cannot get or require plugin "${name}", plugin is not registered
|
|
168
|
+
throw new Error(`[soundworks:core] Cannot get or require plugin "${name}", plugin is not registered
|
|
168
169
|
> registered plugins are:
|
|
169
170
|
${Object.keys(this._registeredPlugins).map(n => `> - ${n}\n`).join('')}
|
|
170
171
|
`);
|
|
@@ -172,7 +173,7 @@ ${Object.keys(this._registeredPlugins).map(n => `> - ${n}\n`).join('')}
|
|
|
172
173
|
|
|
173
174
|
|
|
174
175
|
if (_experienceRequired && this.signals.start.value === true) {
|
|
175
|
-
throw new Error(`Plugin "${name}" required after pluginManager start`);
|
|
176
|
+
throw new Error(`[soundworks:core] Plugin "${name}" required after pluginManager start`);
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
if (!this._instances[name]) {
|
package/client/Socket.js
CHANGED
|
@@ -53,6 +53,13 @@ class Socket {
|
|
|
53
53
|
|
|
54
54
|
/** @private */
|
|
55
55
|
this.ws = null;
|
|
56
|
+
/**
|
|
57
|
+
* WebSocket instance (binary protocol - binaryType = 'arraybuffer').
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/** @private */
|
|
61
|
+
|
|
62
|
+
this.binaryWs = null;
|
|
56
63
|
this._stringListeners = new Map();
|
|
57
64
|
this._binaryListeners = new Map();
|
|
58
65
|
}
|
|
@@ -67,11 +74,11 @@ class Socket {
|
|
|
67
74
|
/** @private */
|
|
68
75
|
|
|
69
76
|
|
|
70
|
-
init(clientType, config) {
|
|
77
|
+
async init(clientType, config) {
|
|
71
78
|
// unique key that allows to associate the two sockets to the same client.
|
|
72
79
|
// note: the key is only used to pair to two sockets, so its usage is very
|
|
73
80
|
// limited in time therefore a random number should hopefully be sufficient.
|
|
74
|
-
const key = (Math.random() + '').replace(/^0
|
|
81
|
+
const key = (Math.random() + '').replace(/^0\./, ''); // open web sockets
|
|
75
82
|
|
|
76
83
|
let {
|
|
77
84
|
path
|
|
@@ -106,47 +113,71 @@ class Socket {
|
|
|
106
113
|
// ----------------------------------------------------------
|
|
107
114
|
|
|
108
115
|
const stringSocketUrl = `${url}?binary=0&${queryParams}`;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
116
|
+
await new Promise((resolve, reject) => {
|
|
117
|
+
const trySocket = async () => {
|
|
118
|
+
log(`[string socket] trying connection - url: ${stringSocketUrl}`);
|
|
119
|
+
const ws = new _isomorphicWs.default(stringSocketUrl);
|
|
120
|
+
ws.addEventListener('open', connectEvent => {
|
|
121
|
+
// parse incoming messages for pubsub
|
|
122
|
+
this.ws = ws;
|
|
123
|
+
this.ws.addEventListener('message', e => {
|
|
124
|
+
const [channel, args] = (0, _socketsEncoderDecoder.unpackStringMessage)(e.data);
|
|
125
|
+
|
|
126
|
+
this._emit(false, channel, ...args);
|
|
127
|
+
}); // broadcast all `WebSocket` native events
|
|
128
|
+
|
|
129
|
+
['close', 'error', 'upgrade', 'message'].forEach(eventName => {
|
|
130
|
+
this.ws.addEventListener(eventName, e => {
|
|
131
|
+
this._emit(false, eventName, e);
|
|
132
|
+
});
|
|
133
|
+
}); // forward open event
|
|
134
|
+
|
|
135
|
+
this._emit(false, 'open', connectEvent); // continue with raw socket
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
resolve();
|
|
139
|
+
}); // cf. https://github.com/collective-soundworks/soundworks/issues/17
|
|
140
|
+
|
|
141
|
+
ws.addEventListener('error', e => {
|
|
142
|
+
if (e.type === 'error' && e.error.code === 'ECONNREFUSED') {
|
|
143
|
+
console.log('[socket] connection refused - (retry in 1s)');
|
|
144
|
+
setTimeout(trySocket, 1000);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
trySocket();
|
|
150
|
+
}); // // ----------------------------------------------------------
|
|
151
|
+
// // init binary socket
|
|
152
|
+
// // ----------------------------------------------------------
|
|
128
153
|
|
|
129
154
|
const binarySocketUrl = `${url}?binary=1&${queryParams}`;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
await new Promise((resolve, reject) => {
|
|
156
|
+
log(`[binary socket] trying connection - url: ${binarySocketUrl}`);
|
|
157
|
+
const ws = new _isomorphicWs.default(binarySocketUrl);
|
|
158
|
+
ws.binaryType = 'arraybuffer';
|
|
159
|
+
ws.addEventListener('open', connectEvent => {
|
|
160
|
+
// parse incoming messages for pubsub
|
|
161
|
+
this.binaryWs = ws;
|
|
162
|
+
this.binaryWs.addEventListener('message', e => {
|
|
163
|
+
const [channel, data] = (0, _socketsEncoderDecoder.unpackBinaryMessage)(e.data);
|
|
164
|
+
|
|
165
|
+
this._emit(true, channel, data);
|
|
166
|
+
}); // broadcast all `WebSocket` native events
|
|
167
|
+
|
|
168
|
+
['close', 'error', 'upgrade', 'message'].forEach(eventName => {
|
|
169
|
+
this.binaryWs.addEventListener(eventName, e => {
|
|
170
|
+
this._emit(true, eventName, e);
|
|
171
|
+
});
|
|
172
|
+
}); // forward open event
|
|
173
|
+
|
|
174
|
+
this._emit(true, 'open', connectEvent);
|
|
175
|
+
|
|
176
|
+
resolve();
|
|
146
177
|
});
|
|
147
|
-
}); //
|
|
178
|
+
}); // everyone is connected
|
|
148
179
|
|
|
149
|
-
return Promise.
|
|
180
|
+
return Promise.resolve();
|
|
150
181
|
}
|
|
151
182
|
/** @private */
|
|
152
183
|
|