@soundworks/core 4.0.0-alpha.1 → 4.0.0-alpha.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/.eslintrc +0 -1
- package/README.md +25 -15
- package/package.json +2 -2
- package/src/client/Client.js +37 -3
- package/src/client/Context.js +37 -10
- package/src/client/Plugin.js +2 -1
- package/src/client/PluginManager.js +26 -17
- package/src/client/Socket.js +44 -39
- package/src/client/index.js +0 -33
- package/src/common/BasePluginManager.js +12 -3
- package/src/common/ParameterBag.js +33 -210
- package/src/common/utils.js +6 -0
- package/src/server/Context.js +162 -18
- package/src/server/ContextManager.js +4 -5
- package/src/server/Plugin.js +2 -1
- package/src/server/PluginManager.js +26 -6
- package/src/server/Server.js +189 -69
- package/src/server/Socket.js +105 -62
- package/src/server/Sockets.js +27 -22
- package/src/server/StateManager.js +232 -24
- package/src/server/index.js +0 -20
package/.eslintrc
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `soundworks`
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/@soundworks%2Fcore)
|
|
4
|
+
[](http://commitizen.github.io/cz-cli/)
|
|
4
5
|
|
|
5
6
|

|
|
6
7
|
|
|
@@ -18,6 +19,8 @@ The best and most simple way to start using `soundworks` is to use the `@soundwo
|
|
|
18
19
|
npx @soundworks/create@latest
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+

|
|
23
|
+
|
|
21
24
|
See [https://soundworks.dev/guides/getting-started.html](https://soundworks.dev/guides/getting-started.html) for more informations on the wizard and how to start with `soundworks`.
|
|
22
25
|
|
|
23
26
|
<!--
|
|
@@ -38,11 +41,17 @@ git checkout v4
|
|
|
38
41
|
serve docs
|
|
39
42
|
```
|
|
40
43
|
|
|
44
|
+
Feel welcome to open an [issue](https://github.com/collective-soundworks/soundworks/issues) or a PR if you find any inconsistency, error or missing information in the documentation.
|
|
45
|
+
|
|
46
|
+
## Share with Us
|
|
47
|
+
|
|
48
|
+
If you made an application using `soundworks` please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
|
|
49
|
+
|
|
41
50
|
## TypeScript Support
|
|
42
51
|
|
|
43
52
|
Basic TypeScript support will be proposed in a (hopefully) near future.
|
|
44
53
|
|
|
45
|
-
However,
|
|
54
|
+
However, for maintenance reasons, we aim at following the TC39 and W3C specifications as close as possible. Therefore, we will wait for the https://github.com/tc39/proposal-type-annotations proposal to reach stage 3 to update the source code in a more integrated manner.
|
|
46
55
|
|
|
47
56
|
## Install
|
|
48
57
|
|
|
@@ -52,27 +61,28 @@ Note that the `@soundworks/core` package is automatically installed when creatin
|
|
|
52
61
|
npm install @soundworks/core
|
|
53
62
|
```
|
|
54
63
|
|
|
55
|
-
##
|
|
56
|
-
|
|
57
|
-
If you made an application using `soundworks` please let us know here: https://github.com/collective-soundworks/soundworks/discussions/61
|
|
64
|
+
## Credits
|
|
58
65
|
|
|
59
|
-
|
|
66
|
+
`soundworks` has been initiated by [Norbert Schnell](https://github.com/NorbertSchnell), [Sébastien Robaszkiewicz](https://github.com/i-Robi), and [Benjamin Matuszewski](https://github.com/b-ma) at the [ISMM](http://ismm.ircam.fr/) team at [Ircam - Centre Pompidou](http://www.ircam.fr/) in the context of the [CoSiMa](http://cosima.ircam.fr/) research project founded by the French National Research Agency (ANR).
|
|
60
67
|
|
|
61
|
-
|
|
62
|
-
- 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)>
|
|
63
|
-
- 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)>
|
|
64
|
-
- 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)>
|
|
68
|
+
Development is now led by Benjamin Matuszewski, in the [Sound Music Movement Interaction Team](https://www.stms-lab.fr/team/interaction-son-musique-mouvement/) from the Ircam's STMS-LAB.
|
|
65
69
|
|
|
66
|
-
|
|
70
|
+
### Supporting Research Projects
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
Initial and futher developments has been supported by the following research projects:
|
|
69
73
|
|
|
70
|
-
|
|
71
|
-
- The [RAPID-MIX project](http://rapidmix.goldsmithsdigital.com/), funded by the European Union’s Horizon 2020 research and innovation program
|
|
74
|
+
- The [DOTS](http://dots.ircam.fr/) project, funded by the French National Research Agency (ANR)
|
|
72
75
|
- The Ircam projects _BeCoMe_ and _SO(a)P_
|
|
73
|
-
- The _Constella(c)tions_ residency
|
|
76
|
+
- The _Constella(c)tions_ residency, funded by the STARTS program of the European Commission
|
|
77
|
+
- The [RAPID-MIX project](http://rapidmix.goldsmithsdigital.com/), funded by the European Union’s Horizon 2020 research and innovation program
|
|
78
|
+
- The [CoSiMa](http://cosima.ircam.fr/) project, funded by the French National Research Agency (ANR)
|
|
74
79
|
|
|
75
|
-
|
|
80
|
+
### Academic Papers
|
|
81
|
+
|
|
82
|
+
- 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)>
|
|
83
|
+
- 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)>
|
|
84
|
+
- 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)>
|
|
85
|
+
- 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)>
|
|
76
86
|
|
|
77
87
|
## License
|
|
78
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soundworks/core",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.3",
|
|
4
4
|
"description": "Open-source creative coding framework for distributed applications based on Web technologies",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Benjamin Matuszewski",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"node": ">=16.0.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
|
-
"doc": "npm run jsdoc
|
|
46
|
+
"doc": "npm run jsdoc",
|
|
47
47
|
"jsdoc": "rm -Rf docs && jsdoc -c .jsdoc.json --verbose && cp -R assets docs/",
|
|
48
48
|
"lint": "npx eslint src",
|
|
49
49
|
"test": "mocha",
|
package/src/client/Client.js
CHANGED
|
@@ -14,7 +14,40 @@ import { isBrowser } from '../common/utils.js';
|
|
|
14
14
|
import logger from '../common/logger.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Configuration object for a client running in a browser runtime.
|
|
18
|
+
*
|
|
19
|
+
* @typedef BrowserClientConfig
|
|
20
|
+
* @memberof client
|
|
21
|
+
* @type {object}
|
|
22
|
+
* @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
|
|
23
|
+
* @property {object} [app] - Application configration object.
|
|
24
|
+
* @property {string} [app.name=''] - Name of the application.
|
|
25
|
+
* @property {string} [app.author=''] - Name of the author.
|
|
26
|
+
* @property {object} [env] - Environment configration object.
|
|
27
|
+
* @property {string} [env.websockets={}] - Configuration options for websockets.
|
|
28
|
+
* @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Configuration object for a client running in a node runtime.
|
|
33
|
+
*
|
|
34
|
+
* @typedef NodeClientConfig
|
|
35
|
+
* @memberof client
|
|
36
|
+
* @type {object}
|
|
37
|
+
* @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
|
|
38
|
+
* @property {object} [app] - Application configration object.
|
|
39
|
+
* @property {string} [app.name=''] - Name of the application.
|
|
40
|
+
* @property {string} [app.author=''] - Name of the author.
|
|
41
|
+
* @property {object} env - Environment configration object.
|
|
42
|
+
* @property {boolean} env.serverAddress - Domain name or IP of the server.
|
|
43
|
+
* @property {boolean} env.useHttps - Define is the server run in http or in https.
|
|
44
|
+
* @property {boolean} env.port - Port on which the server is listening.
|
|
45
|
+
* @property {string} [env.websockets={}] - Configuration options for websockets.
|
|
46
|
+
* @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The `Client` class is the main entry point for the client-side of a soundworks
|
|
18
51
|
* application.
|
|
19
52
|
*
|
|
20
53
|
* A `Client` instance allows to access soundworks components such as {@link client.StateManager},
|
|
@@ -269,8 +302,9 @@ class Client {
|
|
|
269
302
|
* method if it has not been called manually.
|
|
270
303
|
*
|
|
271
304
|
* What it does:
|
|
272
|
-
* -
|
|
273
|
-
* -
|
|
305
|
+
* - implicitly call {@link client.Client#init} if not done manually
|
|
306
|
+
* - start all created contexts. For that to happen, you will have to call `client.init`
|
|
307
|
+
* manually and instantiate the contexts between `client.init()` and `client.start()`
|
|
274
308
|
*
|
|
275
309
|
* @example
|
|
276
310
|
* import { Client } from '@soundworks/core/client.js'
|
package/src/client/Context.js
CHANGED
|
@@ -69,11 +69,15 @@ class Context {
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* The soundworks client instance.
|
|
72
|
+
* @type {client.Client}
|
|
73
|
+
* @readonly
|
|
72
74
|
*/
|
|
73
75
|
this.client = client;
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
78
|
* Status of the context, i.e. 'idle', 'inited', 'started', 'errored'
|
|
79
|
+
* @type {string}
|
|
80
|
+
* @readonly
|
|
77
81
|
*/
|
|
78
82
|
this.status = 'idle';
|
|
79
83
|
|
|
@@ -113,10 +117,16 @@ class Context {
|
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
/**
|
|
116
|
-
*
|
|
120
|
+
* Optionnal user-defined name of the context (defaults to the class name).
|
|
117
121
|
*
|
|
118
|
-
*
|
|
122
|
+
* The context manager will match the client-side and server-side contexts based
|
|
123
|
+
* on this name. If the {@link server.ContextManager} don't find a corresponding
|
|
124
|
+
* user-defined context with the same name, it will use a default (noop) context.
|
|
125
|
+
*
|
|
126
|
+
* @readonly
|
|
127
|
+
* @type {string}
|
|
119
128
|
* @example
|
|
129
|
+
* // server-side and client-side contexts are matched based on their respective `name`
|
|
120
130
|
* class MyContext extends Context {
|
|
121
131
|
* get name() {
|
|
122
132
|
* return 'my-user-defined-context-name';
|
|
@@ -128,21 +138,38 @@ class Context {
|
|
|
128
138
|
}
|
|
129
139
|
|
|
130
140
|
/**
|
|
131
|
-
* Start the context. This method is
|
|
132
|
-
*
|
|
133
|
-
*
|
|
141
|
+
* Start the context. This method is lazilly called when the client enters the
|
|
142
|
+
* context for the first time (cf. ${client.Context#enter}). If you know some
|
|
143
|
+
* some heavy and/or potentially long job has to be done when starting the context
|
|
144
|
+
* (e.g. call to a web service) it may be a good practice to call it explicitely.
|
|
145
|
+
*
|
|
146
|
+
* This method should be implemented to perform operations that are valid for the
|
|
147
|
+
* whole lifetime of the context, regardless the client enters or exits the context.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* import { Context } from '@soundworks/core/client.js';
|
|
151
|
+
*
|
|
152
|
+
* class MyContext extends Context {
|
|
153
|
+
* async start() {
|
|
154
|
+
* await super.start();
|
|
155
|
+
* await this.doSomeLongJob();
|
|
156
|
+
* }
|
|
157
|
+
* }
|
|
134
158
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
159
|
+
* // Instantiate the context
|
|
160
|
+
* const myContext = new Context(client);
|
|
161
|
+
* // manually start the context to perform the long operation before the client
|
|
162
|
+
* // enters the context.
|
|
163
|
+
* await myContext.start();
|
|
137
164
|
*/
|
|
138
165
|
async start() {}
|
|
139
166
|
|
|
140
167
|
/**
|
|
141
168
|
* Stop the context. This method is automatically called when `await client.stop()`
|
|
142
|
-
* is called.
|
|
169
|
+
* is called. It should be used to cleanup context wise operations made in `start()`
|
|
170
|
+
* (e.g. destroy the reusable audio graph).
|
|
143
171
|
*
|
|
144
|
-
*
|
|
145
|
-
* wise behavior regardeless the client enters or exists the context.
|
|
172
|
+
* _WARNING: this method should never be called manually._
|
|
146
173
|
*/
|
|
147
174
|
async stop() {}
|
|
148
175
|
|
package/src/client/Plugin.js
CHANGED
|
@@ -14,7 +14,8 @@ import BasePlugin from '../common/BasePlugin.js';
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Base class to extend in order to create
|
|
17
|
+
* Base class to extend in order to create the client-side counterpart of a
|
|
18
|
+
* `soundworks` plugin.
|
|
18
19
|
*
|
|
19
20
|
* In the `soundworks` paradigm, a plugin is a component that allows to extend
|
|
20
21
|
* the framework capabilities by encapsulating common and reusable logic in
|
|
@@ -23,7 +23,7 @@ import Client from './Client.js';
|
|
|
23
23
|
*
|
|
24
24
|
* Plugins should always be registered both client-side and server-side,
|
|
25
25
|
* and before {@link client.Client#start} or {@link server.Server#start}
|
|
26
|
-
*
|
|
26
|
+
* to be properly initialized.
|
|
27
27
|
*
|
|
28
28
|
* In some sitautions, you might want to register the same plugin factory several times
|
|
29
29
|
* using different ids (e.g. for watching several parts of the file system, etc.).
|
|
@@ -35,12 +35,13 @@ import Client from './Client.js';
|
|
|
35
35
|
* See {@link client.Client#pluginManager}
|
|
36
36
|
*
|
|
37
37
|
* ```
|
|
38
|
+
* // client-side
|
|
38
39
|
* import { Client } from '@soundworks/core/client.js';
|
|
39
|
-
* import
|
|
40
|
+
* import syncPlugin from '@soundworks/plugin-sync/client.js';
|
|
40
41
|
*
|
|
41
42
|
* const client = new Client(config);
|
|
42
43
|
* // register the plugin before `client.start()`
|
|
43
|
-
* client.pluginManager.register('sync',
|
|
44
|
+
* client.pluginManager.register('sync', syncPlugin);
|
|
44
45
|
*
|
|
45
46
|
* await client.start();
|
|
46
47
|
*
|
|
@@ -52,6 +53,25 @@ import Client from './Client.js';
|
|
|
52
53
|
* }, 1000);
|
|
53
54
|
* ```
|
|
54
55
|
*
|
|
56
|
+
* ```
|
|
57
|
+
* // server-side
|
|
58
|
+
* import { Server } from '@soundworks/core/server.js';
|
|
59
|
+
* import syncPlugin from '@soundworks/plugin-sync/server.js';
|
|
60
|
+
*
|
|
61
|
+
* const server = new Server(config);
|
|
62
|
+
* // register the plugin before `server.start()`
|
|
63
|
+
* server.pluginManager.register('sync', syncPlugin);
|
|
64
|
+
*
|
|
65
|
+
* await server.start();
|
|
66
|
+
*
|
|
67
|
+
* const sync = await server.pluginManager.get('sync');
|
|
68
|
+
*
|
|
69
|
+
* setInterval(() => {
|
|
70
|
+
* // log the estimated global synced clock alongside the local clock.
|
|
71
|
+
* console.log(sync.getSyncTime(), sync.getLocalTime());
|
|
72
|
+
* }, 1000);
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
55
75
|
* @memberof client
|
|
56
76
|
* @extends BasePluginManager
|
|
57
77
|
* @inheritdoc
|
|
@@ -91,8 +111,8 @@ class PluginManager extends BasePluginManager {
|
|
|
91
111
|
* initialization (e.g. to display initialization screen, etc.), you should rely
|
|
92
112
|
* on the `onStateChange` method.
|
|
93
113
|
*
|
|
94
|
-
* _Note: the async API is designed to enable the dynamic creation of plugins
|
|
95
|
-
* without brealing changes) in a future release._
|
|
114
|
+
* _Note: the async API is designed to enable the dynamic creation of plugins
|
|
115
|
+
* (hopefully without brealing changes) in a future release._
|
|
96
116
|
*
|
|
97
117
|
* @param {client.Plugin#id} id - Id of the plugin as defined when registered.
|
|
98
118
|
* @returns {client.Plugin}
|
|
@@ -105,18 +125,7 @@ class PluginManager extends BasePluginManager {
|
|
|
105
125
|
throw new Error(`[soundworks.PluginManager] Cannot get plugin before "client.init()"`);
|
|
106
126
|
}
|
|
107
127
|
|
|
108
|
-
return super.
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// client only methods
|
|
112
|
-
// ------------------------------------------------------------
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @protected
|
|
116
|
-
* @ignore
|
|
117
|
-
*/
|
|
118
|
-
getRegisteredPlugins() {
|
|
119
|
-
return Array.from(this._registeredPlugins.keys());
|
|
128
|
+
return super.unsafeGet(id);
|
|
120
129
|
}
|
|
121
130
|
}
|
|
122
131
|
|
package/src/client/Socket.js
CHANGED
|
@@ -28,35 +28,34 @@ import { isBrowser } from '../common/utils.js';
|
|
|
28
28
|
/**
|
|
29
29
|
* The Socket class is a simple publish / subscribe wrapper built on top of the
|
|
30
30
|
* [isomorphic-ws](https://github.com/heineiuo/isomorphic-ws) library.
|
|
31
|
-
* An instance of `Socket` is automatically created by the `soundworks.Client
|
|
31
|
+
* An instance of `Socket` is automatically created by the `soundworks.Client`
|
|
32
|
+
* (see {@link client.Client#socket}).
|
|
32
33
|
*
|
|
33
|
-
* _Important: In most cases, you should consider using a {@link client.SharedState}
|
|
34
|
-
*
|
|
34
|
+
* _Important: In most cases, you should consider using a {@link client.SharedState}
|
|
35
|
+
* rather than directly using the sockets._
|
|
35
36
|
*
|
|
36
37
|
* The Socket class concurrently opens two different WebSockets:
|
|
37
|
-
* - a socket configured with `binaryType = '
|
|
38
|
-
*
|
|
39
|
-
* - a socket configured with `binaryType=arraybuffer` for efficient streaming
|
|
38
|
+
* - a socket configured with `binaryType = 'blob'` for JSON compatible data
|
|
39
|
+
* types (i.e. string, number, boolean, object, array and null).
|
|
40
|
+
* - a socket configured with `binaryType= 'arraybuffer'` for efficient streaming
|
|
40
41
|
* of binary data.
|
|
41
42
|
*
|
|
42
43
|
* Both sockets re-emits all "native" ws events ('open', 'upgrade', 'close', 'error'
|
|
43
44
|
* and 'message'.
|
|
44
45
|
*
|
|
45
|
-
* See {@link client.Client#socket}
|
|
46
|
-
*
|
|
47
46
|
* @memberof client
|
|
48
47
|
* @hideconstructor
|
|
49
48
|
*/
|
|
50
49
|
class Socket {
|
|
51
50
|
constructor() {
|
|
52
51
|
/**
|
|
53
|
-
* WebSocket instance
|
|
52
|
+
* WebSocket instance configured with `binaryType = 'blob'`.
|
|
54
53
|
*
|
|
55
54
|
* @private
|
|
56
55
|
*/
|
|
57
56
|
this.ws = null;
|
|
58
57
|
/**
|
|
59
|
-
* WebSocket instance
|
|
58
|
+
* WebSocket instance configured with `binaryType = 'arraybuffer'`.
|
|
60
59
|
*
|
|
61
60
|
* @private
|
|
62
61
|
*/
|
|
@@ -231,6 +230,22 @@ class Socket {
|
|
|
231
230
|
return Promise.resolve();
|
|
232
231
|
}
|
|
233
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Removes all listeners and immediately close the two sockets. Is automatically
|
|
235
|
+
* called on `client.stop()`
|
|
236
|
+
*
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
async terminate() {
|
|
240
|
+
this.removeAllListeners();
|
|
241
|
+
this.removeAllBinaryListeners();
|
|
242
|
+
|
|
243
|
+
this.ws.close();
|
|
244
|
+
this.binaryWs.close();
|
|
245
|
+
|
|
246
|
+
return Promise.resolve();
|
|
247
|
+
}
|
|
248
|
+
|
|
234
249
|
/**
|
|
235
250
|
* @param {boolean} binary - Emit to either the string or binary socket.
|
|
236
251
|
* @param {string} channel - Channel name.
|
|
@@ -293,10 +308,11 @@ class Socket {
|
|
|
293
308
|
}
|
|
294
309
|
|
|
295
310
|
/**
|
|
296
|
-
* Send JSON compatible
|
|
311
|
+
* Send messages with JSON compatible data types on a given channel.
|
|
297
312
|
*
|
|
298
|
-
* @param {string} channel - Channel name
|
|
299
|
-
* @param {...*} args -
|
|
313
|
+
* @param {string} channel - Channel name.
|
|
314
|
+
* @param {...*} args - Payload of the message. As many arguments as needed, of
|
|
315
|
+
* JSON compatible data types (i.e. string, number, boolean, object, array and null).
|
|
300
316
|
*/
|
|
301
317
|
send(channel, ...args) {
|
|
302
318
|
const msg = packStringMessage(channel, ...args);
|
|
@@ -304,10 +320,12 @@ class Socket {
|
|
|
304
320
|
}
|
|
305
321
|
|
|
306
322
|
/**
|
|
307
|
-
* Listen
|
|
323
|
+
* Listen messages with JSON compatible data types on a given channel.
|
|
308
324
|
*
|
|
309
|
-
* @param {string} channel - Channel name
|
|
310
|
-
* @param {Function} callback - Callback to execute when a message is received
|
|
325
|
+
* @param {string} channel - Channel name.
|
|
326
|
+
* @param {Function} callback - Callback to execute when a message is received,
|
|
327
|
+
* arguments of the callback function will match the arguments sent using the
|
|
328
|
+
* {@link server.Socket#send} method.
|
|
311
329
|
*/
|
|
312
330
|
addListener(channel, callback) {
|
|
313
331
|
this._addListener(this._stringListeners, channel, callback);
|
|
@@ -316,7 +334,7 @@ class Socket {
|
|
|
316
334
|
/**
|
|
317
335
|
* Remove a listener from JSON compatible messages on a given channel.
|
|
318
336
|
*
|
|
319
|
-
* @param {string} channel - Channel name
|
|
337
|
+
* @param {string} channel - Channel name.
|
|
320
338
|
* @param {Function} callback - Callback to remove.
|
|
321
339
|
*/
|
|
322
340
|
removeListener(channel, callback) {
|
|
@@ -324,9 +342,9 @@ class Socket {
|
|
|
324
342
|
}
|
|
325
343
|
|
|
326
344
|
/**
|
|
327
|
-
* Remove all listeners
|
|
345
|
+
* Remove all listeners of messages with JSON compatible data types.
|
|
328
346
|
*
|
|
329
|
-
* @param {string} channel - Channel name
|
|
347
|
+
* @param {string} channel - Channel name.
|
|
330
348
|
*/
|
|
331
349
|
removeAllListeners(channel = null) {
|
|
332
350
|
this._removeAllListeners(this._stringListeners, channel);
|
|
@@ -335,7 +353,7 @@ class Socket {
|
|
|
335
353
|
/**
|
|
336
354
|
* Send binary messages on a given channel.
|
|
337
355
|
*
|
|
338
|
-
* @param {string} channel - Channel name
|
|
356
|
+
* @param {string} channel - Channel name.
|
|
339
357
|
* @param {TypedArray} typedArray - Binary data to be sent.
|
|
340
358
|
*/
|
|
341
359
|
sendBinary(channel, typedArray) {
|
|
@@ -344,9 +362,9 @@ class Socket {
|
|
|
344
362
|
}
|
|
345
363
|
|
|
346
364
|
/**
|
|
347
|
-
* Listen binary messages on a given channel
|
|
365
|
+
* Listen binary messages on a given channel
|
|
348
366
|
*
|
|
349
|
-
* @param {string} channel - Channel name
|
|
367
|
+
* @param {string} channel - Channel name.
|
|
350
368
|
* @param {Function} callback - Callback to execute when a message is received.
|
|
351
369
|
*/
|
|
352
370
|
addBinaryListener(channel, callback) {
|
|
@@ -354,36 +372,23 @@ class Socket {
|
|
|
354
372
|
}
|
|
355
373
|
|
|
356
374
|
/**
|
|
357
|
-
* Remove a listener
|
|
375
|
+
* Remove a listener of binary compatible messages from a given channel
|
|
358
376
|
*
|
|
359
|
-
* @param {string} channel - Channel
|
|
360
|
-
* @param {Function} callback - Callback to
|
|
377
|
+
* @param {string} channel - Channel name.
|
|
378
|
+
* @param {Function} callback - Callback to remove.
|
|
361
379
|
*/
|
|
362
380
|
removeBinaryListener(channel, callback) {
|
|
363
381
|
this._removeListener(this._binaryListeners, channel, callback);
|
|
364
382
|
}
|
|
365
383
|
|
|
366
384
|
/**
|
|
367
|
-
* Remove all listeners
|
|
385
|
+
* Remove all listeners of binary compatible messages on a given channel
|
|
368
386
|
*
|
|
369
387
|
* @param {string} channel - Channel of the message.
|
|
370
388
|
*/
|
|
371
389
|
removeAllBinaryListeners(channel = null) {
|
|
372
390
|
this._removeAllListeners(this._binaryListeners, channel);
|
|
373
391
|
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Removes all listeners and immediately close the two sockets.
|
|
377
|
-
*/
|
|
378
|
-
async terminate() {
|
|
379
|
-
this.removeAllListeners();
|
|
380
|
-
this.removeAllBinaryListeners();
|
|
381
|
-
|
|
382
|
-
this.ws.close();
|
|
383
|
-
this.binaryWs.close();
|
|
384
|
-
|
|
385
|
-
return Promise.resolve();
|
|
386
|
-
}
|
|
387
392
|
}
|
|
388
393
|
|
|
389
394
|
export default Socket;
|
package/src/client/index.js
CHANGED
|
@@ -1,36 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration object for a client running in a browser runtime.
|
|
3
|
-
*
|
|
4
|
-
* @typedef BrowserClientConfig
|
|
5
|
-
* @memberof client
|
|
6
|
-
* @type {object}
|
|
7
|
-
* @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
|
|
8
|
-
* @property {object} [app] - Application configration object.
|
|
9
|
-
* @property {string} [app.name=''] - Name of the application.
|
|
10
|
-
* @property {string} [app.author=''] - Name of the author.
|
|
11
|
-
* @property {object} [env] - Environment configration object.
|
|
12
|
-
* @property {string} [env.websockets={}] - Configuration options for websockets.
|
|
13
|
-
* @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Configuration object for a client running in a node runtime.
|
|
18
|
-
*
|
|
19
|
-
* @typedef NodeClientConfig
|
|
20
|
-
* @memberof client
|
|
21
|
-
* @type {object}
|
|
22
|
-
* @property {string} role - Role of the client in the application (e.g. 'player', 'controller').
|
|
23
|
-
* @property {object} [app] - Application configration object.
|
|
24
|
-
* @property {string} [app.name=''] - Name of the application.
|
|
25
|
-
* @property {string} [app.author=''] - Name of the author.
|
|
26
|
-
* @property {object} env - Environment configration object.
|
|
27
|
-
* @property {boolean} env.serverAddress - Domain name or IP of the server.
|
|
28
|
-
* @property {boolean} env.useHttps - Define is the server run in http or in https.
|
|
29
|
-
* @property {boolean} env.port - Port on which the server is listening.
|
|
30
|
-
* @property {string} [env.websockets={}] - Configuration options for websockets.
|
|
31
|
-
* @property {string} [env.subpath=''] - If running behind a proxy, path to the application.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
1
|
/**
|
|
35
2
|
* Client-side part of the `soundworks` framework.
|
|
36
3
|
*
|
|
@@ -75,6 +75,14 @@ class BasePluginManager {
|
|
|
75
75
|
this._registeredPlugins.set(id, { ctor, options, deps });
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Returns the list of the registered plugins ids
|
|
80
|
+
* @returns {string[]}
|
|
81
|
+
*/
|
|
82
|
+
getRegisteredPlugins() {
|
|
83
|
+
return Array.from(this._registeredPlugins.keys());
|
|
84
|
+
}
|
|
85
|
+
|
|
78
86
|
/**
|
|
79
87
|
* Initialize all the registered plugin. Executed during the `Client.init()` or
|
|
80
88
|
* `Server.init()` initialization step.
|
|
@@ -98,7 +106,7 @@ class BasePluginManager {
|
|
|
98
106
|
// propagate all 'idle' statuses before start
|
|
99
107
|
this._propagateStateChange();
|
|
100
108
|
|
|
101
|
-
const promises = Array.from(this._registeredPlugins.keys()).map(id => this.
|
|
109
|
+
const promises = Array.from(this._registeredPlugins.keys()).map(id => this.unsafeGet(id));
|
|
102
110
|
|
|
103
111
|
try {
|
|
104
112
|
await Promise.all(promises);
|
|
@@ -109,6 +117,7 @@ class BasePluginManager {
|
|
|
109
117
|
}
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
/** @private */
|
|
112
121
|
async stop() {
|
|
113
122
|
for (let instance of this._instances.values()) {
|
|
114
123
|
await instance.stop();
|
|
@@ -122,7 +131,7 @@ class BasePluginManager {
|
|
|
122
131
|
*
|
|
123
132
|
* @private
|
|
124
133
|
*/
|
|
125
|
-
async
|
|
134
|
+
async unsafeGet(id) {
|
|
126
135
|
if (!isString(id)) {
|
|
127
136
|
throw new Error(`[soundworks.PluginManager] Invalid argument, "pluginManager.get(name)" argument should be a string`);
|
|
128
137
|
}
|
|
@@ -145,7 +154,7 @@ class BasePluginManager {
|
|
|
145
154
|
|
|
146
155
|
// recursively get the dependency chain
|
|
147
156
|
const { deps } = this._registeredPlugins.get(id);
|
|
148
|
-
const promises = deps.map(id => this.
|
|
157
|
+
const promises = deps.map(id => this.unsafeGet(id));
|
|
149
158
|
|
|
150
159
|
await Promise.all(promises);
|
|
151
160
|
|