ovenplayer 0.10.46 → 0.10.48
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/LICENSE +1 -1
- package/README.md +22 -22
- package/dist/ovenplayer.js +1 -1
- package/dist/ovenplayer.js.map +1 -1
- package/package.json +4 -4
- package/src/js/api/Configurator.js +272 -270
- package/src/js/api/caption/Loader.js +67 -67
- package/src/js/api/caption/Manager.js +143 -141
- package/src/js/api/constants.js +622 -621
- package/src/js/api/provider/html5/Provider.js +570 -563
- package/src/js/api/provider/html5/providers/WebRTCLoader.js +1 -1
- package/src/js/view/components/controls/settingPanel/captionPanel.js +42 -42
- package/src/js/view/components/controls/settingPanel/main.js +321 -321
- package/src/js/view/components/helpers/contextPanel.js +44 -38
- package/src/js/view/components/helpers/contextPanelTemplate.js +19 -9
|
@@ -1,563 +1,570 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by hoho on 2018. 6. 27..
|
|
3
|
-
*/
|
|
4
|
-
import Ima from "api/ads/ima/Ad";
|
|
5
|
-
import Vast from "api/ads/vast/Ad";
|
|
6
|
-
import EventEmitter from "api/EventEmitter";
|
|
7
|
-
import EventsListener from "api/provider/html5/Listener";
|
|
8
|
-
import { pickCurrentSource } from "api/provider/utils";
|
|
9
|
-
import {
|
|
10
|
-
WARN_MSG_MUTEDPLAY,
|
|
11
|
-
UI_ICONS, PLAYER_WARNING,
|
|
12
|
-
STATE_IDLE, STATE_PLAYING, STATE_PAUSED, STATE_COMPLETE, STATE_ERROR,
|
|
13
|
-
PLAYER_STATE, PLAYER_COMPLETE, PLAYER_PAUSE, PLAYER_PLAY, PLAYER_ZOOM_CHANGED, STATE_AD_PLAYING, STATE_AD_PAUSED,
|
|
14
|
-
CONTENT_META, CONTENT_TIME, CONTENT_CAPTION_CUE_CHANGED, CONTENT_SOURCE_CHANGED,
|
|
15
|
-
AD_CLIENT_GOOGLEIMA, AD_CLIENT_VAST,
|
|
16
|
-
PLAYBACK_RATE_CHANGED, CONTENT_MUTE, PROVIDER_HTML5, PROVIDER_WEBRTC, PROVIDER_DASH, PROVIDER_HLS
|
|
17
|
-
} from "api/constants";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @brief Core For Html5 Video.
|
|
21
|
-
* @param spec member value
|
|
22
|
-
* @param playerConfig player config
|
|
23
|
-
* @param onExtendedLoad on load handler
|
|
24
|
-
* */
|
|
25
|
-
const Provider = function (spec, playerConfig, onExtendedLoad) {
|
|
26
|
-
OvenPlayerConsole.log("[Provider] loaded. ");
|
|
27
|
-
|
|
28
|
-
let that = {};
|
|
29
|
-
EventEmitter(that);
|
|
30
|
-
|
|
31
|
-
let dashAttachedView = false;
|
|
32
|
-
|
|
33
|
-
let elVideo = spec.element;
|
|
34
|
-
let ads = null, listener = null, videoEndedCallback = null;
|
|
35
|
-
|
|
36
|
-
let isPlayingProcessing = false;
|
|
37
|
-
|
|
38
|
-
if (spec.adTagUrl) {
|
|
39
|
-
OvenPlayerConsole.log("[Provider] Ad Client - ", playerConfig.getAdClient());
|
|
40
|
-
if (playerConfig.getAdClient() === AD_CLIENT_VAST) {
|
|
41
|
-
ads = Vast(elVideo, that, playerConfig, spec.adTagUrl);
|
|
42
|
-
} else {
|
|
43
|
-
ads = Ima(elVideo, that, playerConfig, spec.adTagUrl);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!ads) {
|
|
47
|
-
console.log("Can not load due to google ima for Ads.");
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
listener = EventsListener(elVideo, that, ads ? ads.videoEndedCallback : null, playerConfig);
|
|
52
|
-
elVideo.playbackRate = elVideo.defaultPlaybackRate = playerConfig.getPlaybackRate();
|
|
53
|
-
spec.zoomFactor = 1.0;
|
|
54
|
-
|
|
55
|
-
const _load = (lastPlayPosition) => {
|
|
56
|
-
|
|
57
|
-
const source = spec.sources[spec.currentSource];
|
|
58
|
-
spec.framerate = source.framerate;
|
|
59
|
-
|
|
60
|
-
that.setVolume(playerConfig.getVolume());
|
|
61
|
-
|
|
62
|
-
if (!spec.framerate) {
|
|
63
|
-
//init timecode mode
|
|
64
|
-
playerConfig.setTimecodeMode(true);
|
|
65
|
-
}
|
|
66
|
-
if (onExtendedLoad) {
|
|
67
|
-
onExtendedLoad(source, lastPlayPosition);
|
|
68
|
-
|
|
69
|
-
} else {
|
|
70
|
-
|
|
71
|
-
OvenPlayerConsole.log("source loaded : ", source, "lastPlayPosition : " + lastPlayPosition);
|
|
72
|
-
|
|
73
|
-
let previousSource = elVideo.src;
|
|
74
|
-
|
|
75
|
-
// const sourceElement = document.createElement('source');
|
|
76
|
-
// sourceElement.src = source.file;
|
|
77
|
-
|
|
78
|
-
const sourceChanged = (source.file !== previousSource);
|
|
79
|
-
|
|
80
|
-
if (sourceChanged) {
|
|
81
|
-
|
|
82
|
-
elVideo.src = source.file;
|
|
83
|
-
|
|
84
|
-
//Don't use this. https://stackoverflow.com/questions/30637784/detect-an-error-on-html5-video
|
|
85
|
-
//elVideo.append(sourceElement);
|
|
86
|
-
|
|
87
|
-
// Do not call load if src was not set. load() will cancel any active play promise.
|
|
88
|
-
if (previousSource || previousSource === '') {
|
|
89
|
-
|
|
90
|
-
elVideo.load();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
that.on(CONTENT_META, function () {
|
|
96
|
-
if (lastPlayPosition > 0) {
|
|
97
|
-
that.seek(lastPlayPosition);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
that.getName = () => {
|
|
105
|
-
return spec.name;
|
|
106
|
-
};
|
|
107
|
-
that.getMse = () => {
|
|
108
|
-
return spec.mse;
|
|
109
|
-
};
|
|
110
|
-
that.getMediaElement = () => {
|
|
111
|
-
return spec.element;
|
|
112
|
-
};
|
|
113
|
-
that.canSeek = () => {
|
|
114
|
-
return spec.canSeek;
|
|
115
|
-
};
|
|
116
|
-
that.setCanSeek = (canSeek) => {
|
|
117
|
-
spec.canSeek = canSeek;
|
|
118
|
-
};
|
|
119
|
-
that.isSeeking = () => {
|
|
120
|
-
return spec.seeking;
|
|
121
|
-
};
|
|
122
|
-
that.setSeeking = (seeking) => {
|
|
123
|
-
spec.seeking = seeking;
|
|
124
|
-
};
|
|
125
|
-
that.setMetaLoaded = () => {
|
|
126
|
-
spec.isLoaded = true;
|
|
127
|
-
};
|
|
128
|
-
that.metaLoaded = () => {
|
|
129
|
-
return spec.isLoaded;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
that.setState = (newState) => {
|
|
133
|
-
if (spec.state !== newState) {
|
|
134
|
-
let prevState = spec.state;
|
|
135
|
-
|
|
136
|
-
OvenPlayerConsole.log("Provider : setState()", newState);
|
|
137
|
-
|
|
138
|
-
//ToDo : This is temporary code. If main video occur error, player avoid error message on ad playing.
|
|
139
|
-
if (prevState === STATE_AD_PLAYING && (newState === STATE_ERROR || newState === STATE_IDLE)) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/*
|
|
144
|
-
* 2019-06-13
|
|
145
|
-
* No more necessary this codes.
|
|
146
|
-
* Checking the autoPlay support was using main video element. elVideo.play() -> yes or no??
|
|
147
|
-
* And then that causes triggering play and pause event.
|
|
148
|
-
* And that checking waits for elVideo loaded. Dash load completion time is unknown.
|
|
149
|
-
* Then I changed check method. I make temporary video tag and insert empty video.
|
|
150
|
-
* */
|
|
151
|
-
//if ((prevState === STATE_AD_PLAYING || prevState === STATE_AD_PAUSED ) && (newState === STATE_PAUSED || newState === STATE_PLAYING)) {
|
|
152
|
-
// return false;
|
|
153
|
-
//Ads checks checkAutoplaySupport(). It calls real play() and pause() to video element.
|
|
154
|
-
//And then that triggers "playing" and "pause".
|
|
155
|
-
//I prevent these process.
|
|
156
|
-
//}
|
|
157
|
-
|
|
158
|
-
OvenPlayerConsole.log("Provider : triggerSatatus", newState);
|
|
159
|
-
switch (newState) {
|
|
160
|
-
case STATE_COMPLETE:
|
|
161
|
-
that.trigger(PLAYER_COMPLETE);
|
|
162
|
-
break;
|
|
163
|
-
case STATE_PAUSED:
|
|
164
|
-
that.trigger(PLAYER_PAUSE, {
|
|
165
|
-
prevState: spec.state,
|
|
166
|
-
newstate: STATE_PAUSED
|
|
167
|
-
});
|
|
168
|
-
break;
|
|
169
|
-
case STATE_AD_PAUSED:
|
|
170
|
-
that.trigger(PLAYER_PAUSE, {
|
|
171
|
-
prevState: spec.state,
|
|
172
|
-
newstate: STATE_AD_PAUSED
|
|
173
|
-
});
|
|
174
|
-
break;
|
|
175
|
-
case STATE_PLAYING:
|
|
176
|
-
that.trigger(PLAYER_PLAY, {
|
|
177
|
-
prevState: spec.state,
|
|
178
|
-
newstate: STATE_PLAYING
|
|
179
|
-
});
|
|
180
|
-
break;
|
|
181
|
-
case STATE_AD_PLAYING:
|
|
182
|
-
that.trigger(PLAYER_PLAY, {
|
|
183
|
-
prevState: spec.state,
|
|
184
|
-
newstate: STATE_AD_PLAYING
|
|
185
|
-
});
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
spec.state = newState;
|
|
189
|
-
that.trigger(PLAYER_STATE, {
|
|
190
|
-
prevstate: prevState,
|
|
191
|
-
newstate: spec.state
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
that.getState = () => {
|
|
198
|
-
return spec.state;
|
|
199
|
-
};
|
|
200
|
-
that.setBuffer = (newBuffer) => {
|
|
201
|
-
spec.buffer = newBuffer;
|
|
202
|
-
};
|
|
203
|
-
that.getBuffer = () => {
|
|
204
|
-
return spec.buffer;
|
|
205
|
-
};
|
|
206
|
-
that.isLive = () => {
|
|
207
|
-
return spec.isLive ? true : (elVideo.duration === Infinity);
|
|
208
|
-
};
|
|
209
|
-
that.getDuration = () => {
|
|
210
|
-
return that.isLive() ? Infinity : elVideo.duration;
|
|
211
|
-
};
|
|
212
|
-
that.getDvrWindow = () => {
|
|
213
|
-
return spec.dvrWindow;
|
|
214
|
-
};
|
|
215
|
-
that.getPosition = () => {
|
|
216
|
-
if (!elVideo) {
|
|
217
|
-
return 0;
|
|
218
|
-
}
|
|
219
|
-
return elVideo.currentTime;
|
|
220
|
-
};
|
|
221
|
-
that.setVolume = (volume) => {
|
|
222
|
-
if (!elVideo) {
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
elVideo.volume = volume / 100;
|
|
226
|
-
playerConfig.setVolume(volume);
|
|
227
|
-
};
|
|
228
|
-
that.getVolume = () => {
|
|
229
|
-
|
|
230
|
-
return playerConfig.getVolume();
|
|
231
|
-
};
|
|
232
|
-
that.setMute = (state) => {
|
|
233
|
-
if (!elVideo) {
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
if (typeof state === 'undefined') {
|
|
237
|
-
|
|
238
|
-
const muted = playerConfig.isMute();
|
|
239
|
-
|
|
240
|
-
elVideo.muted = !muted;
|
|
241
|
-
playerConfig.setMute(!muted);
|
|
242
|
-
|
|
243
|
-
that.trigger(CONTENT_MUTE, {
|
|
244
|
-
mute: playerConfig.isMute()
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
} else {
|
|
248
|
-
|
|
249
|
-
elVideo.muted = state;
|
|
250
|
-
playerConfig.setMute(state);
|
|
251
|
-
|
|
252
|
-
that.trigger(CONTENT_MUTE, {
|
|
253
|
-
mute: playerConfig.isMute()
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
return elVideo.muted;
|
|
257
|
-
};
|
|
258
|
-
that.getMute = () => {
|
|
259
|
-
|
|
260
|
-
return playerConfig.isMute();
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
that.preload = (sources, lastPlayPosition) => {
|
|
264
|
-
|
|
265
|
-
spec.sources = sources;
|
|
266
|
-
|
|
267
|
-
spec.currentSource = pickCurrentSource(sources, playerConfig);
|
|
268
|
-
_load(lastPlayPosition || 0);
|
|
269
|
-
|
|
270
|
-
return new Promise(function (resolve, reject) {
|
|
271
|
-
|
|
272
|
-
if (playerConfig.isMute()) {
|
|
273
|
-
that.setMute(true);
|
|
274
|
-
}
|
|
275
|
-
if (playerConfig.getVolume()) {
|
|
276
|
-
that.setVolume(playerConfig.getVolume());
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
resolve();
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
};
|
|
283
|
-
that.load = (sources) => {
|
|
284
|
-
|
|
285
|
-
spec.sources = sources;
|
|
286
|
-
spec.currentSource = pickCurrentSource(sources, playerConfig);
|
|
287
|
-
_load(0);
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
that.play = () => {
|
|
291
|
-
|
|
292
|
-
OvenPlayerConsole.log("Provider : play()");
|
|
293
|
-
if (!elVideo) {
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
//Test it thoroughly and remove isPlayingProcessing. Most of the hazards have been removed. a lot of nonblocking play() way -> blocking play()
|
|
298
|
-
// if(isPlayingProcessing){
|
|
299
|
-
// return false;
|
|
300
|
-
// }
|
|
301
|
-
|
|
302
|
-
isPlayingProcessing = true;
|
|
303
|
-
if (that.getState() !== STATE_PLAYING) {
|
|
304
|
-
if ((ads && ads.isActive()) || (ads && !ads.started())) {
|
|
305
|
-
ads.play().then(_ => {
|
|
306
|
-
//ads play success
|
|
307
|
-
isPlayingProcessing = false;
|
|
308
|
-
OvenPlayerConsole.log("Provider : ads play success");
|
|
309
|
-
|
|
310
|
-
}).catch(error => {
|
|
311
|
-
//ads play fail maybe cause user interactive less
|
|
312
|
-
isPlayingProcessing = false;
|
|
313
|
-
OvenPlayerConsole.log("Provider : ads play fail", error);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
} else {
|
|
317
|
-
let promise = elVideo.play();
|
|
318
|
-
if (promise !== undefined) {
|
|
319
|
-
promise.then(function () {
|
|
320
|
-
isPlayingProcessing = false;
|
|
321
|
-
OvenPlayerConsole.log("Provider : video play success");
|
|
322
|
-
/*
|
|
323
|
-
if(mutedPlay){
|
|
324
|
-
that.trigger(PLAYER_WARNING, {
|
|
325
|
-
message : WARN_MSG_MUTEDPLAY,
|
|
326
|
-
timer : 10 * 1000,
|
|
327
|
-
iconClass : UI_ICONS.volume_mute,
|
|
328
|
-
onClickCallback : function(){
|
|
329
|
-
that.setMute(false);
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
}*/
|
|
333
|
-
}).catch(error => {
|
|
334
|
-
OvenPlayerConsole.log("Provider : video play error", error.message);
|
|
335
|
-
|
|
336
|
-
isPlayingProcessing = false;
|
|
337
|
-
|
|
338
|
-
if
|
|
339
|
-
|
|
340
|
-
that.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if (
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
};
|
|
379
|
-
that.
|
|
380
|
-
if (!elVideo) {
|
|
381
|
-
return
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
return
|
|
391
|
-
};
|
|
392
|
-
that.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return spec.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
//
|
|
431
|
-
//that.
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
that.
|
|
467
|
-
if (!elVideo) {
|
|
468
|
-
return [];
|
|
469
|
-
}
|
|
470
|
-
return spec.
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
that.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
that.
|
|
485
|
-
if (!elVideo) {
|
|
486
|
-
return [];
|
|
487
|
-
}
|
|
488
|
-
return spec.
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
that.
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
that.
|
|
499
|
-
//Do nothing
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
that.
|
|
503
|
-
|
|
504
|
-
};
|
|
505
|
-
that.
|
|
506
|
-
|
|
507
|
-
};
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Created by hoho on 2018. 6. 27..
|
|
3
|
+
*/
|
|
4
|
+
import Ima from "api/ads/ima/Ad";
|
|
5
|
+
import Vast from "api/ads/vast/Ad";
|
|
6
|
+
import EventEmitter from "api/EventEmitter";
|
|
7
|
+
import EventsListener from "api/provider/html5/Listener";
|
|
8
|
+
import { pickCurrentSource } from "api/provider/utils";
|
|
9
|
+
import {
|
|
10
|
+
WARN_MSG_MUTEDPLAY,
|
|
11
|
+
UI_ICONS, PLAYER_WARNING,
|
|
12
|
+
STATE_IDLE, STATE_PLAYING, STATE_PAUSED, STATE_COMPLETE, STATE_ERROR,
|
|
13
|
+
PLAYER_STATE, PLAYER_COMPLETE, PLAYER_PAUSE, PLAYER_PLAY, PLAYER_ZOOM_CHANGED, STATE_AD_PLAYING, STATE_AD_PAUSED,
|
|
14
|
+
CONTENT_META, CONTENT_TIME, CONTENT_CAPTION_CUE_CHANGED, CONTENT_SOURCE_CHANGED,
|
|
15
|
+
AD_CLIENT_GOOGLEIMA, AD_CLIENT_VAST,
|
|
16
|
+
PLAYBACK_RATE_CHANGED, CONTENT_MUTE, PROVIDER_HTML5, PROVIDER_WEBRTC, PROVIDER_DASH, PROVIDER_HLS
|
|
17
|
+
} from "api/constants";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @brief Core For Html5 Video.
|
|
21
|
+
* @param spec member value
|
|
22
|
+
* @param playerConfig player config
|
|
23
|
+
* @param onExtendedLoad on load handler
|
|
24
|
+
* */
|
|
25
|
+
const Provider = function (spec, playerConfig, onExtendedLoad) {
|
|
26
|
+
OvenPlayerConsole.log("[Provider] loaded. ");
|
|
27
|
+
|
|
28
|
+
let that = {};
|
|
29
|
+
EventEmitter(that);
|
|
30
|
+
|
|
31
|
+
let dashAttachedView = false;
|
|
32
|
+
|
|
33
|
+
let elVideo = spec.element;
|
|
34
|
+
let ads = null, listener = null, videoEndedCallback = null;
|
|
35
|
+
|
|
36
|
+
let isPlayingProcessing = false;
|
|
37
|
+
|
|
38
|
+
if (spec.adTagUrl) {
|
|
39
|
+
OvenPlayerConsole.log("[Provider] Ad Client - ", playerConfig.getAdClient());
|
|
40
|
+
if (playerConfig.getAdClient() === AD_CLIENT_VAST) {
|
|
41
|
+
ads = Vast(elVideo, that, playerConfig, spec.adTagUrl);
|
|
42
|
+
} else {
|
|
43
|
+
ads = Ima(elVideo, that, playerConfig, spec.adTagUrl);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!ads) {
|
|
47
|
+
console.log("Can not load due to google ima for Ads.");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
listener = EventsListener(elVideo, that, ads ? ads.videoEndedCallback : null, playerConfig);
|
|
52
|
+
elVideo.playbackRate = elVideo.defaultPlaybackRate = playerConfig.getPlaybackRate();
|
|
53
|
+
spec.zoomFactor = 1.0;
|
|
54
|
+
|
|
55
|
+
const _load = (lastPlayPosition) => {
|
|
56
|
+
|
|
57
|
+
const source = spec.sources[spec.currentSource];
|
|
58
|
+
spec.framerate = source.framerate;
|
|
59
|
+
|
|
60
|
+
that.setVolume(playerConfig.getVolume());
|
|
61
|
+
|
|
62
|
+
if (!spec.framerate) {
|
|
63
|
+
//init timecode mode
|
|
64
|
+
playerConfig.setTimecodeMode(true);
|
|
65
|
+
}
|
|
66
|
+
if (onExtendedLoad) {
|
|
67
|
+
onExtendedLoad(source, lastPlayPosition);
|
|
68
|
+
|
|
69
|
+
} else {
|
|
70
|
+
|
|
71
|
+
OvenPlayerConsole.log("source loaded : ", source, "lastPlayPosition : " + lastPlayPosition);
|
|
72
|
+
|
|
73
|
+
let previousSource = elVideo.src;
|
|
74
|
+
|
|
75
|
+
// const sourceElement = document.createElement('source');
|
|
76
|
+
// sourceElement.src = source.file;
|
|
77
|
+
|
|
78
|
+
const sourceChanged = (source.file !== previousSource);
|
|
79
|
+
|
|
80
|
+
if (sourceChanged) {
|
|
81
|
+
|
|
82
|
+
elVideo.src = source.file;
|
|
83
|
+
|
|
84
|
+
//Don't use this. https://stackoverflow.com/questions/30637784/detect-an-error-on-html5-video
|
|
85
|
+
//elVideo.append(sourceElement);
|
|
86
|
+
|
|
87
|
+
// Do not call load if src was not set. load() will cancel any active play promise.
|
|
88
|
+
if (previousSource || previousSource === '') {
|
|
89
|
+
|
|
90
|
+
elVideo.load();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
that.on(CONTENT_META, function () {
|
|
96
|
+
if (lastPlayPosition > 0) {
|
|
97
|
+
that.seek(lastPlayPosition);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
that.getName = () => {
|
|
105
|
+
return spec.name;
|
|
106
|
+
};
|
|
107
|
+
that.getMse = () => {
|
|
108
|
+
return spec.mse;
|
|
109
|
+
};
|
|
110
|
+
that.getMediaElement = () => {
|
|
111
|
+
return spec.element;
|
|
112
|
+
};
|
|
113
|
+
that.canSeek = () => {
|
|
114
|
+
return spec.canSeek;
|
|
115
|
+
};
|
|
116
|
+
that.setCanSeek = (canSeek) => {
|
|
117
|
+
spec.canSeek = canSeek;
|
|
118
|
+
};
|
|
119
|
+
that.isSeeking = () => {
|
|
120
|
+
return spec.seeking;
|
|
121
|
+
};
|
|
122
|
+
that.setSeeking = (seeking) => {
|
|
123
|
+
spec.seeking = seeking;
|
|
124
|
+
};
|
|
125
|
+
that.setMetaLoaded = () => {
|
|
126
|
+
spec.isLoaded = true;
|
|
127
|
+
};
|
|
128
|
+
that.metaLoaded = () => {
|
|
129
|
+
return spec.isLoaded;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
that.setState = (newState) => {
|
|
133
|
+
if (spec.state !== newState) {
|
|
134
|
+
let prevState = spec.state;
|
|
135
|
+
|
|
136
|
+
OvenPlayerConsole.log("Provider : setState()", newState);
|
|
137
|
+
|
|
138
|
+
//ToDo : This is temporary code. If main video occur error, player avoid error message on ad playing.
|
|
139
|
+
if (prevState === STATE_AD_PLAYING && (newState === STATE_ERROR || newState === STATE_IDLE)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/*
|
|
144
|
+
* 2019-06-13
|
|
145
|
+
* No more necessary this codes.
|
|
146
|
+
* Checking the autoPlay support was using main video element. elVideo.play() -> yes or no??
|
|
147
|
+
* And then that causes triggering play and pause event.
|
|
148
|
+
* And that checking waits for elVideo loaded. Dash load completion time is unknown.
|
|
149
|
+
* Then I changed check method. I make temporary video tag and insert empty video.
|
|
150
|
+
* */
|
|
151
|
+
//if ((prevState === STATE_AD_PLAYING || prevState === STATE_AD_PAUSED ) && (newState === STATE_PAUSED || newState === STATE_PLAYING)) {
|
|
152
|
+
// return false;
|
|
153
|
+
//Ads checks checkAutoplaySupport(). It calls real play() and pause() to video element.
|
|
154
|
+
//And then that triggers "playing" and "pause".
|
|
155
|
+
//I prevent these process.
|
|
156
|
+
//}
|
|
157
|
+
|
|
158
|
+
OvenPlayerConsole.log("Provider : triggerSatatus", newState);
|
|
159
|
+
switch (newState) {
|
|
160
|
+
case STATE_COMPLETE:
|
|
161
|
+
that.trigger(PLAYER_COMPLETE);
|
|
162
|
+
break;
|
|
163
|
+
case STATE_PAUSED:
|
|
164
|
+
that.trigger(PLAYER_PAUSE, {
|
|
165
|
+
prevState: spec.state,
|
|
166
|
+
newstate: STATE_PAUSED
|
|
167
|
+
});
|
|
168
|
+
break;
|
|
169
|
+
case STATE_AD_PAUSED:
|
|
170
|
+
that.trigger(PLAYER_PAUSE, {
|
|
171
|
+
prevState: spec.state,
|
|
172
|
+
newstate: STATE_AD_PAUSED
|
|
173
|
+
});
|
|
174
|
+
break;
|
|
175
|
+
case STATE_PLAYING:
|
|
176
|
+
that.trigger(PLAYER_PLAY, {
|
|
177
|
+
prevState: spec.state,
|
|
178
|
+
newstate: STATE_PLAYING
|
|
179
|
+
});
|
|
180
|
+
break;
|
|
181
|
+
case STATE_AD_PLAYING:
|
|
182
|
+
that.trigger(PLAYER_PLAY, {
|
|
183
|
+
prevState: spec.state,
|
|
184
|
+
newstate: STATE_AD_PLAYING
|
|
185
|
+
});
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
spec.state = newState;
|
|
189
|
+
that.trigger(PLAYER_STATE, {
|
|
190
|
+
prevstate: prevState,
|
|
191
|
+
newstate: spec.state
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
that.getState = () => {
|
|
198
|
+
return spec.state;
|
|
199
|
+
};
|
|
200
|
+
that.setBuffer = (newBuffer) => {
|
|
201
|
+
spec.buffer = newBuffer;
|
|
202
|
+
};
|
|
203
|
+
that.getBuffer = () => {
|
|
204
|
+
return spec.buffer;
|
|
205
|
+
};
|
|
206
|
+
that.isLive = () => {
|
|
207
|
+
return spec.isLive ? true : (elVideo.duration === Infinity);
|
|
208
|
+
};
|
|
209
|
+
that.getDuration = () => {
|
|
210
|
+
return that.isLive() ? Infinity : elVideo.duration;
|
|
211
|
+
};
|
|
212
|
+
that.getDvrWindow = () => {
|
|
213
|
+
return spec.dvrWindow;
|
|
214
|
+
};
|
|
215
|
+
that.getPosition = () => {
|
|
216
|
+
if (!elVideo) {
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
return elVideo.currentTime;
|
|
220
|
+
};
|
|
221
|
+
that.setVolume = (volume) => {
|
|
222
|
+
if (!elVideo) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
elVideo.volume = volume / 100;
|
|
226
|
+
playerConfig.setVolume(volume);
|
|
227
|
+
};
|
|
228
|
+
that.getVolume = () => {
|
|
229
|
+
|
|
230
|
+
return playerConfig.getVolume();
|
|
231
|
+
};
|
|
232
|
+
that.setMute = (state) => {
|
|
233
|
+
if (!elVideo) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
if (typeof state === 'undefined') {
|
|
237
|
+
|
|
238
|
+
const muted = playerConfig.isMute();
|
|
239
|
+
|
|
240
|
+
elVideo.muted = !muted;
|
|
241
|
+
playerConfig.setMute(!muted);
|
|
242
|
+
|
|
243
|
+
that.trigger(CONTENT_MUTE, {
|
|
244
|
+
mute: playerConfig.isMute()
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
} else {
|
|
248
|
+
|
|
249
|
+
elVideo.muted = state;
|
|
250
|
+
playerConfig.setMute(state);
|
|
251
|
+
|
|
252
|
+
that.trigger(CONTENT_MUTE, {
|
|
253
|
+
mute: playerConfig.isMute()
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return elVideo.muted;
|
|
257
|
+
};
|
|
258
|
+
that.getMute = () => {
|
|
259
|
+
|
|
260
|
+
return playerConfig.isMute();
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
that.preload = (sources, lastPlayPosition) => {
|
|
264
|
+
|
|
265
|
+
spec.sources = sources;
|
|
266
|
+
|
|
267
|
+
spec.currentSource = pickCurrentSource(sources, playerConfig);
|
|
268
|
+
_load(lastPlayPosition || 0);
|
|
269
|
+
|
|
270
|
+
return new Promise(function (resolve, reject) {
|
|
271
|
+
|
|
272
|
+
if (playerConfig.isMute()) {
|
|
273
|
+
that.setMute(true);
|
|
274
|
+
}
|
|
275
|
+
if (playerConfig.getVolume()) {
|
|
276
|
+
that.setVolume(playerConfig.getVolume());
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
resolve();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
};
|
|
283
|
+
that.load = (sources) => {
|
|
284
|
+
|
|
285
|
+
spec.sources = sources;
|
|
286
|
+
spec.currentSource = pickCurrentSource(sources, playerConfig);
|
|
287
|
+
_load(0);
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
that.play = () => {
|
|
291
|
+
|
|
292
|
+
OvenPlayerConsole.log("Provider : play()");
|
|
293
|
+
if (!elVideo) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
//Test it thoroughly and remove isPlayingProcessing. Most of the hazards have been removed. a lot of nonblocking play() way -> blocking play()
|
|
298
|
+
// if(isPlayingProcessing){
|
|
299
|
+
// return false;
|
|
300
|
+
// }
|
|
301
|
+
|
|
302
|
+
isPlayingProcessing = true;
|
|
303
|
+
if (that.getState() !== STATE_PLAYING) {
|
|
304
|
+
if ((ads && ads.isActive()) || (ads && !ads.started())) {
|
|
305
|
+
ads.play().then(_ => {
|
|
306
|
+
//ads play success
|
|
307
|
+
isPlayingProcessing = false;
|
|
308
|
+
OvenPlayerConsole.log("Provider : ads play success");
|
|
309
|
+
|
|
310
|
+
}).catch(error => {
|
|
311
|
+
//ads play fail maybe cause user interactive less
|
|
312
|
+
isPlayingProcessing = false;
|
|
313
|
+
OvenPlayerConsole.log("Provider : ads play fail", error);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
} else {
|
|
317
|
+
let promise = elVideo.play();
|
|
318
|
+
if (promise !== undefined) {
|
|
319
|
+
promise.then(function () {
|
|
320
|
+
isPlayingProcessing = false;
|
|
321
|
+
OvenPlayerConsole.log("Provider : video play success");
|
|
322
|
+
/*
|
|
323
|
+
if(mutedPlay){
|
|
324
|
+
that.trigger(PLAYER_WARNING, {
|
|
325
|
+
message : WARN_MSG_MUTEDPLAY,
|
|
326
|
+
timer : 10 * 1000,
|
|
327
|
+
iconClass : UI_ICONS.volume_mute,
|
|
328
|
+
onClickCallback : function(){
|
|
329
|
+
that.setMute(false);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}*/
|
|
333
|
+
}).catch(error => {
|
|
334
|
+
OvenPlayerConsole.log("Provider : video play error", error.message);
|
|
335
|
+
|
|
336
|
+
isPlayingProcessing = false;
|
|
337
|
+
|
|
338
|
+
// Auto mute and retry play if autoMuteRetryOnNotAllowed config is enabled
|
|
339
|
+
if (error.name === 'NotAllowedError' && playerConfig.getConfig().autoMuteRetryOnNotAllowed) {
|
|
340
|
+
that.setMute(true);
|
|
341
|
+
that.play(true);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/*
|
|
345
|
+
if(!mutedPlay){
|
|
346
|
+
that.setMute(true);
|
|
347
|
+
that.play(true);
|
|
348
|
+
}
|
|
349
|
+
*/
|
|
350
|
+
});
|
|
351
|
+
} else {
|
|
352
|
+
//IE promise is undefinded.
|
|
353
|
+
OvenPlayerConsole.log("Provider : video play success (ie)");
|
|
354
|
+
isPlayingProcessing = false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
};
|
|
360
|
+
that.pause = () => {
|
|
361
|
+
|
|
362
|
+
OvenPlayerConsole.log("Provider : pause()");
|
|
363
|
+
if (!elVideo) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (that.getState() === STATE_PLAYING) {
|
|
368
|
+
elVideo.pause();
|
|
369
|
+
} else if (that.getState() === STATE_AD_PLAYING) {
|
|
370
|
+
ads.pause();
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
that.seek = (position) => {
|
|
374
|
+
if (!elVideo) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
elVideo.currentTime = position;
|
|
378
|
+
};
|
|
379
|
+
that.setPlaybackRate = (playbackRate) => {
|
|
380
|
+
if (!elVideo) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
that.trigger(PLAYBACK_RATE_CHANGED, { playbackRate: playbackRate });
|
|
384
|
+
return elVideo.playbackRate = elVideo.defaultPlaybackRate = playbackRate;
|
|
385
|
+
};
|
|
386
|
+
that.getPlaybackRate = () => {
|
|
387
|
+
if (!elVideo) {
|
|
388
|
+
return 0;
|
|
389
|
+
}
|
|
390
|
+
return elVideo.playbackRate;
|
|
391
|
+
};
|
|
392
|
+
that.getZoomFactor = () => {
|
|
393
|
+
return spec.zoomFactor;
|
|
394
|
+
};
|
|
395
|
+
that.setZoomFactor = (zoomFactor) => {
|
|
396
|
+
that.trigger(PLAYER_ZOOM_CHANGED, { zoomFactor: zoomFactor });
|
|
397
|
+
return spec.zoomFactor = zoomFactor;
|
|
398
|
+
};
|
|
399
|
+
that.getSources = () => {
|
|
400
|
+
if (!elVideo) {
|
|
401
|
+
return [];
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return spec.sources.map(function (source, index) {
|
|
405
|
+
|
|
406
|
+
var obj = {
|
|
407
|
+
file: source.file,
|
|
408
|
+
type: source.type,
|
|
409
|
+
label: source.label,
|
|
410
|
+
index: index,
|
|
411
|
+
sectionStart: source.sectionStart,
|
|
412
|
+
sectionEnd: source.sectionEnd,
|
|
413
|
+
gridThumbnail: source.gridThumbnail,
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
if (source.lowLatency) {
|
|
417
|
+
obj.lowLatency = source.lowLatency;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return obj;
|
|
421
|
+
});
|
|
422
|
+
};
|
|
423
|
+
that.getCurrentSource = () => {
|
|
424
|
+
return spec.currentSource;
|
|
425
|
+
};
|
|
426
|
+
that.setCurrentSource = (sourceIndex, needProviderChange) => {
|
|
427
|
+
|
|
428
|
+
if (sourceIndex > -1) {
|
|
429
|
+
if (spec.sources && spec.sources.length > sourceIndex) {
|
|
430
|
+
//that.pause();
|
|
431
|
+
//that.setState(STATE_IDLE);
|
|
432
|
+
OvenPlayerConsole.log("source changed : " + sourceIndex);
|
|
433
|
+
spec.currentSource = sourceIndex;
|
|
434
|
+
|
|
435
|
+
playerConfig.setSourceIndex(sourceIndex);
|
|
436
|
+
//playerConfig.setSourceLabel(spec.sources[sourceIndex].label);
|
|
437
|
+
//spec.currentQuality = sourceIndex;
|
|
438
|
+
//that.pause();
|
|
439
|
+
that.setState(STATE_IDLE);
|
|
440
|
+
if (needProviderChange) {
|
|
441
|
+
_load(elVideo.currentTime || 0);
|
|
442
|
+
}
|
|
443
|
+
//
|
|
444
|
+
return spec.currentSource;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
that.getQualityLevels = () => {
|
|
451
|
+
if (!elVideo) {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
return spec.qualityLevels;
|
|
455
|
+
};
|
|
456
|
+
that.getCurrentQuality = () => {
|
|
457
|
+
if (!elVideo) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
return spec.currentQuality;
|
|
461
|
+
};
|
|
462
|
+
that.setCurrentQuality = (qualityIndex) => {
|
|
463
|
+
//Do nothing
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
that.getAudioTracks = () => {
|
|
467
|
+
if (!elVideo) {
|
|
468
|
+
return [];
|
|
469
|
+
}
|
|
470
|
+
return spec.audioTracks;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
that.getCurrentAudioTrack = () => {
|
|
474
|
+
if (!elVideo) {
|
|
475
|
+
return [];
|
|
476
|
+
}
|
|
477
|
+
return spec.currentAudioTrack;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
that.setCurrentAudioTrack = (audioTrackIndex) => {
|
|
481
|
+
//Do nothing
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
that.getSubtitleTracks = () => {
|
|
485
|
+
if (!elVideo) {
|
|
486
|
+
return [];
|
|
487
|
+
}
|
|
488
|
+
return spec.subtitleTracks;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
that.getCurrentSubtitleTrack = () => {
|
|
492
|
+
if (!elVideo) {
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
return spec.currentSubtitleTrack;
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
that.setCurrentSubtitleTrack = (subtitleTrackIndex) => {
|
|
499
|
+
//Do nothing
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
that.isAutoQuality = () => {
|
|
503
|
+
//Do nothing
|
|
504
|
+
};
|
|
505
|
+
that.setAutoQuality = (isAuto) => {
|
|
506
|
+
//Do nothing
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
that.getFramerate = () => {
|
|
510
|
+
return spec.framerate;
|
|
511
|
+
};
|
|
512
|
+
that.setFramerate = (framerate) => {
|
|
513
|
+
return spec.framerate = framerate;
|
|
514
|
+
};
|
|
515
|
+
that.seekFrame = (frameCount) => {
|
|
516
|
+
let fps = spec.framerate;
|
|
517
|
+
let currentFrames = elVideo.currentTime * fps;
|
|
518
|
+
let newPosition = (currentFrames + frameCount) / fps;
|
|
519
|
+
newPosition = newPosition + 0.00001; // FIXES A SAFARI SEEK ISSUE. myVdieo.currentTime = 0.04 would give SMPTE 00:00:00:00 wheras it should give 00:00:00:01
|
|
520
|
+
|
|
521
|
+
that.pause();
|
|
522
|
+
that.seek(newPosition);
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
that.stop = () => {
|
|
526
|
+
if (!elVideo) {
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
OvenPlayerConsole.log("CORE : stop() ");
|
|
530
|
+
|
|
531
|
+
elVideo.removeAttribute('preload');
|
|
532
|
+
elVideo.removeAttribute('src');
|
|
533
|
+
while (elVideo.firstChild) {
|
|
534
|
+
elVideo.removeChild(elVideo.firstChild);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
that.pause();
|
|
538
|
+
that.setState(STATE_IDLE);
|
|
539
|
+
isPlayingProcessing = false;
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
that.destroy = () => {
|
|
543
|
+
if (!elVideo) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
that.stop();
|
|
547
|
+
listener.destroy();
|
|
548
|
+
//elVideo.remove();
|
|
549
|
+
|
|
550
|
+
if (ads) {
|
|
551
|
+
ads.destroy();
|
|
552
|
+
ads = null;
|
|
553
|
+
}
|
|
554
|
+
that.off();
|
|
555
|
+
OvenPlayerConsole.log("CORE : destroy() player stop, listener, event destroied");
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
//XXX : I hope using es6 classes. but I think to occur problem from Old IE. Then I choice function inherit. Finally using super function is so difficult.
|
|
559
|
+
// use : let super_destroy = that.super('destroy'); ... super_destroy();
|
|
560
|
+
that.super = (name) => {
|
|
561
|
+
const method = that[name];
|
|
562
|
+
return function () {
|
|
563
|
+
return method.apply(that, arguments);
|
|
564
|
+
};
|
|
565
|
+
};
|
|
566
|
+
return that;
|
|
567
|
+
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
export default Provider;
|