import Audio from './audio';
import Subtitle from './subtitle';
import Logger from '../service/logger';
import Vast from '../service/vast';
class Player {
/**
* This is for Player operations. It depends to Device. Some methods are abstracted by Devices
*
* @param {Object} currentDevice - Current device object
* @param {Object} events - Events class inheritance
* @param {Object} config - Config object
*
* @class Player
* @constructor
*/
constructor(currentDevice, events, config) {
this.currentDevice = currentDevice;
this.Events = events;
Logger.addLog('Player', 'create', 'Player Class Initialized');
this.Config = config;
}
/**
* Creates Video element. It creates a HTML5 video element with config videoPlayerId
* Then you can reach this video element with this.videoElement
* It appends this video element to body. You have to set it to a fixed position with css.
* Most of Tv manufacturers runs its own video player and its position fixed to (0,0) cooridnates
* Its important to consider your design
*
* @method createVideoElement
* @for Player
* @return null
*/
createVideoElement() {
if (this.videoElement) {
this.deleteVideoElement();
}
this.videoElement = document.createElement('video');
this.videoElement.style.position = 'absolute';
this.videoElement.setAttribute('class', 'player');
this.videoElement.setAttribute('id', 'dtv-video');
document.body.appendChild(this.videoElement);
this.registerVideoEvents();
Logger.addLog('Player', 'info', 'Player Element Created and Registered Video Events');
return null;
}
/**
* Sets this.playerInfo with initial values. This values usefull for later usages
* For example Vast, device specific, DRM Type etc we are using this object
*
* @for Player
* @method setPlayerInfo
* @return {Object} this.playerInfo
*/
setPlayerInfo() {
this.playerInfo = {
canPlay: false,
canPlayThrough: false,
playbackRate: 1,
duration: null,
currentState: null,
dataLoaded: false,
metaDataLoaded: false,
isSeeking: false,
isStalled: false,
currentVolume: this.videoElement.volume,
customData: null,
drmType: null,
drmOrganizer: null,
src: null,
adsEnabled: false,
adsType: null,
subtitleEnabled: false
};
return this.playerInfo;
}
/**
* Removes videoElement from DOM.
* Its recommended to call this function if you are consider to close video
* TODO We have to check DRM inited if yes we have to detach DRM before removing
*
* @for Player
* @method deleteVideoElement
* @return {Boolean}
*/
deleteVideoElement() {
this.pause();
document.body.removeChild(this.videoElement);
this.videoElement = false;
return true;
}
/**
* Adds video source to element.
* If trying to play DRM video you have to send customData with video source
* It sets this customData to player info so it can be accessible.
* Checks content address if it includes manifest regex it will start DRM functions automatically
* It catches DRM providers with currentDevice
* You can send HLS, Live HLS and Microsoft SS (PlayReady) content
* TODO DRM providers can be included in another function
*
* @param {String} src - Source url for video content
* @param {String} customData - Custom Data
*
* @for Player
* @method addVideoSource
*
*/
addVideoSource(src, customData) {
this.autoLoop = false;
// this.Events.removeAllListeners();
this.playerInfo.customData = customData;
this.playerInfo.src = src;
const _this = this;
if (src.match(/\/manifest/i)) {
if (this.currentDevice.brandName === 'webos') {
this.playerInfo.drmType = 'playready';
} else {
this.playerInfo.drmType = 'playReady';
}
switch (this.playerInfo.drmOrganizer) {
case 'OIPF': // eslint-disable-line
Logger.addLog('Player', 'info', `Found playReady Content & drmType is ${this.playerInfo.drmType}`);
this.createOIPFDrmAgent();
const oipfMessage = '<?xml version="1.0" encoding="utf-8"?>' +
'<PlayReadyInitiator xmlns="http://schemas.microsoft.com/DRM/2007/03/protocols/">' +
'<SetCustomData><CustomData>dummy</CustomData></SetCustomData></PlayReadyInitiator>';
const mimeType = this.Config.playReady.mimeType;
const DRMSystemID = this.Config.playReady.DRMSystemID;
this.OIPFDrmObject.sendDRMMessage(mimeType, oipfMessage, DRMSystemID);
this.videoElement.setAttribute('src', this.playerInfo.src);
break;
case 'TIZEN':
console.log('TIZEN');
break;
case 'WEBOS':
this.setupWebOSDrm();
this.Events.addListener('DRM_WebOSReady', () => {
_this.sourceElement = document.createElement('source');
_this.sourceElement.setAttribute('src', _this.playerInfo.src);
_this.sourceElement.setAttribute('type', `application/vnd.ms-sstr+xml;mediaOption=${_this._WebOS.mediaOption}`);
_this.videoElement.appendChild(_this.sourceElement);
document.body.setAttribute('onunload', _this.unloadDrmClient);
});
break;
default:
console.log('STANDART');
}
} else {
Logger.addLog('Player', 'info', 'This is a DRM-Free Content');
// _this.sourceElement = document.createElement('source');
// _this.sourceElement.setAttribute('src', _this.playerInfo.src);
// _this.videoElement.appendChild(_this.sourceElement);
this.videoElement.setAttribute('src', _this.playerInfo.src);
}
}
/**
* Initialize ads with given source and type. So type is mandatory field to operate
*
* @param {String} type - Type of ads source 'VMAP' or just 'VAST'
* @param url - Url of ads source VMAP or VAST Url
*
* @for Player
* @method initAds
* @return {*}
*/
initAds(type, url) {
const _this = this;
_this.playerInfo.adsType = type;
_this.playerInfo.adsEnabled = true;
switch (type) {
case 'VMAP': // eslint-disable-line
const xhr = new window.XMLHttpRequest();
xhr.open('GET', url);
xhr.send();
_this.Events.on('vmapLoaded', (vmapObject) => {
_this.prepareVastFromVmap(vmapObject);
});
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Parse VMAP
Vast.parseVMAP(xhr.responseXML, _this.Events);
Logger.addLog('Player - ADS', 'info', 'VMAP Target Loaded Successfully');
_this.addAdsCaption();
}
};
break;
case 'VAST':
console.log('VAST');
break;
default:
return Logger.addLog('Player - Ads', 'error', '');
}
}
/**
* If ads type is VMAP and detected in initAds method it will call automatically this function
*
* @param {Object} vmapObject - Vmap object its response of VMAP XML
*
* @for Player
* @method prepareVastFromVmap
*/
prepareVastFromVmap(vmapObject) {
// Create Wrapper Div
this.wrapperDiv = document.createElement('div');
this.wrapperDiv.className = 'vastWrapper';
this.wrapperDiv.id = `vastWrapper_${this.Config.videoPlayerId}`;
this.videoElement.parentNode.insertBefore(this.wrapperDiv, this.videoElement);
this.wrapperDiv.appendChild(this.videoElement);
this.vastElement = this.videoElement.cloneNode(true);
this.vastElement.id = 'vast-player';
this.vastElement.style.visibility = 'hidden';
// this.vastElement.childNodes[0].src = '';
this.vastElement.src = '';
this.wrapperDiv.appendChild(this.vastElement);
this.vastTrackElement = document.createElement('img');
this.vastTrackElement.setAttribute('src', 'deneme');
document.body.appendChild(this.vastTrackElement);
this.vastReadyItems = [];
this.adsInProgress = false;
for (let i = 0; i < vmapObject.length; i += 1) {
this.vastReadyItems.push(this.readVastFile(vmapObject[i].url, this.Config.vastOptions));
}
for (let j = 0; j < Vast.vastArray.length; j += 1) {
if (Vast.vastArray[j].time === 'end') {
Vast.vastArray[j].time = (Math.floor(this.videoElement.duration) - 1);
}
}
}
/**
* Reads Vast file and seperates its source and options (extensions, type etc)
*
* @param {String} vastUrl - URL address for Vast
* @param {Object} options - It stands for this.config.vastOptions
* @for Player
* @method readVastFile
* @return {{}}
*/
readVastFile(vastUrl, options) { // eslint-disable-line
// Read XML file
let xmlHttpReq;
let xmlDoc;
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
} else {
xmlHttpReq = new ActiveXObject('Microsoft.XMLHTTP'); // eslint-disable-line
}
xmlHttpReq.open('GET', vastUrl, false);
xmlHttpReq.send();
xmlDoc = xmlHttpReq.responseXML; // eslint-disable-line
const vastObj = {};
// Get impression tag
const impression = xmlDoc.getElementsByTagName('Impression');
if (impression != null) {
// obj_vast.impression_url = impression[0].childNodes[0].nodeValue;
vastObj.impression = impression;
// alert(obj_vast.impression_url);
}
// Get Creative
const creative = xmlDoc.getElementsByTagName('Creative');
let mediaFiles;
let trackingEvents;
for (let i = 0; i < creative.length; i += 1) {
const creativeLinear = creative[i].getElementsByTagName('Linear');
if (creativeLinear != null) {
for (let j = 0; j < creativeLinear.length; j += 1) {
// Get media files
const creativeLinearMediaFiles = creativeLinear[j].getElementsByTagName('MediaFiles');
if (creativeLinearMediaFiles != null) {
for (let k = 0; k < creativeLinearMediaFiles.length; k += 1) {
const creativeLinearMediaFile = creativeLinearMediaFiles[k].getElementsByTagName('MediaFile');
if (creativeLinearMediaFile != null) {
mediaFiles = creativeLinearMediaFile;
}
}
}
// Get Clickthrough URL
const creativeLinearVideoClicks = creativeLinear[j].getElementsByTagName('VideoClicks');
if (creativeLinearVideoClicks != null) {
for (let k = 0; k < creativeLinearVideoClicks.length; k += 1) {
const creativeLineartVClicksClickthrough = creativeLinearVideoClicks[k].getElementsByTagName('ClickThrough')[0].childNodes[0].nodeValue;
const creativeLineartVClicksClickthroughTracking = creativeLinearVideoClicks[k].getElementsByTagName('ClickTracking');
if (creativeLineartVClicksClickthrough != null) {
vastObj.clickthroughUrl = creativeLineartVClicksClickthrough;
}
if (creativeLineartVClicksClickthroughTracking != null) {
vastObj.clickthroughTracking = creativeLineartVClicksClickthroughTracking;
}
}
}
// Get Tracking Events
const creativeLinearTrackingEvents = creativeLinear[j].getElementsByTagName('TrackingEvents');
if (creativeLinearTrackingEvents != null) {
for (let k = 0; k < creativeLinearTrackingEvents.length; k += 1) {
const creativeLinearTrackingEventsTracking = creativeLinearTrackingEvents[k].getElementsByTagName('Tracking');
if (creativeLinearTrackingEventsTracking != null) {
trackingEvents = creativeLinearTrackingEventsTracking;
}
}
}
// Get AD Duration
const creativeLinearDuration = creativeLinear[j].getElementsByTagName('Duration')[0];
if (creativeLinearDuration != null) {
vastObj.duration = creativeLinearDuration.childNodes[0].nodeValue;
// alert(obj_vast.duration);
const arrD = vastObj.duration.split(':');
const strSecs = (+arrD[0]) * 60 * 60 + (+arrD[1]) * 60 + (+arrD[2]);
vastObj.duration = strSecs;
}
}
}
}
if (typeof mediaFiles !== 'undefined') {
for (let i = 0; i < mediaFiles.length; i += 1) {
if (mediaFiles[i].getAttribute('type') === options.media_type) {
if ((mediaFiles[i].getAttribute('bitrate') > options.media_bitrate_min) && (mediaFiles[i].getAttribute('bitrate') < options.media_bitrate_max)) {
vastObj.mediaFile = mediaFiles[i].childNodes[0].nodeValue;
}
}
}
}
if (typeof trackingEvents !== 'undefined') {
for (let i = 0; i < trackingEvents.length; i += 1) {
if (trackingEvents[i].getAttribute('event') === 'start') {
if (vastObj.trackingStart != null) {
vastObj.trackingStart += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingStart = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingStartTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'firstQuartile') {
if (vastObj.trackingFirstQuartile != null) {
vastObj.trackingFirstQuartile += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingFirstQuartile = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.tracking_first_quartile_tracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'midpoint') {
if (vastObj.trackingMidpoint != null) {
vastObj.trackingMidpoint += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingMidpoint = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingMidpointTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'thirdQuartile') {
if (vastObj.trackingThirdQuartile != null) {
vastObj.trackingThirdQuartile += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingThirdQuartile = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingThirdQuartileTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'complete') {
if (vastObj.trackingComplete != null) {
vastObj.trackingComplete += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingComplete = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingCompleteTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'mute') {
if (vastObj.trackingMute != null) {
vastObj.trackingMute += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingMute = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingMuteTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'unmute') {
if (vastObj.trackingUnmute != null) {
vastObj.trackingUnmute += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingUnmute = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingUnmuteTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'pause') {
if (vastObj.trackingPause != null) {
vastObj.trackingPause += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingPause = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingPauseTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'resume') {
if (vastObj.trackingResume != null) {
vastObj.trackingResume += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingResume = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingResumeTracked = false;
}
if (trackingEvents[i].getAttribute('event') === 'fullscreen') {
if (vastObj.trackingFullscreen != null) {
vastObj.trackingFullscreen += ` ${trackingEvents[i].childNodes[0].nodeValue}`;
} else {
vastObj.trackingFullscreen = trackingEvents[i].childNodes[0].nodeValue;
}
vastObj.trackingFullscreenTracked = false;
}
}
}
// Tracking events
return vastObj;
}
/**
* This function is triggered with timeUpdate event of video player.
* It compares with Vast time with current time
*
* @for Player
* @method checkAdsStatus
*/
checkAdsStatus() {
if (!this.adsInProgress) {
// let currentTime = Math.floor(this.videoElement.currentTime);
if (this.videoElement.currentTime >= Vast.vastArray[0].time) {
this.adsInProgress = true;
this.pause();
this.initVastAd(this.videoElement.currentTime);
}
}
}
/**
* It starts ads in videoPlayer. Pauses current video then starting ads
* After completing ads it starts old src url with initial seeking with time
*
* @param time - current time of video player
* @for Player
* @method initVastAd
*/
initVastAd(time) {
const _this = this;
this.videoElement.src = '';
this.captionDiv.style.visibility = 'visible';
this.captionDiv.innerHTML = 'Reklamlar Yükleniyor';
this.vastElement.src = this.vastReadyItems[0].mediaFile;
this.vastElement.removeAttribute('controls');
this.vastElement.addEventListener('loadedmetadata', () => {
_this.videoElement.style.visibility = 'hidden';
_this.vastElement.style.visibility = 'visible';
_this.captionDiv.innerHTML = _this.Config.vastOptions.ad_caption;
console.log('Meta Data YüklenDi');
_this.vastElement.play();
});
this.vastElement.addEventListener('ended', () => {
console.log('Bitti');
_this.vastElement.style.visibility = 'hidden';
_this.videoElement.style.visibility = 'visible';
_this.captionDiv.style.visibility = 'hidden';
_this.adsInProgress = false;
_this.videoElement.src = _this.playerInfo.src;
_this.videoElement.currentTime = time;
_this.play();
});
this.vastElement.addEventListener('play', () => {
console.log('Reklam Başladı');
});
console.log(`init ettik${time}`);
Vast.vastArray.splice(0, 1);
_this.vastReadyItems.splice(0, 1);
}
/**
* Adds ads caption to video player to end user notified about Ads
* This text can be edited via config
*
* @return {boolean}
*
* @for Player
* @method addAdsCaption
*/
addAdsCaption() {
this.captionDiv = document.createElement('div');
this.captionDiv.className = 'vastCaption';
this.captionDiv.id = `vastCaption_${this.Config.videoPlayerId}`;
this.captionDiv.innerHTML = this.Config.vastOptions.ad_caption;
this.wrapperDiv.appendChild(this.captionDiv);
// Adjust style
this.captionDiv.style.left = `${(this.vastElement.offsetWidth / 2) - (document.getElementsByClassName('vastCaption')[0].offsetWidth / 2)}px`; this.captionDiv.style.visibility = 'hidden';
return true;
}
/**
* Unloads DRM client. !IMPORTANT! Some devices may be crash if you are not unloaded drm client
*
* @for Player
* @method unloadDrmClient
*/
unloadDrmClient() {
console.log('Unload Geldi');
const _this = this;
if (this.currentDevice.brandName === 'webos' && _this._WebOS.isDrmClientLoaded) {
webOS.service.request('luna://com.webos.service.drm', { // eslint-disable-line
method: 'unload',
parameters: { clientId: _this._WebOS.clientId },
onSuccess: (result) => {
_this._WebOS.isDrmClientLoaded = false;
console.log('DRM Client is unloaded successfully.');
},
onFailure: (result) => {
console.log(`[${result.errorCode}] ${result.errorText}`);
// Do something for error handling
}
});
}
}
/**
* Initialize WebOs DRM
* TODO This can be move to webos device with abstract
*
* @for Player
* @method setupWebOSDrm
*/
setupWebOSDrm() {
const _this = this;
_this._WebOS = {};
_this._WebOS.appId = 'com.dtv.smarttv';
_this._WebOS.clientId = '';
_this._WebOS.isDrmClientLoaded = '';
webOS.service.request('luna://com.webos.service.drm', { // eslint-disable-line
method: 'load',
parameters: {
drmType: _this.playerInfo.drmType,
appId: _this._WebOS.appId
},
onSuccess: (result) => {
_this._WebOS.clientId = result.clientId;
_this._WebOS.isDrmClientLoaded = true;
console.log('DRM Client is loaded successfully.');
_this.sendWebOSDrm();
},
onFailure: (result) => {
console.log(`[${result.errorCode}] ${result.errorText}`);
// Do something for error handling
}
});
}
/**
* WebOs Drm trigger
*
* @for Player
* @method sendWebOSDrm
*/
sendWebOSDrm() {
this._WebOS.msg = `<?xml version="1.0" encoding="utf-8"?>
<PlayReadyInitiator xmlns= "http://schemas.microsoft.com/DRM/2007/03/protocols/">
<LicenseAcquisition>
<Header><WRMHEADER xmlns= "http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0">
<DATA>
<PROTECTINFO>
<KEYLEN>16
</KEYLEN>
<ALGID>AESCTR</ALGID>
</PROTECTINFO>
<LA_URL>${this.Config.DRM.licenserUrl}</LA_URL>
<KID>lFmb2gxg0Cr5bfEnJXgJeA==</KID>
<CHECKSUM>P7ORpD2IpA==</CHECKSUM>
</DATA>
</WRMHEADER>
</Header>
<CustomData>${this.playerInfo.customData}</CustomData>
</LicenseAcquisition>
</PlayReadyInitiator>`;
const _this = this;
webOS.service.request('luna://com.webos.service.drm', { // eslint-disable-line
method: 'sendDrmMessage',
parameters: {
clientId: this._WebOS.clientId,
msgType: this.Config.DRM.mimeType,
msg: this._WebOS.msg,
drmSystemId: this.Config.DRM.drmSystemId
},
onSuccess: (result) => {
_this._WebOS.msgId = result.msgId;
_this._WebOS.resultCode = result.resultCode;
_this._WebOS.resultMsg = result.resultMsg;
console.log(`Message ID: ${_this._WebOS.msgId}`);
console.log(`[${_this._WebOS.resultCode}] ${_this._WebOS.resultMsg}`);
_this._WebOS.options = {};
_this._WebOS.options.option = {};
_this._WebOS.options.option.drm = {};
_this._WebOS.options.option.drm.type = _this.playerInfo.drmType;
_this._WebOS.options.option.drm.clientId = _this._WebOS.clientId;
_this._WebOS.mediaOption = escape(JSON.stringify(_this._WebOS.options));
_this.Events.triggerEvent('DRM_WebOSReady');
if (_this._WebOS.resultCode !== 0) {
// Do Handling DRM message error
}
},
onFailure: (result) => {
console.log(`[${result.errorCode}] ${result.errorText}`);
}
});
}
/**
* Constructor for Audio class
*
* @for Player
* @method initAudioClass
*/
initAudioClass() {
this.Audio = new Audio();
this.changeAudioWithOrder = this.Audio.changeAudioWithOrder;
this.getCurrentAudioWithOrder = this.Audio.getCurrentAudioWithOrder;
this.denemeSERDAR = this.Audio.getThis;
}
/**
* Add Subtitle Method
*
* @for Player
* @method initAudioClass
*/
addSubtitle(srt, targetElement) {
this.playerInfo.subtitleEnabled = true;
this.Subtitle = new Subtitle(srt, this, targetElement)
}
removeSubtitle() {
this.playerInfo.subtitleEnabled = false;
this.Subtitle = null;
}
/**
* Play trigger for videoElement
*
* @for Player
* @method play
*/
play() {
this.videoElement.play();
}
/**
* Stop trigger for videoElement
* it removes video element from dom
*
* @for Player
* @method stop
*/
stop() {
// this.videoElement.remove();
this.Events.removeAllListeners();
this.addVideoSource('');
}
/**
* Pause trigger for videoElement
*
* @for Player
* @method pause
*/
pause() {
this.videoElement.pause();
}
/**
* Play/Pause toggle trigger for videoElement
*
* @for Player
* @method togglePlay
*/
togglePlay() {
if (this.videoElement.paused) {
this.play();
} else {
this.pause();
}
}
/**
* Play trigger for a video element with endless autoloop
* you can use this feature to enable silent background videos
*
* @for Player
* @method playWithLoop
*/
playWithLoop() {
if (this.videoElement) {
this.autoLoop = true;
this.play();
}
}
/**
* Trigger specific events for all videoElement trigger
* @for Player
* @method registerVideoEvents
*/
registerVideoEvents() {
const _this = this;
this.videoElement.oncanplay = () => {
_this.playerInfo.canPlay = true;
_this.Events.triggerEvent('player_onCanPlay');
};
this.videoElement.oncanplaythrough = () => {
_this.playerInfo.canPlayThrough = true;
_this.Events.triggerEvent('player_onCanPlayThrough');
};
this.videoElement.ondurationchange = () => {
_this.Events.triggerEvent('player_onDurationChange', [Math.trunc(_this.videoElement.duration)]);
_this.playerInfo.duration = _this.videoElement.duration;
};
this.videoElement.onended = () => {
_this.playerInfo.currentState = 'Finished';
_this.Events.triggerEvent('player_onEnded', ['Video Finished']);
if(this.autoLoop) {
this.playWithLoop();
}
};
this.videoElement.onloadeddata = () => {
_this.Events.triggerEvent('player_onDataLoaded', ['Data Loaded']);
_this.playerInfo.dataLoaded = true;
};
this.videoElement.onloadedmetadata = () => {
_this.Events.triggerEvent('player_onMetaDataLoaded', ['Meta Data Loaded']);
_this.playerInfo.metaDataLoaded = true;
};
this.videoElement.onloadstart = () => {
_this.Events.triggerEvent('player_onLoadStart', ['Load Started']);
};
this.videoElement.onpause = () => {
_this.Events.triggerEvent('player_onPause', ['Pause']);
_this.playerInfo.currentState = 'Paused';
};
this.videoElement.onplay = () => {
_this.Events.triggerEvent('player_onPlay', ['Play']);
_this.playerInfo.currentState = 'Play';
};
this.videoElement.onplaying = () => {
_this.Events.triggerEvent('player_onPlaying', ['Playing']);
_this.playerInfo.currentState = 'Playing';
};
this.videoElement.progress = () => {
_this.Events.triggerEvent('player_onProgress', ['Downloading Video']);
};
this.videoElement.onratechange = () => {
_this.Events.triggerEvent('player_onRateChange', [_this.videoElement.playbackRate]);
_this.playerInfo.playbackRate = _this.videoElement.playbackRate;
};
this.videoElement.onseeked = () => {
_this.Events.triggerEvent('player_onSeeked', ['Seek Completed']);
_this.playerInfo.isSeeking = false;
};
this.videoElement.onseeking = () => {
_this.Events.triggerEvent('player_onSeeking', ['Seek In Progress']);
_this.playerInfo.isSeeking = true;
};
this.videoElement.ontimeupdate = () => {
_this.Events.triggerEvent('player_onTimeUpdate', [Math.trunc(_this.videoElement.currentTime)]);
if (_this.playerInfo.adsEnabled) {
_this.checkAdsStatus();
}
};
this.videoElement.onvolumechange = () => {
_this.Events.triggerEvent('player_onVolumeChange', [_this.videoElement.volume]);
_this.videoElement.currentVolume = _this.videoElement.volume;
};
this.videoElement.onwaiting = () => {
_this.Events.triggerEvent('player_onWaiting');
_this.playerInfo.currentState = 'Waiting';
};
}
/**
* Drm initiator for OIPF Devices such as Vestel and Arcelik
*
* @for Player
* @method createOIPFDrmAgent
*/
createOIPFDrmAgent() {
this.OIPFDrmObject = document.createElement('object');
this.OIPFDrmObject.setAttribute('type', 'application/oipfDrmAgent');
this.OIPFDrmObject.setAttribute('id', 'oipfDrm');
this.OIPFDrmObject.style.display = 'none';
document.head.appendChild(this.OIPFDrmObject);
this.OIPFDrmObject.onDRMMessageResult = function(msgId, resultMsg, resultCode) {
if (resultCode === 0) {
Logger.addLog('Player', 'create', `DRM Initialized Successfuly, Result Code = ${resultCode}!`);
} else {
switch (resultCode) {
case 1:
Logger.addLog('Player', 'error', 'Error Code : 1 / Unknown Error - ', HtmlEncode(resultMsg)); // eslint-disable-line no-undef
break;
case 2:
Logger.addLog('Player', 'error', 'Error Code : 2 / Cannot Process Result');
break;
case 3:
Logger.addLog('Player', 'error', 'Error Code : 3 / Unknown MIME Type');
break;
case 4:
Logger.addLog('Player', 'error', 'Error Code : 4 / User Consent Required');
break;
default:
Logger.addLog('Player', 'error', 'Error', resultCode);
break;
}
}
};
}
/**
* Seek with given value adding
*
* @param {Number} value
* @for Player
* @method seekWithTimeAdd
*/
seekWithTimeAdd(value) {
this.videoElement.currentTime += value;
}
/**
* Seek to given time
* TODO Check device performances if needed use pause method first
*
* @param value
*
* @for Player
* @method seekToTime
*/
seekToTime(value) {
this.videoElement.currentTime = value;
}
/**
* Sets currentTime to 0 and plays automatically
*
* @for Player
* @method restart
*/
restart() {
this.pause();
this.videoElement.currentTime = 0;
this.play();
}
}
export default Player;