videomail-client 8.3.1 → 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 (38) hide show
  1. package/package.json +1 -1
  2. package/prototype/js/videomail-client.js +12 -14
  3. package/prototype/js/videomail-client.min.js +1 -1
  4. package/prototype/js/videomail-client.min.js.map +1 -1
  5. package/src/js/client.js +0 -210
  6. package/src/js/constants.js +0 -11
  7. package/src/js/events.js +0 -46
  8. package/src/js/index.js +0 -15
  9. package/src/js/options.js +0 -180
  10. package/src/js/resource.js +0 -206
  11. package/src/js/util/audioRecorder.js +0 -152
  12. package/src/js/util/browser.js +0 -319
  13. package/src/js/util/collectLogger.js +0 -72
  14. package/src/js/util/eventEmitter.js +0 -72
  15. package/src/js/util/humanize.js +0 -16
  16. package/src/js/util/mediaEvents.js +0 -148
  17. package/src/js/util/pretty.js +0 -70
  18. package/src/js/util/standardize.js +0 -71
  19. package/src/js/util/videomailError.js +0 -431
  20. package/src/js/wrappers/buttons.js +0 -670
  21. package/src/js/wrappers/container.js +0 -797
  22. package/src/js/wrappers/dimension.js +0 -149
  23. package/src/js/wrappers/form.js +0 -319
  24. package/src/js/wrappers/optionsWrapper.js +0 -81
  25. package/src/js/wrappers/visuals/inside/recorder/countdown.js +0 -83
  26. package/src/js/wrappers/visuals/inside/recorder/facingMode.js +0 -53
  27. package/src/js/wrappers/visuals/inside/recorder/pausedNote.js +0 -59
  28. package/src/js/wrappers/visuals/inside/recorder/recordNote.js +0 -42
  29. package/src/js/wrappers/visuals/inside/recorder/recordTimer.js +0 -149
  30. package/src/js/wrappers/visuals/inside/recorderInsides.js +0 -144
  31. package/src/js/wrappers/visuals/notifier.js +0 -341
  32. package/src/js/wrappers/visuals/recorder.js +0 -1492
  33. package/src/js/wrappers/visuals/replay.js +0 -355
  34. package/src/js/wrappers/visuals/userMedia.js +0 -541
  35. package/src/js/wrappers/visuals.js +0 -410
  36. package/src/styles/css/main.min.css.js +0 -1
  37. package/src/styles/styl/keyframes/blink.styl +0 -16
  38. package/src/styles/styl/main.styl +0 -126
@@ -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
- }