videomail-client 8.3.0 → 8.3.2

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.
Files changed (69) hide show
  1. package/package.json +1 -2
  2. package/prototype/js/videomail-client.js +12 -15
  3. package/prototype/js/videomail-client.min.js +1 -1
  4. package/prototype/js/videomail-client.min.js.map +1 -1
  5. package/videomail-client.code-workspace +25 -0
  6. package/.eslintignore +0 -1
  7. package/.eslintrc.js +0 -46
  8. package/.nvmrc +0 -1
  9. package/.prettierignore +0 -1
  10. package/.travis.yml +0 -14
  11. package/audit-ci.json +0 -12
  12. package/babel.config.js +0 -38
  13. package/browserstack.png +0 -0
  14. package/env/dev/cert.pem +0 -26
  15. package/env/dev/key.pem +0 -28
  16. package/env/dev/release.sh +0 -96
  17. package/gulpfile.js +0 -241
  18. package/prettier.config.js +0 -8
  19. package/src/js/client.js +0 -210
  20. package/src/js/constants.js +0 -11
  21. package/src/js/events.js +0 -46
  22. package/src/js/index.js +0 -15
  23. package/src/js/options.js +0 -180
  24. package/src/js/resource.js +0 -206
  25. package/src/js/util/audioRecorder.js +0 -152
  26. package/src/js/util/browser.js +0 -319
  27. package/src/js/util/collectLogger.js +0 -72
  28. package/src/js/util/eventEmitter.js +0 -72
  29. package/src/js/util/humanize.js +0 -16
  30. package/src/js/util/mediaEvents.js +0 -148
  31. package/src/js/util/pretty.js +0 -70
  32. package/src/js/util/standardize.js +0 -71
  33. package/src/js/util/videomailError.js +0 -431
  34. package/src/js/wrappers/buttons.js +0 -670
  35. package/src/js/wrappers/container.js +0 -797
  36. package/src/js/wrappers/dimension.js +0 -149
  37. package/src/js/wrappers/form.js +0 -319
  38. package/src/js/wrappers/optionsWrapper.js +0 -81
  39. package/src/js/wrappers/visuals/inside/recorder/countdown.js +0 -83
  40. package/src/js/wrappers/visuals/inside/recorder/facingMode.js +0 -53
  41. package/src/js/wrappers/visuals/inside/recorder/pausedNote.js +0 -59
  42. package/src/js/wrappers/visuals/inside/recorder/recordNote.js +0 -42
  43. package/src/js/wrappers/visuals/inside/recorder/recordTimer.js +0 -149
  44. package/src/js/wrappers/visuals/inside/recorderInsides.js +0 -144
  45. package/src/js/wrappers/visuals/notifier.js +0 -341
  46. package/src/js/wrappers/visuals/recorder.js +0 -1492
  47. package/src/js/wrappers/visuals/replay.js +0 -355
  48. package/src/js/wrappers/visuals/userMedia.js +0 -541
  49. package/src/js/wrappers/visuals.js +0 -410
  50. package/src/styles/css/main.min.css.js +0 -1
  51. package/src/styles/styl/keyframes/blink.styl +0 -16
  52. package/src/styles/styl/main.styl +0 -126
  53. package/test/core/client.test.js +0 -64
  54. package/test/core/resource.test.js +0 -12
  55. package/test/util/audioRecorder.test.js +0 -13
  56. package/test/util/browser.test.js +0 -157
  57. package/test/util/collectLogger.test.js +0 -13
  58. package/test/util/eventEmitter.test.js +0 -13
  59. package/test/util/humanize.test.js +0 -21
  60. package/test/util/pretty.test.js +0 -116
  61. package/test/util/videomailError.test.js +0 -323
  62. package/test/wrappers/buttons.test.js +0 -15
  63. package/test/wrappers/container.test.js +0 -18
  64. package/test/wrappers/form.test.js +0 -13
  65. package/test/wrappers/notifier.test.js +0 -13
  66. package/test/wrappers/recorder.test.js +0 -18
  67. package/test/wrappers/replay.test.js +0 -15
  68. package/test/wrappers/userMedia.test.js +0 -13
  69. package/test/wrappers/visuals.test.js +0 -18
@@ -1,541 +0,0 @@
1
- import AudioRecorder from "./../../util/audioRecorder";
2
- import Browser from "./../../util/browser";
3
- import EventEmitter from "./../../util/eventEmitter";
4
- import Events from "./../../events";
5
- import MEDIA_EVENTS from "./../../util/mediaEvents";
6
- import VideomailError from "./../../util/videomailError";
7
- import h from "hyperscript";
8
- import pretty from "./../../util/pretty";
9
- import stringify from "safe-json-stringify";
10
-
11
- const EVENT_ASCII = "|—O—|";
12
-
13
- export default function (recorder, options) {
14
- EventEmitter.call(this, options, "UserMedia");
15
-
16
- const rawVisualUserMedia = recorder && recorder.getRawVisualUserMedia();
17
- const browser = new Browser(options);
18
- const self = this;
19
-
20
- let paused = false;
21
- let record = false;
22
-
23
- let audioRecorder;
24
- let currentVisualStream;
25
-
26
- function attachMediaStream(stream) {
27
- currentVisualStream = stream;
28
-
29
- if (typeof rawVisualUserMedia.srcObject !== "undefined") {
30
- rawVisualUserMedia.srcObject = stream;
31
- } else if (typeof rawVisualUserMedia.src !== "undefined") {
32
- const URL = window.URL || window.webkitURL;
33
- rawVisualUserMedia.src = URL.createObjectURL(stream) || stream;
34
- } else {
35
- throw VideomailError.create(
36
- "Error attaching stream to element.",
37
- "Contact the developer about this",
38
- options,
39
- );
40
- }
41
- }
42
-
43
- function setVisualStream(localMediaStream) {
44
- if (localMediaStream) {
45
- attachMediaStream(localMediaStream);
46
- } else {
47
- rawVisualUserMedia.removeAttribute("srcObject");
48
- rawVisualUserMedia.removeAttribute("src");
49
-
50
- currentVisualStream = null;
51
- }
52
- }
53
-
54
- function getVisualStream() {
55
- if (rawVisualUserMedia.mozSrcObject) {
56
- return rawVisualUserMedia.mozSrcObject;
57
- } else if (rawVisualUserMedia.srcObject) {
58
- return rawVisualUserMedia.srcObject;
59
- }
60
-
61
- return currentVisualStream;
62
- }
63
-
64
- function hasEnded() {
65
- if (rawVisualUserMedia.ended) {
66
- return rawVisualUserMedia.ended;
67
- }
68
-
69
- const visualStream = getVisualStream();
70
- return visualStream && visualStream.ended;
71
- }
72
-
73
- function hasInvalidDimensions() {
74
- if (
75
- (rawVisualUserMedia.videoWidth && rawVisualUserMedia.videoWidth < 3) ||
76
- (rawVisualUserMedia.height && rawVisualUserMedia.height < 3)
77
- ) {
78
- return true;
79
- }
80
- }
81
-
82
- function getTracks(localMediaStream) {
83
- let tracks;
84
-
85
- if (localMediaStream && localMediaStream.getTracks) {
86
- tracks = localMediaStream.getTracks();
87
- }
88
-
89
- return tracks;
90
- }
91
-
92
- function getVideoTracks(localMediaStream) {
93
- let videoTracks;
94
-
95
- if (localMediaStream && localMediaStream.getVideoTracks) {
96
- videoTracks = localMediaStream.getVideoTracks();
97
- }
98
-
99
- return videoTracks;
100
- }
101
-
102
- function getFirstVideoTrack(localMediaStream) {
103
- const videoTracks = getVideoTracks(localMediaStream);
104
- let videoTrack;
105
-
106
- if (videoTracks && videoTracks[0]) {
107
- videoTrack = videoTracks[0];
108
- }
109
-
110
- return videoTrack;
111
- }
112
-
113
- function logEvent(event, params) {
114
- options.debug("UserMedia: ...", EVENT_ASCII, "event", event, stringify(params));
115
- }
116
-
117
- function isPromise(anything) {
118
- return anything && typeof Promise !== "undefined" && anything instanceof Promise;
119
- }
120
-
121
- function outputEvent(e) {
122
- logEvent(e.type, { readyState: rawVisualUserMedia.readyState });
123
-
124
- // remove myself
125
- rawVisualUserMedia.removeEventListener &&
126
- rawVisualUserMedia.removeEventListener(e.type, outputEvent);
127
- }
128
-
129
- this.unloadRemainingEventListeners = function () {
130
- options.debug("UserMedia: unloadRemainingEventListeners()");
131
-
132
- MEDIA_EVENTS.forEach(function (eventName) {
133
- rawVisualUserMedia.removeEventListener(eventName, outputEvent);
134
- });
135
- };
136
-
137
- this.init = function (
138
- localMediaStream,
139
- videoCallback,
140
- audioCallback,
141
- endedEarlyCallback,
142
- params = {},
143
- ) {
144
- this.stop(localMediaStream, {
145
- aboutToInitialize: true,
146
- switchingFacingMode: params.switchingFacingMode,
147
- });
148
-
149
- let onPlayReached = false;
150
- let onLoadedMetaDataReached = false;
151
- let playingPromiseReached = false;
152
-
153
- if (options && options.isAudioEnabled()) {
154
- audioRecorder ||= new AudioRecorder(this, options);
155
- }
156
-
157
- function audioRecord() {
158
- self.removeListener(Events.SENDING_FIRST_FRAME, audioRecord);
159
- audioRecorder && audioRecorder.record(audioCallback);
160
- }
161
-
162
- function unloadAllEventListeners() {
163
- options.debug("UserMedia: unloadAllEventListeners()");
164
-
165
- self.removeListener(Events.SENDING_FIRST_FRAME, audioRecord);
166
-
167
- rawVisualUserMedia.removeEventListener &&
168
- rawVisualUserMedia.removeEventListener("play", onPlay);
169
-
170
- rawVisualUserMedia.removeEventListener &&
171
- rawVisualUserMedia.removeEventListener("loadedmetadata", onLoadedMetaData);
172
-
173
- self.unloadRemainingEventListeners();
174
- }
175
-
176
- function play() {
177
- // Resets the media element and restarts the media resource. Any pending events are discarded.
178
- try {
179
- rawVisualUserMedia.load();
180
-
181
- /*
182
- * fixes https://github.com/binarykitchen/videomail.io/issues/401
183
- * see https://github.com/MicrosoftEdge/Demos/blob/master/photocapture/scripts/demo.js#L27
184
- */
185
- if (rawVisualUserMedia.paused) {
186
- options.debug(
187
- "UserMedia: play()",
188
- `media.readyState=${rawVisualUserMedia.readyState}`,
189
- `media.paused=${rawVisualUserMedia.paused}`,
190
- `media.ended=${rawVisualUserMedia.ended}`,
191
- `media.played=${pretty(rawVisualUserMedia.played)}`,
192
- );
193
-
194
- let p;
195
-
196
- try {
197
- p = rawVisualUserMedia.play();
198
- } catch (exc) {
199
- /*
200
- * this in the hope to catch InvalidStateError, see
201
- * https://github.com/binarykitchen/videomail-client/issues/149
202
- */
203
- options.logger.warn("Caught raw usermedia play exception:", exc);
204
- }
205
-
206
- /*
207
- * using the promise here just experimental for now
208
- * and this to catch any weird errors early if possible
209
- */
210
- if (isPromise(p)) {
211
- p.then(function () {
212
- if (!playingPromiseReached) {
213
- options.debug("UserMedia: play promise successful. Playing now.");
214
- playingPromiseReached = true;
215
- }
216
- }).catch(function (reason) {
217
- /*
218
- * promise can be interrupted, i.E. when switching tabs
219
- * and promise can get resumed when switching back to tab, hence
220
- * do not treat this like an error
221
- */
222
- options.logger.warn(
223
- "Caught pending usermedia promise exception: %s",
224
- reason.toString(),
225
- );
226
- });
227
- }
228
- }
229
- } catch (exc) {
230
- unloadAllEventListeners();
231
- endedEarlyCallback(exc);
232
- }
233
- }
234
-
235
- function fireCallbacks() {
236
- const { readyState } = rawVisualUserMedia;
237
-
238
- // ready state, see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
239
- options.debug(
240
- `UserMedia: fireCallbacks(` +
241
- `readyState=${readyState}, ` +
242
- `onPlayReached=${onPlayReached}, ` +
243
- `onLoadedMetaDataReached=${onLoadedMetaDataReached})`,
244
- );
245
-
246
- if (onPlayReached && onLoadedMetaDataReached) {
247
- videoCallback();
248
-
249
- if (audioRecorder && audioCallback) {
250
- try {
251
- audioRecorder.init(localMediaStream);
252
- self.on(Events.SENDING_FIRST_FRAME, audioRecord);
253
- } catch (exc) {
254
- unloadAllEventListeners();
255
- endedEarlyCallback(exc);
256
- }
257
- }
258
- }
259
- }
260
-
261
- function onPlay() {
262
- try {
263
- logEvent("play", {
264
- readyState: rawVisualUserMedia.readyState,
265
- audio: options.isAudioEnabled(),
266
- width: rawVisualUserMedia.width,
267
- height: rawVisualUserMedia.height,
268
- videoWidth: rawVisualUserMedia.videoWidth,
269
- videoHeight: rawVisualUserMedia.videoHeight,
270
- });
271
-
272
- rawVisualUserMedia.removeEventListener &&
273
- rawVisualUserMedia.removeEventListener("play", onPlay);
274
-
275
- if (hasEnded() || hasInvalidDimensions()) {
276
- endedEarlyCallback(
277
- VideomailError.create(
278
- "Already busy",
279
- "Probably another browser window is using your webcam?",
280
- options,
281
- ),
282
- );
283
- } else {
284
- onPlayReached = true;
285
- fireCallbacks();
286
- }
287
- } catch (exc) {
288
- unloadAllEventListeners();
289
- endedEarlyCallback(exc);
290
- }
291
- }
292
-
293
- // player modifications to perform that must wait until `loadedmetadata` has been triggered
294
- function onLoadedMetaData() {
295
- logEvent("loadedmetadata", {
296
- readyState: rawVisualUserMedia.readyState,
297
- paused: rawVisualUserMedia.paused,
298
- width: rawVisualUserMedia.width,
299
- height: rawVisualUserMedia.height,
300
- videoWidth: rawVisualUserMedia.videoWidth,
301
- videoHeight: rawVisualUserMedia.videoHeight,
302
- });
303
-
304
- rawVisualUserMedia.removeEventListener &&
305
- rawVisualUserMedia.removeEventListener("loadedmetadata", onLoadedMetaData);
306
-
307
- if (!hasEnded() && !hasInvalidDimensions()) {
308
- self.emit(Events.LOADED_META_DATA);
309
-
310
- /*
311
- * for android devices, we cannot call play() unless meta data has been loaded!
312
- * todo consider removing that if it's not the case anymore (for better performance)
313
- */
314
- if (browser.isAndroid()) {
315
- play();
316
- }
317
-
318
- onLoadedMetaDataReached = true;
319
- fireCallbacks();
320
- }
321
- }
322
-
323
- try {
324
- const videoTrack = getFirstVideoTrack(localMediaStream);
325
-
326
- if (!videoTrack) {
327
- options.debug("UserMedia: detected (but no video tracks exist");
328
- } else if (!videoTrack.enabled) {
329
- throw VideomailError.create(
330
- "Webcam is disabled",
331
- "The video track seems to be disabled. Enable it in your system.",
332
- options,
333
- );
334
- } else {
335
- let description;
336
-
337
- if (videoTrack.label && videoTrack.label.length > 0) {
338
- description = videoTrack.label;
339
- }
340
-
341
- description += ` with enabled=${videoTrack.enabled}`;
342
- description += `, muted=${videoTrack.muted}`;
343
- description += `, remote=${videoTrack.remote}`;
344
- description += `, readyState=${videoTrack.readyState}`;
345
- description += `, error=${videoTrack.error}`;
346
-
347
- options.debug(`UserMedia: ${videoTrack.kind} detected.`, description || "");
348
- }
349
-
350
- // very useful i think, so leave this and just use options.debug()
351
- const heavyDebugging = true;
352
-
353
- if (heavyDebugging) {
354
- MEDIA_EVENTS.forEach(function (eventName) {
355
- rawVisualUserMedia.addEventListener(eventName, outputEvent, false);
356
- });
357
- }
358
-
359
- rawVisualUserMedia.addEventListener("loadedmetadata", onLoadedMetaData);
360
- rawVisualUserMedia.addEventListener("play", onPlay);
361
-
362
- /*
363
- * experimental, not sure if this is ever needed/called? since 2 apr 2017
364
- * An error occurs while fetching the media data.
365
- * Error can be an object with the code MEDIA_ERR_NETWORK or higher.
366
- * networkState equals either NETWORK_EMPTY or NETWORK_IDLE, depending on when the download was aborted.
367
- */
368
- rawVisualUserMedia.addEventListener("error", function (err) {
369
- options.logger.warn("Caught video element error event: %s", pretty(err));
370
- });
371
-
372
- setVisualStream(localMediaStream);
373
-
374
- play();
375
- } catch (exc) {
376
- self.emit(Events.ERROR, exc);
377
- }
378
- };
379
-
380
- this.isReady = function () {
381
- return Boolean(rawVisualUserMedia.src);
382
- };
383
-
384
- this.stop = function (visualStream, params = {}) {
385
- try {
386
- // do not stop "too much" when going to initialize anyway
387
- const { aboutToInitialize } = params;
388
- const { switchingFacingMode } = params;
389
-
390
- if (!aboutToInitialize) {
391
- if (!visualStream) {
392
- visualStream = getVisualStream();
393
- }
394
-
395
- const tracks = getTracks(visualStream);
396
- let newStopApiFound = false;
397
-
398
- if (tracks) {
399
- tracks.forEach(function (track) {
400
- if (track.stop) {
401
- newStopApiFound = true;
402
- track.stop();
403
- }
404
- });
405
- }
406
-
407
- // will probably become obsolete in one year (after june 2017)
408
- !newStopApiFound && visualStream && visualStream.stop && visualStream.stop();
409
-
410
- setVisualStream(null);
411
-
412
- audioRecorder && audioRecorder.stop();
413
-
414
- audioRecorder = null;
415
- }
416
-
417
- /*
418
- * don't have to reset these states when just switching camera
419
- * while still recording or pausing
420
- */
421
- if (!switchingFacingMode) {
422
- paused = record = false;
423
- }
424
- } catch (exc) {
425
- self.emit(Events.ERROR, exc);
426
- }
427
- };
428
-
429
- this.createCanvas = function () {
430
- return h("canvas", {
431
- width: this.getRawWidth(true),
432
- height: this.getRawHeight(true),
433
- });
434
- };
435
-
436
- this.getVideoHeight = function () {
437
- return rawVisualUserMedia.videoHeight;
438
- };
439
-
440
- this.getVideoWidth = function () {
441
- return rawVisualUserMedia.videoWidth;
442
- };
443
-
444
- this.hasVideoWidth = function () {
445
- return this.getVideoWidth() > 0;
446
- };
447
-
448
- this.getRawWidth = function (responsive) {
449
- let rawWidth = this.getVideoWidth();
450
- const widthDefined = options.hasDefinedWidth();
451
-
452
- if (widthDefined || options.hasDefinedHeight()) {
453
- if (!responsive && widthDefined) {
454
- rawWidth = options.video.width;
455
- } else {
456
- rawWidth = recorder.calculateWidth(responsive);
457
- }
458
- }
459
-
460
- if (responsive) {
461
- rawWidth = recorder.limitWidth(rawWidth);
462
- }
463
-
464
- return rawWidth;
465
- };
466
-
467
- this.getRawHeight = function (responsive) {
468
- let rawHeight;
469
-
470
- if (options.hasDefinedDimension()) {
471
- rawHeight = recorder.calculateHeight(responsive);
472
-
473
- if (rawHeight < 1) {
474
- throw VideomailError.create(
475
- "Bad dimensions",
476
- "Calculated raw height cannot be less than 1!",
477
- options,
478
- );
479
- }
480
- } else {
481
- rawHeight = this.getVideoHeight();
482
-
483
- if (rawHeight < 1) {
484
- throw VideomailError.create(
485
- "Bad dimensions",
486
- "Raw video height from DOM element cannot be less than 1!",
487
- options,
488
- );
489
- }
490
- }
491
-
492
- if (responsive) {
493
- rawHeight = recorder.limitHeight(rawHeight);
494
- }
495
-
496
- return rawHeight;
497
- };
498
-
499
- this.getRawVisuals = function () {
500
- return rawVisualUserMedia;
501
- };
502
-
503
- this.pause = function () {
504
- paused = true;
505
- };
506
-
507
- this.isPaused = function () {
508
- return paused;
509
- };
510
-
511
- this.resume = function () {
512
- paused = false;
513
- };
514
-
515
- this.record = function () {
516
- record = true;
517
- };
518
-
519
- this.isRecording = function () {
520
- return record;
521
- };
522
-
523
- this.getAudioSampleRate = function () {
524
- if (audioRecorder) {
525
- return audioRecorder.getSampleRate();
526
- }
527
-
528
- return -1;
529
- };
530
-
531
- this.getCharacteristics = function () {
532
- return {
533
- audioSampleRate: this.getAudioSampleRate(),
534
- muted: rawVisualUserMedia && rawVisualUserMedia.muted,
535
- width: rawVisualUserMedia && rawVisualUserMedia.width,
536
- height: rawVisualUserMedia && rawVisualUserMedia.height,
537
- videoWidth: rawVisualUserMedia && rawVisualUserMedia.videoWidth,
538
- videoHeight: rawVisualUserMedia && rawVisualUserMedia.videoHeight,
539
- };
540
- };
541
- }