define('application/components/players/vod', [
'application/components/player',
'application/decorators/player/interfaces/playerinterface',
'application/helpers/playerproperties',
'application/helpers/drmconfig',
'application/views/player/vod',
'rofl/lib/utils',
'application/utils',
'application/managers/api',
'application/constants',
'antie/runtimecontext',
'application/events/bingewatchevent',
'application/events/nextepisodeevent',
'product-layer/player/widgets/seeker',
'application/managers/player'
], function (
Component,
AppCorePlaybackInterface,
PlayerProperties,
DRMConfig,
VODView,
Utils,
AppUtils,
ApiManager,
Constants,
RuntimeContext,
BingeWatchEvent,
NextEpisodeEvent,
Seeker,
PlayerManager
) {
'use strict';
var api = ApiManager.getKPNAPI(),
application = RuntimeContext.getCurrentApplication(),
configuration = application.getConfiguration();
return Component.extend({
/**
* Initializes component.
*/
init: function init () {
init.base.call(this);
},
/**
* BeforeShow event.
*
* @param {Object} e - The event data.
*/
onBeforeShow: function onBeforeShow (e) {
var args = e.args;
this._bingewatch = this._nextEpisodes = args.bingewatch || [];
onBeforeShow.base.call(this, e);
},
/**
* Sets the view for the player.
*
* @private
*/
_setView: function () {
this._view = new VODView({
mouseOverHandler: Utils.bind(function () {
if (this._view.supportsPointer()) {
this._showUI();
}
}, this)
});
this.appendChildWidget(this._view);
},
/**
* Prepares playback: Checks parental or start requesting bookmarks and program data to request and play stream.
*
* @param {Object} playbackData - The playback content data.
* @private
*/
_preparePlayback: function (playbackData) {
// This will set program with 0 startTime, after receving the bookmark the position is set to it.
this._setProgram(playbackData.data);
if (AppUtils.isBroadcastLocked(playbackData.data)) {
application.hideLoader();
this._checkingParental = true;
this.playerInterface.unload();
this._playbackStatus.active = false;
this._view.hideUI();
if (this.isFocussed()) {
this._showParental({
successCallback: Utils.bind(this._onParentalSuccess, this, playbackData),
errorCallback: Utils.bind(this._onPlayerError, this),
escapeCallback: Utils.bind(this._onBack, this)
});
}
} else {
this._requestBookmark(playbackData)
.then(Utils.bind(this._setProgram, this, playbackData.data))
.then(Utils.bind(this._requestStream, this, playbackData))
.then(Utils.bind(this._startPlayback, this))
['catch'](Utils.bind(this._onPlayerError, this));
}
},
/**
* Requests bookmark data for the given playback content data.
*
* @param {Object} playbackData - The playback content data.
* @returns {Promise} - The userdata resolved promise.
* @private
*/
_requestBookmark: function (playbackData) {
return api.read('userdata', {
params: playbackData,
withCredentials: true
})
.then(Utils.bind(this._onRequestBookmark, this, playbackData));
},
/**
* Sets the bookmark.
*
* @param {Object} playbackData - The playback content data.
* @param {Object} data - Bookmark data.
* @private
*/
_onRequestBookmark: function (playbackData, data) {
// Check for empty assetId and set bookmarkTime.
playbackData.data = AppUtils.checkForEmptyAsset(playbackData.data, data);
this._bookmarkTime = this.bookmarkManager.parsedBookmarkTime(data);
},
/**
* Requests the content's stream data.
*
* @param {Object} playbackData - Playback content data.
* @returns {Object} - Stream data.
*/
_requestStream: function (playbackData) {
var program = playbackData.data;
return api.read('streams/vod', {
params: playbackData,
withCredentials: true,
headers: this.getStreamHeaders(program)
});
},
/**
* Prepares the player properties and attempts to start playback.
*
* @param {Object} data - Contains the stream data.
* @private
*/
_startPlayback: function _startPlayback (data) {
var properties = new PlayerProperties({
source: {
src: data.url,
mimeType: data.mimeType || PlayerProperties.MIME_TYPES.mpd
},
async: true,
autoplay: true,
startTime: this._startTime,
drmConfig: new DRMConfig({
type: DRMConfig.TYPES.PLAYREADY,
options: {
licenseServer: data.licenseUrl
}
})
});
_startPlayback.base.call(this, properties);
this._bingewatchActive = false;
},
/**
* Requests the content's stream data.
*
* @param {Object} program - The requested program.
*/
_setProgram: function (program) {
this._program = program;
this._startTime = this._bookmarkTime || 0;
this._endTime = new Date(program.getEndTime() * 1000);
this._contentId = program.getId();
this._type = AppUtils.getContentVideoType(program.getContentType(), program.getContentSubtype());
this._view.setProgramInfoButton(program.getDetailsAction());
this._view.setNextEpisodeButton(!!this._nextEpisodes.length);
this._view.setProgram(program);
this._setProgress({
duration: program.getDuration(),
currentTime: this._startTime,
percentage: (this._startTime / program.getDuration()) * 100
});
this._buildSeeker();
},
/**
* Parental pin success callback.
*
* @param {Object} playbackData - Playback content data.
* @private
*/
_onParentalSuccess: function (playbackData) {
// Update Program info.
this._preparePlayback(playbackData);
},
/**
* On before hide event.
*/
onBeforeHide: function () {
this.playerInterface.unload();
},
/**
* Select event.
*
* @param {Object} e - The event data.
* @private
*/
_onSelect: function _onSelect (e) {
var target = e.target,
episode;
if (this._view.isUIVisible()) {
switch (target.id) {
case VODView.CONTROLS.INFO:
case VODView.CONTROLS.MENU:
case VODView.CONTROLS.PLAYPAUSE:
case VODView.CONTROLS.REWIND:
case VODView.CONTROLS.FORWARD:
case VODView.CONTROLS.RESTART:
// Falls through common actions
_onSelect.base.call(this, e);
break;
case VODView.CONTROLS.NEXT:
if (!this._mediaChangeInProgress) {
episode = this._nextEpisodes.splice(0, 1)[0];
application.broadcastEvent(new NextEpisodeEvent(episode));
this._onNextEpisode(episode);
}
this._view.closeExpandedContents();
break;
case VODView.CONTROLS.BACK:
this._view.closeExpandedContents();
this._onBack();
break;
case VODView.CONTROLS.LIVE:
this._onLive();
break;
}
} else {
this._view.showUI();
}
},
/**
* Launches bingewatching overlay.
*/
_launchBingeWatch: function () {
this._bingewatchActive = true;
this._view.hideUI({
skipAnim: true
});
application.route('bingewatching', {
episode: this._bingewatch.splice(0, 1)[0],
successCallback: Utils.bind(this._onBingeWatch, this),
cancelCallback: Utils.bind(this._onCancelBingeWatch, this)
});
},
/**
* Bingewatch callback.
*
* @param {Object} episode - The episode to watch.
* @private
*/
_onBingeWatch: function (episode) {
application.broadcastEvent(new BingeWatchEvent(episode));
this._view.closeExpandedContents();
application.showLoader(true);
this._preparePlayer({
data: episode,
bingewatch: this._bingewatch,
callingPage: this._callingPage,
analyticsType: this._analyticsType,
type: this._type
});
},
/**
* Cancels bingewatch callback.
*
* @private
*/
_onCancelBingeWatch: function () {
this._onBack();
},
/**
* PlayerEvent.
*
* @param {Object} e - The player event data.
* @private
*/
onPlayerEvent: function onPlayerEvent (e) {
switch (e.type) {
case this.MEDIA_PLAYER_EVENTS.ERROR:
case this.MEDIA_PLAYER_EVENTS.BITRATE_CHANGED:
onPlayerEvent.base.call(this, e);
break;
case this.MEDIA_PLAYER_EVENTS.STATUS:
if (this._currentProgram === this._program) {
this._setProgress(e);
application.hideLoader();
if (!this._playbackStatus.active) {
if (!this._bingewatchActive) {
this._view.showUI();
}
this._playbackStatus.active = true;
}
}
break;
case this.MEDIA_PLAYER_EVENTS.PLAYING:
this.bookmarkManager.onPlayStart(this._contentId, this._type);
onPlayerEvent.base.call(this, e);
break;
case this.MEDIA_PLAYER_EVENTS.PAUSED:
onPlayerEvent.base.call(this, e);
break;
case this.MEDIA_PLAYER_EVENTS.COMPLETE:
if (!this._bingewatchActive) {
this._onBack();
}
break;
}
},
/**
* VOD Mouse Seek event.
*
* @param {Object} e - The event data.
* @param {number} e.percentage - The seek percentage.
* @param {boolean} e.finished - True if the mouse seek event has finished.
* @private
*/
_onMouseSeek: function (e) {
if (this.playerInterface.isPlaying()) {
this.playerInterface.pause();
}
if (e.finished) {
this.playerInterface.seek((this.playerInterface.getDuration() / 100) * e.percentage);
}
},
/**
* Updates the progress view and checks for bingewatching activation.
*
* @param {Object} e - Object that contains a player event..
* @private
*/
_setProgress: function (e) {
var duration = Math.floor(e.duration),
currentTime = Math.floor(e.currentTime),
percentage = (e.currentTime / e.duration) * 100;
this._view.setProgress({
duration: duration,
currentTime: currentTime,
percentage: percentage
});
if (this._bingewatch.length
&& !this._bingewatchActive
&& currentTime >= duration - 5) {
this._launchBingeWatch();
}
},
/**
*
*
* @param {number} time - The current seek time.
* @private
*/
_onSeekCurrentTime: function (time) {
var duration = this.playerInterface.getDuration(),
maxTime = PlayerManager.getMaxSeekValue();
this._seekCurrentTime = time;
if (!this._program.canSeek() && this._seekSpeed > 0 && time >= maxTime) {
this._seeker.confirm(maxTime);
time = maxTime;
}
if (time <= 0) {
this._seeker.confirm();
} else if (time >= duration) {
this._seeker.confirm(duration - 5);
}
this._setProgress({
currentTime: time,
duration: duration
});
},
/**
* Gets executed when the seek is confirmed.
*
* @private
*/
_onSeek: function () {
this._seekSpeed = null;
this._seekCurrentTime = null;
this._view.resetControls();
this._view.setProgressMaxPointerPosition();
},
/**
* Checks the bookmark threshold so bookmark can be stored.
*/
storeBookmark: function () {
var currentTime = this.playerInterface.getCurrentTime(),
duration = this.playerInterface.getDuration();
if (currentTime / duration < configuration.BOOKMARK_THRESHOLD) {
this.bookmarkManager.onStop(null, currentTime);
} else {
this.bookmarkManager.onStop(null, 0);
}
},
/**
* On back action.
*
* @private
*/
_onBack: function _onBack () {
this._view.hideUI({
skipAnim: true
});
this._view.resetControls();
this.storeBookmark();
this.playerInterface.destroy();
_onBack.base.call(this);
this._playbackStatus.active = false;
this._bingewatchActive = false;
},
/**
* Close player.
*/
closePlayer: function closePlayer () {
this._view.hideUI({
skipAnim: true
});
this._view.resetControls();
this.storeBookmark();
this.playerInterface.destroy();
closePlayer.base.call(this);
this._playbackStatus.active = false;
this._bingewatchActive = false;
}
});
});