playable
Version:
Video player based on HTML5Video
170 lines • 6.29 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NATIVE_VIDEO_EVENTS_TO_STATE = void 0;
var device_detection_1 = require("../../../../utils/device-detection");
var constants_1 = require("../../../../constants");
exports.NATIVE_VIDEO_EVENTS_TO_STATE = [
'loadstart',
'loadedmetadata',
'canplay',
'play',
'playing',
'pause',
'ended',
'waiting',
'seeking',
'seeked',
];
var StateEngine = /** @class */ (function () {
function StateEngine(eventEmitter, video) {
this._eventEmitter = eventEmitter;
this._video = video;
this._currentState = null;
this._isMetadataLoaded = false;
this._statesTimestamps = {};
this._bindCallbacks();
this._bindEvents();
}
StateEngine.prototype._bindCallbacks = function () {
this._processEventFromVideo = this._processEventFromVideo.bind(this);
};
StateEngine.prototype._bindEvents = function () {
var _this = this;
exports.NATIVE_VIDEO_EVENTS_TO_STATE.forEach(function (event) {
_this._video.addEventListener(event, _this._processEventFromVideo);
});
};
StateEngine.prototype._unbindEvents = function () {
var _this = this;
exports.NATIVE_VIDEO_EVENTS_TO_STATE.forEach(function (event) {
return _this._video.removeEventListener(event, _this._processEventFromVideo);
});
};
StateEngine.prototype.clearTimestamps = function () {
this._statesTimestamps = {};
};
StateEngine.prototype._setInitialTimeStamp = function () {
this._initialTimeStamp = Date.now();
};
StateEngine.prototype._setStateTimestamp = function (state) {
if (!this._statesTimestamps[state]) {
this._statesTimestamps[state] = Date.now() - this._initialTimeStamp;
this._setInitialTimeStamp();
}
};
Object.defineProperty(StateEngine.prototype, "stateTimestamps", {
get: function () {
return this._statesTimestamps;
},
enumerable: false,
configurable: true
});
StateEngine.prototype._processEventFromVideo = function (event) {
if (event === void 0) { event = {}; }
var videoElement = this._video;
switch (event.type) {
case 'loadstart': {
this._setInitialTimeStamp();
this.setState(constants_1.EngineState.LOAD_STARTED);
break;
}
case 'loadedmetadata': {
this._setStateTimestamp(constants_1.EngineState.METADATA_LOADED);
this.setState(constants_1.EngineState.METADATA_LOADED);
this._isMetadataLoaded = true;
break;
}
case 'canplay': {
if (this._currentState === constants_1.EngineState.METADATA_LOADED) {
this._setStateTimestamp(constants_1.EngineState.READY_TO_PLAY);
this.setState(constants_1.EngineState.READY_TO_PLAY);
}
break;
}
case 'play': {
this.setState(constants_1.EngineState.PLAY_REQUESTED);
break;
}
case 'playing': {
// Safari triggers event 'playing' even when play request aborted by browser. So we need to check if video is actualy playing
if ((0, device_detection_1.isSafari)()) {
if (!videoElement.paused) {
this.setState(constants_1.EngineState.PLAYING);
}
}
else {
this.setState(constants_1.EngineState.PLAYING);
}
break;
}
case 'waiting': {
this.setState(constants_1.EngineState.WAITING);
break;
}
case 'pause': {
// Safari triggers event 'pause' even when playing was aborted buy autoplay policies, emit pause event even if there wasn't any real playback
if ((0, device_detection_1.isSafari)()) {
if (videoElement.played.length) {
this.setState(constants_1.EngineState.PAUSED);
}
}
else {
this.setState(constants_1.EngineState.PAUSED);
}
break;
}
case 'ended': {
this.setState(constants_1.EngineState.ENDED);
break;
}
case 'seeking': {
this.setState(constants_1.EngineState.SEEK_IN_PROGRESS);
break;
}
case 'seeked': {
this.setState(videoElement.paused ? constants_1.EngineState.PAUSED : constants_1.EngineState.PLAYING);
break;
}
default:
break;
}
};
StateEngine.prototype.setState = function (state) {
if (state === this._currentState) {
return;
}
//This case is happens only with dash.js sometimes when manifest got some problems
if (this._currentState === constants_1.EngineState.METADATA_LOADED) {
if (state === constants_1.EngineState.SEEK_IN_PROGRESS ||
state === constants_1.EngineState.PAUSED) {
return;
}
}
this._eventEmitter.emitAsync(constants_1.VideoEvent.STATE_CHANGED, {
prevState: this._currentState,
nextState: state,
});
this._eventEmitter.emitAsync(state);
this._currentState = state;
};
Object.defineProperty(StateEngine.prototype, "isMetadataLoaded", {
get: function () {
return this._isMetadataLoaded;
},
enumerable: false,
configurable: true
});
Object.defineProperty(StateEngine.prototype, "state", {
get: function () {
return this._currentState;
},
enumerable: false,
configurable: true
});
StateEngine.prototype.destroy = function () {
this._unbindEvents();
};
return StateEngine;
}());
exports.default = StateEngine;
//# sourceMappingURL=state-engine.js.map