@clockworkdog/cogs-client 2.0.0 → 2.1.1

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.
@@ -6,6 +6,7 @@ type EventTypes = {
6
6
  audioClipState: MediaClipStateMessage;
7
7
  };
8
8
  export default class AudioPlayer {
9
+ private cogsConnection;
9
10
  private eventTarget;
10
11
  private globalVolume;
11
12
  private audioClipPlayers;
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const howler_1 = require("howler");
4
- const urls_1 = require("./helpers/urls");
5
4
  const DEBUG = false;
6
5
  // Check an iOS-only property (See https://developer.mozilla.org/en-US/docs/Web/API/Navigator#non-standard_properties)
7
6
  const IS_IOS = typeof navigator.standalone !== 'undefined';
8
7
  class AudioPlayer {
9
8
  constructor(cogsConnection) {
9
+ this.cogsConnection = cogsConnection;
10
10
  this.eventTarget = new EventTarget();
11
11
  this.globalVolume = 1;
12
12
  this.audioClipPlayers = {};
@@ -407,7 +407,7 @@ class AudioPlayer {
407
407
  }
408
408
  createPlayer(path, config) {
409
409
  const player = new howler_1.Howl({
410
- src: (0, urls_1.assetUrl)(path),
410
+ src: this.cogsConnection.getAssetUrl(path),
411
411
  autoplay: false,
412
412
  loop: false,
413
413
  volume: 1,
@@ -17,6 +17,18 @@ export default class CogsConnection<Manifest extends CogsPluginManifest> {
17
17
  get showPhase(): ShowPhase;
18
18
  private _timerState;
19
19
  get timerState(): TimerState | null;
20
+ /**
21
+ * Track the support for HTTP/2 assets on the client and server side
22
+ * Client side is dictated by the environment we're connecting from (and the media cogs-av-box version)
23
+ * Server side is dictated by the COGS version which added the HTTP/2 assets server itself
24
+ */
25
+ private clientSupportsHttp2Assets;
26
+ private serverSupportsHttp2Assets;
27
+ get supportsHttp2Assets(): boolean;
28
+ /**
29
+ * Return asset URLs using the information about the client and server support for HTTP/2
30
+ */
31
+ getAssetUrl(path: string): string;
20
32
  /**
21
33
  * Cached audio outputs use to look up the device/sink ID when a different device label is requested
22
34
  */
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CogsIncomingEvent = exports.CogsStateChangedEvent = exports.CogsConfigChangedEvent = exports.CogsMessageEvent = exports.CogsConnectionCloseEvent = exports.CogsConnectionOpenEvent = void 0;
7
+ const compare_versions_1 = require("compare-versions");
7
8
  const ShowPhase_1 = __importDefault(require("./types/ShowPhase"));
8
9
  const reconnecting_websocket_1 = __importDefault(require("reconnecting-websocket"));
9
10
  const urls_1 = require("./helpers/urls");
@@ -20,6 +21,15 @@ class CogsConnection {
20
21
  get timerState() {
21
22
  return this._timerState ? { ...this._timerState } : null;
22
23
  }
24
+ get supportsHttp2Assets() {
25
+ return this.clientSupportsHttp2Assets && this.serverSupportsHttp2Assets;
26
+ }
27
+ /**
28
+ * Return asset URLs using the information about the client and server support for HTTP/2
29
+ */
30
+ getAssetUrl(path) {
31
+ return (0, urls_1.assetUrl)(path, this.supportsHttp2Assets);
32
+ }
23
33
  get selectedAudioOutput() {
24
34
  return this._selectedAudioOutput;
25
35
  }
@@ -31,18 +41,29 @@ class CogsConnection {
31
41
  this.currentState = {}; // Received on open connection - TODO: set initial state from manifest?
32
42
  this._showPhase = ShowPhase_1.default.Setup;
33
43
  this._timerState = null;
44
+ /**
45
+ * Track the support for HTTP/2 assets on the client and server side
46
+ * Client side is dictated by the environment we're connecting from (and the media cogs-av-box version)
47
+ * Server side is dictated by the COGS version which added the HTTP/2 assets server itself
48
+ */
49
+ this.clientSupportsHttp2Assets = false;
50
+ this.serverSupportsHttp2Assets = false;
34
51
  /**
35
52
  * Cached audio outputs use to look up the device/sink ID when a different device label is requested
36
53
  */
37
54
  this.audioOutputs = undefined;
38
55
  this._selectedAudioOutput = '';
39
56
  this.currentState = { ...initialClientState };
40
- const { useReconnectingWebsocket, path, pathParams } = websocketParametersFromUrl(document.location.href);
57
+ const { useReconnectingWebsocket, path, pathParams, supportsHttp2Assets } = websocketParametersFromUrl(document.location.href);
41
58
  const socketUrl = `ws://${hostname}:${port}${path}${pathParams ? '?' + pathParams : ''}`;
42
59
  this.websocket = useReconnectingWebsocket ? new reconnecting_websocket_1.default(socketUrl) : new WebSocket(socketUrl);
60
+ this.clientSupportsHttp2Assets = !!supportsHttp2Assets;
43
61
  this.websocket.onopen = () => {
44
62
  this.currentConfig = {}; // Received on open connection
45
63
  this.currentState = {}; // Received on open connection
64
+ // Reset this flag as we might have just connected to an old COGS version which doesn't support HTTP/2
65
+ // The flag will be set when COGS sends a "cogs_environment" message
66
+ this.serverSupportsHttp2Assets = false;
46
67
  this.dispatchEvent(new CogsConnectionOpenEvent());
47
68
  this.setState(this.currentState); // TODO: Remove this because you should set it manually...??
48
69
  };
@@ -77,6 +98,9 @@ class CogsConnection {
77
98
  case 'show_phase':
78
99
  this._showPhase = message.phase;
79
100
  break;
101
+ case 'cogs_environment':
102
+ this.serverSupportsHttp2Assets = message.http2AssetsServer;
103
+ break;
80
104
  }
81
105
  this.dispatchEvent(new CogsMessageEvent(message));
82
106
  }
@@ -168,41 +192,67 @@ class CogsConnection {
168
192
  }
169
193
  exports.default = CogsConnection;
170
194
  function websocketParametersFromUrl(url) {
171
- var _a, _b, _c, _d, _e;
195
+ var _a, _b, _c, _d, _e, _f, _g, _h;
172
196
  const parsedUrl = new URL(url);
173
197
  const pathParams = new URLSearchParams(parsedUrl.searchParams);
174
198
  const localClientId = pathParams.get('local_id');
175
199
  const isSimulator = pathParams.get('simulator') === 'true';
176
200
  const display = (_a = pathParams.get('display')) !== null && _a !== void 0 ? _a : '';
177
201
  const pluginId = parsedUrl.pathname.startsWith('/plugin/') ? decodeURIComponent(parsedUrl.pathname.split('/')[2]) : undefined;
202
+ // Allow explicitly disabling HTTP/2 assets. This is useful in situations where we know the self-signed certificate cannot be
203
+ // supported such as the native mobile app
204
+ const disableHttp2Assets = ((_b = pathParams.get('http2Assets')) !== null && _b !== void 0 ? _b : '') === 'false';
178
205
  if (localClientId) {
179
- const type = (_b = pathParams.get('t')) !== null && _b !== void 0 ? _b : '';
206
+ const type = (_c = pathParams.get('t')) !== null && _c !== void 0 ? _c : '';
180
207
  pathParams.delete('local_id');
181
208
  return {
182
209
  path: `/local/${encodeURIComponent(localClientId)}`,
183
210
  pathParams: new URLSearchParams({ t: type }),
184
211
  useReconnectingWebsocket: true,
212
+ supportsHttp2Assets: !disableHttp2Assets,
185
213
  };
186
214
  }
187
215
  else if (isSimulator) {
188
- const name = (_c = pathParams.get('name')) !== null && _c !== void 0 ? _c : '';
216
+ const supportsHttp2Assets = ((_d = pathParams.get('http2Assets')) !== null && _d !== void 0 ? _d : '') === 'true';
217
+ pathParams.delete('http2Assets');
218
+ const name = (_e = pathParams.get('name')) !== null && _e !== void 0 ? _e : '';
189
219
  pathParams.delete('simulator');
190
220
  pathParams.delete('name');
191
- return { path: `/simulator/${encodeURIComponent(name)}`, pathParams, useReconnectingWebsocket: true };
221
+ return {
222
+ path: `/simulator/${encodeURIComponent(name)}`,
223
+ pathParams,
224
+ useReconnectingWebsocket: true,
225
+ supportsHttp2Assets: !disableHttp2Assets && supportsHttp2Assets,
226
+ };
192
227
  }
193
228
  else if (display) {
194
- const displayIdIndex = (_d = pathParams.get('displayIdIndex')) !== null && _d !== void 0 ? _d : '';
229
+ const displayIdIndex = (_f = pathParams.get('displayIdIndex')) !== null && _f !== void 0 ? _f : '';
195
230
  pathParams.delete('display');
196
231
  pathParams.delete('displayIdIndex');
197
- return { path: `/display/${encodeURIComponent(display)}/${encodeURIComponent(displayIdIndex)}` };
232
+ return {
233
+ path: `/display/${encodeURIComponent(display)}/${encodeURIComponent(displayIdIndex)}`,
234
+ supportsHttp2Assets: !disableHttp2Assets,
235
+ };
198
236
  }
199
237
  else if (pluginId) {
200
- return { path: `/plugin/${encodeURIComponent(pluginId)}`, useReconnectingWebsocket: true };
238
+ return {
239
+ path: `/plugin/${encodeURIComponent(pluginId)}`,
240
+ useReconnectingWebsocket: true,
241
+ supportsHttp2Assets: !disableHttp2Assets,
242
+ };
201
243
  }
202
244
  else {
203
- const serial = (_e = pathParams.get('serial')) !== null && _e !== void 0 ? _e : '';
245
+ const serial = (_g = pathParams.get('serial')) !== null && _g !== void 0 ? _g : '';
204
246
  pathParams.delete('serial');
205
- return { path: `/client/${encodeURIComponent(serial)}`, pathParams };
247
+ // Check if cogs-box-av is a version which added support for ignoring HTTP/2 self-signed certificates
248
+ const firmwareVersion = ((_h = pathParams.get('f')) !== null && _h !== void 0 ? _h : '').replace(/^v/, '');
249
+ const isCogsBoxAvDevBuild = firmwareVersion === '0.0.0'; // We assume dev firmware builds have HTTP/2 assets support - Added in 2024-03
250
+ const supportsHttp2Assets = isCogsBoxAvDevBuild || ((0, compare_versions_1.validate)(firmwareVersion) && (0, compare_versions_1.satisfies)(firmwareVersion, '>=4.9.0'));
251
+ return {
252
+ path: `/client/${encodeURIComponent(serial)}`,
253
+ pathParams,
254
+ supportsHttp2Assets: !disableHttp2Assets && supportsHttp2Assets,
255
+ };
206
256
  }
207
257
  }
208
258
  class CogsConnectionOpenEvent extends Event {
@@ -7,6 +7,7 @@ type EventTypes = {
7
7
  videoClipState: MediaClipStateMessage;
8
8
  };
9
9
  export default class VideoPlayer {
10
+ private cogsConnection;
10
11
  private eventTarget;
11
12
  private globalVolume;
12
13
  private videoClipPlayers;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const urls_1 = require("./helpers/urls");
4
3
  const VideoState_1 = require("./types/VideoState");
5
4
  const DEFAULT_PARENT_ELEMENT = document.body;
6
5
  class VideoPlayer {
7
6
  constructor(cogsConnection, parentElement = DEFAULT_PARENT_ELEMENT) {
7
+ this.cogsConnection = cogsConnection;
8
8
  this.eventTarget = new EventTarget();
9
9
  this.globalVolume = 1;
10
10
  this.videoClipPlayers = {};
@@ -284,7 +284,7 @@ class VideoPlayer {
284
284
  createVideoElement(path, config, { volume }) {
285
285
  const videoElement = document.createElement('video');
286
286
  videoElement.playsInline = true; // Required for iOS
287
- videoElement.src = (0, urls_1.assetUrl)(path);
287
+ videoElement.src = this.cogsConnection.getAssetUrl(path);
288
288
  videoElement.autoplay = false;
289
289
  videoElement.loop = false;
290
290
  setVideoElementVolume(videoElement, volume * this.globalVolume);