@ircam/comote-helpers 0.3.0 → 0.3.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.
@@ -22,7 +22,7 @@ jobs:
22
22
  uses: actions/checkout@v2
23
23
  - name: Build project # This would actually build your project, using zip for an example artifact
24
24
  run: |
25
- (cd max && zip -r - comote) > comote-for-max.zip
25
+ (cd max && zip -r - CoMo.te) > CoMo.te.zip
26
26
  - name: Create Release
27
27
  id: create_release
28
28
  uses: actions/create-release@v1
@@ -40,6 +40,6 @@ jobs:
40
40
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
41
  with:
42
42
  upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
43
- asset_path: ./comote-for-max.zip
44
- asset_name: comote-for-max.zip
43
+ asset_path: ./CoMo.te.zip
44
+ asset_name: CoMo.te.zip
45
45
  asset_content_type: application/zip
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # `@ircam/comote-helpers`
1
+ # `CoMo.te helpers`
2
2
 
3
3
  > Javascript and Max/MSP utilities to create applications compatible with iPhone
4
- > and Android `CoMo.te` application.
4
+ > and Android `CoMo.te` application, cf. [https://ismm-apps.ircam.fr/comote](https://ismm-apps.ircam.fr/comote).
5
5
 
6
6
 
7
7
  The CoMo.te application (iOS and Android) allows for streaming motion data (accelerometer, gyroscope) from the smartphone to desktop applications using either the OSC or Websockets protocols. The network's setup is facilitated by the use of a QR code generated by the targeted remote application receiving the motion sensor data.
@@ -12,7 +12,9 @@ Among the CoMo applications that make use of CoMo.te are CoMo-Vox to learn and t
12
12
 
13
13
  CoMo.te and the CoMo applications are software designed and developed by IRCAM in the Sound-Music-Movement-Interaction team (UMR STMS).
14
14
 
15
- This repository provides utilities to help to generate the QRCode in the target application both for Max/MSP and Node.js
15
+ This repository provides utilities to help to generate the QRCode in the target application both for Max/MSP and Node.js.
16
+
17
+
16
18
 
17
19
  ## Table of Contents
18
20
 
@@ -28,7 +30,7 @@ This repository provides utilities to help to generate the QRCode in the target
28
30
 
29
31
  ## Max/MSP
30
32
 
31
- Download the Max abstraction (SoundworksAPI.zip) from the releases page: https://github.com/ircam-ismm/comote-helpers/releases
33
+ Download the Max abstraction (i.e. CoMo.te.zip) from the lastest release in the releases page: https://github.com/ircam-ismm/comote-helpers/releases
32
34
  Unzip the package and copy the resulting directory in `~/Documents/Max 8/Packages`
33
35
 
34
36
  For now, the package only provide abstraction `[comote.connect]` that allows you to generate a QRCode that can be
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getNetworkInterfacesInfos = getNetworkInterfacesInfos;
7
+ var _systeminformation = _interopRequireDefault(require("systeminformation"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ /**
10
+ * @typedef {Object} NetworkInterfaces
11
+ * @property {Array.<NetworkInterface>} Interfaces
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} NetworkInterface
16
+ *
17
+ * @property {string} iface: - identifier eg. 'en0'
18
+ * @property {string} ifaceName - name eg. 'en0'
19
+ * @property {boolean} default - true if default interface (for sending data)
20
+ * @property {string} ip4 - address eg. '192.168.0.1'
21
+ * @property {string} ip4subnet - eg. '255.255.252.0'
22
+ * @property {string} ip6 eg. 'fe80::456:7890:abcd:ef01'
23
+ * @property {string} ip6subnet eg. 'ffff:ffff:ffff:ffff::'
24
+ * @property {string} type eg. 'wireless' or 'wired'
25
+ *
26
+ * @see https://www.npmjs.com/package/systeminformation
27
+ */
28
+
29
+ /**
30
+ * @callback interfacaFilterCallback
31
+ * @param {Object} interface network interface to test
32
+ * @return {boolean} true to keep this interface
33
+ */
34
+
35
+ /**
36
+ * Retrieve information of network interfaces
37
+ *
38
+ * @async
39
+ * @param {Object} options
40
+ * @param {interfacaFilterCallback} options.interfaceFilter callback for filter to test interface
41
+ * @return {NetworkInterfaces|null} null if no interface found
42
+ */
43
+ async function getNetworkInterfacesInfos({
44
+ interfaceFilter = i => {
45
+ // only IPv4
46
+ // avoid localhost
47
+ return i.ip4 && i.ip4 !== '127.0.0.1' && i.ip4 !== 'localhost';
48
+ }
49
+ } = {}) {
50
+ const interfaces = await _systeminformation.default.networkInterfaces();
51
+ if (!interfaces) {
52
+ return null;
53
+ }
54
+ if (typeof interfaceFilter !== 'function') {
55
+ return interfaces;
56
+ }
57
+ return interfaces.filter(interfaceFilter);
58
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ircam/comote-helpers",
3
- "version": "0.3.0",
3
+ "version": "0.3.3",
4
4
  "description": "Server component & utilities for the CoMo.te application",
5
5
  "authors": [
6
6
  "Benjamin.Matuszewski@ircam.fr",
package/qrcode.js CHANGED
@@ -6,83 +6,70 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.dataURL = dataURL;
7
7
  exports.rawLink = rawLink;
8
8
  exports.terminal = terminal;
9
-
10
9
  var _qrcode = _interopRequireDefault(require("qrcode"));
11
-
12
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
11
  function formatConfigToLink(config) {
15
12
  let link = `comote://settings?`;
16
13
  const query = [];
17
-
18
14
  if ('id' in config) {
19
15
  query.push(`id=${config.id}`);
20
16
  }
21
-
22
17
  if (Number.isFinite(config.interval) && config.interval > 0) {
23
18
  query.push(`interval=${config.interval}`);
24
19
  }
25
-
26
20
  if (config.ws) {
27
21
  const {
28
22
  protocol,
29
23
  hostname,
30
24
  port,
31
25
  pathname
32
- } = config.ws; // build valid url
33
- // only hostname is required
26
+ } = config.ws;
34
27
 
28
+ // build valid url
29
+ // only hostname is required
35
30
  if (!hostname) {
36
31
  throw new Error(`Invalid WebSocket config: ${config.ws}`);
37
32
  }
38
-
39
33
  let url = `ws-url=`;
40
34
  url += protocol == 'ws' || protocol == 'wss' ? `${protocol}://` : `ws://`;
41
35
  url += hostname;
42
-
43
36
  if (port) {
44
37
  url += `:${port}`;
45
38
  }
46
-
47
39
  if (pathname) {
48
40
  url += pathname;
49
41
  }
42
+ query.push(url);
50
43
 
51
- query.push(url); // autostart
52
-
44
+ // autostart
53
45
  if (config.ws.autostart === true) {
54
46
  query.push(`ws-enable=1`);
55
47
  }
56
48
  }
57
-
58
49
  if (config.osc) {
59
50
  const {
60
51
  hostname,
61
52
  port
62
53
  } = config.osc;
63
-
64
54
  if (!hostname || !Number.isInteger(port)) {
65
55
  throw new Error(`Invalid WebSocket config: ${config.osc}`);
66
56
  }
67
-
68
57
  query.push(`osc-url=udp://${hostname}:${port}`);
69
-
70
58
  if (config.osc.autostart === true) {
71
59
  query.push(`osc-enable=1`);
72
60
  }
73
61
  }
74
-
75
62
  link += query.join('&');
76
63
  return link;
77
64
  }
65
+
78
66
  /**
79
67
  * Return the link to be encoded in the QRCode accroding to given `CoMoteConfig`
80
68
  */
81
-
82
-
83
69
  function rawLink(config) {
84
70
  return formatConfigToLink(config);
85
71
  }
72
+
86
73
  /**
87
74
  * Create a qrcode to be logged in terminal according to given `CoMoteConfig``
88
75
  *
@@ -90,15 +77,13 @@ function rawLink(config) {
90
77
  * @example
91
78
  * console(await CoMoteQRCode.terminal(config));
92
79
  */
93
-
94
-
95
80
  async function terminal(config) {
96
81
  const link = formatConfigToLink(config);
97
82
  return await _qrcode.default.toString(link, {
98
- type: 'terminal',
99
- small: true
83
+ type: 'terminal'
100
84
  });
101
85
  }
86
+
102
87
  /**
103
88
  * Create a qrcode to be used as in Image source according to given `CoMoteConfig``
104
89
  *
@@ -108,8 +93,6 @@ async function terminal(config) {
108
93
  *
109
94
  * <img src="${qrCode}" />
110
95
  */
111
-
112
-
113
96
  async function dataURL(config) {
114
97
  const link = formatConfigToLink(config);
115
98
  return await await _qrcode.default.toDataURL(link);
package/server.js CHANGED
@@ -4,19 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Server = void 0;
7
-
8
7
  var _ws = _interopRequireDefault(require("ws"));
9
-
10
8
  var _utf8Validate = _interopRequireDefault(require("utf-8-validate"));
11
-
12
9
  var _nodeOsc = require("node-osc");
13
-
14
10
  var _cloneDeep = _interopRequireDefault(require("clone-deep"));
15
-
16
11
  var _assignDeep = _interopRequireDefault(require("assign-deep"));
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  /**
21
14
  * @typedef {Object} CoMoteConfig
22
15
  * @property {String} id - id of the client CoMo.te
@@ -52,103 +45,89 @@ class Server {
52
45
  verbose: false
53
46
  }, config));
54
47
  this._verbose = !!options.verbose;
55
-
56
48
  if (this._verbose) {
57
49
  console.log('+ CoMo.te config:');
58
50
  console.log(this.config, '\n');
59
51
  }
60
-
61
52
  this._websocketServer = null;
62
53
  this._oscServer = null;
63
54
  this._wsListeners = new Set();
64
55
  this._oscListeners = new Set();
65
56
  }
66
-
67
57
  async start() {
68
58
  let wsPromise = true;
69
59
  let oscPromise = true;
70
-
71
60
  if (this.config.ws !== null) {
72
61
  const {
73
62
  hostname,
74
63
  port
75
64
  } = this.config.ws;
76
-
77
65
  if (!Number.isInteger(port)) {
78
66
  throw new Error(`Invalid port "${port}" for WebSocket server`);
79
67
  }
80
-
81
68
  if (this._verbose) {
82
69
  console.log(`> CoMo.te: Launching WebSocket server on port: ${port}`);
83
70
  }
84
-
85
71
  this._websocketServer = new _ws.default.Server({
86
72
  port
87
73
  });
88
74
  const sockets = new Map();
89
-
90
75
  this._websocketServer.on('connection', (socket, request) => {
91
76
  // const ip = request.socket.remoteAddress;
92
77
  socket.on('message', (data, isBinary) => {
93
- if (isBinary) {// @todo
78
+ if (isBinary) {
79
+ // @todo
94
80
  } else {
95
81
  if ((0, _utf8Validate.default)(data)) {
96
82
  // do we really need this check?
97
83
  data = JSON.parse(data);
98
-
99
84
  if (this._verbose) {
100
85
  console.log(`> CoMo.te: new WebSocket message`, data);
101
- } // console.log(data);
102
- // console.log(this._wsListeners.size);
103
-
86
+ }
104
87
 
88
+ // console.log(data);
89
+ // console.log(this._wsListeners.size);
105
90
  this._wsListeners.forEach(listener => listener(data));
106
91
  }
107
92
  }
108
- }); // When a socket closes, or disconnects, remove it from the array.
93
+ });
109
94
 
95
+ // When a socket closes, or disconnects, remove it from the array.
110
96
  socket.on('close', (code, data) => {
111
97
  if (this._verbose) {
112
98
  console.log('> CoMo.te: closed socket connection');
113
99
  }
114
100
  });
115
101
  });
116
-
117
102
  wsPromise = new Promise((resolve, reject) => {
118
103
  this._websocketServer.on('listening', () => {
119
104
  if (this._verbose) {
120
105
  console.log(`> CoMo.te: WebSocket server listening`);
121
106
  }
122
-
123
107
  resolve();
124
108
  });
125
-
126
109
  this._websocketServer.on('error', err => {
127
110
  console.log(`> CoMo.te: WebSocket server error`, err);
128
111
  reject(err);
129
112
  });
130
113
  });
131
114
  }
132
-
133
115
  if (this.config.osc !== null) {
134
116
  const {
135
117
  hostname,
136
118
  port
137
119
  } = this.config.osc;
138
-
139
120
  if (!Number.isInteger(port)) {
140
121
  throw new Error(`Invalid port "${port}" for OSC server`);
141
- } // fallback to broadcast
142
-
122
+ }
143
123
 
124
+ // fallback to broadcast
144
125
  if (!hostname) {
145
126
  hostname = '0.0.0.0';
146
127
  }
147
-
148
128
  if (this._verbose) {
149
129
  console.log(`> CoMo.te: Launching OSC server udp://${hostname}:${port}`);
150
130
  }
151
-
152
131
  oscPromise = new Promise((resolve, reject) => {
153
132
  this._oscServer = new _nodeOsc.Server(this.config.osc.port, hostname, err => {
154
133
  if (err) {
@@ -156,75 +135,59 @@ class Server {
156
135
  reject();
157
136
  return;
158
137
  }
159
-
160
138
  if (this._verbose) {
161
139
  console.log(`> CoMo.te: OSC server listening`);
162
140
  }
163
-
164
141
  resolve();
165
142
  });
166
-
167
143
  this._oscServer.on('message', data => {
168
144
  let address = data.shift();
169
-
170
145
  if (this._verbose) {
171
146
  console.log(`> CoMo.te: new OSC message "${address}":`, data);
172
147
  }
173
-
174
148
  this._oscListeners.forEach(callback => callback(address, data));
175
149
  });
176
150
  });
177
151
  }
178
-
179
152
  return Promise.all([wsPromise, oscPromise]);
180
153
  }
181
-
182
154
  async stop() {
183
155
  if (this._websocketServer) {
184
156
  this._websocketServer.close();
185
157
  }
186
-
187
158
  if (this._oscServer) {
188
159
  this._oscServer.close();
189
160
  }
190
161
  }
162
+
191
163
  /**
192
164
  * Add a listener for incomming WebSocket message
193
165
  */
194
-
195
-
196
166
  addWsListener(callback) {
197
167
  this._wsListeners.add(callback);
198
-
199
168
  return () => this._wsListeners.delete(callback);
200
169
  }
170
+
201
171
  /**
202
172
  * Remove WebSocket listener
203
173
  */
204
-
205
-
206
174
  removeWsListener(callback) {
207
175
  this._wsListeners.delete(callback);
208
176
  }
177
+
209
178
  /**
210
179
  * Add a listener for incomming OSC message
211
180
  */
212
-
213
-
214
181
  addOscListener(callback) {
215
182
  this._oscListeners.add(callback);
216
-
217
183
  return () => this._oscListeners.delete(callback);
218
184
  }
185
+
219
186
  /**
220
187
  * Remove OSC listener
221
188
  */
222
-
223
-
224
189
  removeOscListener(callback) {
225
190
  this._oscListeners.delete(callback);
226
191
  }
227
-
228
192
  }
229
-
230
193
  exports.Server = Server;
package/wifi-infos.js CHANGED
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getWifiInfos = getWifiInfos;
7
-
8
7
  var _systeminformation = _interopRequireDefault(require("systeminformation"));
9
-
10
8
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
9
  /**
13
10
  * @typedef {Object} WifiInfos
14
11
  * @property {number} ssid - SSID of the WiFi connection
@@ -26,12 +23,11 @@ async function getWifiInfos() {
26
23
  // find first wifi connection
27
24
  const wifiConnections = await _systeminformation.default.wifiConnections();
28
25
  const conn = wifiConnections[0];
29
-
30
26
  if (!conn) {
31
27
  return null;
32
- } // find related interface
33
-
28
+ }
34
29
 
30
+ // find related interface
35
31
  const interfaces = await _systeminformation.default.networkInterfaces();
36
32
  const int = interfaces.find(int => int.iface === conn.iface);
37
33
  return {