define('application/decorators/player/livemanipulation', [
'antie/runtimecontext',
'rofl/lib/l10n',
'application/managers/player',
'application/managers/recording',
'rofl/lib/utils',
'application/managers/feature',
'rofl/analytics/web/google',
'application/constants',
'application/utils',
'application/managers/progress'
], function (
RuntimeContext,
L10N,
PlayerManager,
RecordingManager,
Utils,
FeatureManager,
GoogleAnalytics,
Constants,
AppUtils
) {
'use strict';
var application = RuntimeContext.getCurrentApplication(),
recordingManager = RecordingManager.getInstance(),
featureManager = FeatureManager.getInstance(),
GA = GoogleAnalytics.getInstance(),
l10n = L10N.getInstance();
return {
/**
* Pauses the player.
*
* @private
*/
_onPause: function () {
if (!this.playerInterface.isPlaying()) {
return;
}
// Focus on play/pause button.
this._view.focus();
this._view.onPause();
this.playerInterface.pause();
this._sendPauseAnalytics();
},
/**
* Plays the player.
*
* @private
*/
_onPlay: function () {
if (!this.playerInterface.isPaused()) {
return;
}
this._view.onPlay();
if (this._seeker.isActive()) {
this._seeker.confirm();
this._sendTrickplayAnalytics();
} else {
if (this._type === Constants.LIVE_VIDEO_TYPE) {
this._delayedStreamTime = this._pauseTime;
// LIVE video was paused, request startover with media player's current time.
this._onRestart(this.playerInterface.getCurrentTime());
} else {
// RESTART video was paused, resume playback.
this.playerInterface.resume();
}
}
GA.onEvent(
Constants.ANALYTICS_EVENT_CATEGORY_ACTION,
Constants.ANALYTICS_EVENT_ACTION_PLAY_VIDEO,
{
eventLabel: AppUtils.getAnalyticsEventLabel(this._type)
}
);
},
/**
* Plays or Pauses the video, depending on the current state.
*
* @private
*/
_onPlayPause: function () {
if (this.playerInterface.isPlaying()) {
this._onPause();
} else if (this.playerInterface.isPaused()) {
this._onPlay();
}
},
/**
* Prepares playback of live broadcast.
*/
_onLive: function () {
this._stopProgressTimeouts();
this._view.resetControls();
application.showLoader();
this._preparePlayer({
data: this._program,
type: Constants.LIVE_VIDEO_TYPE
});
this._view.focus();
},
/**
* Function solves selecting restart button.
*
* @param {number} [startTime] - The restart start time.
* @private
*/
_onRestart: function (startTime) {
var isRestart = this._type === Constants.RESTART_VIDEO_TYPE;
if (this.playerInterface.isPaused() ||
this.playerInterface.isPlaying() && this._playbackStatus.active) {
if (isRestart) {
this.playerInterface.seek(0);
} else {
// Stop the live and Restart progress.
this._stopProgressTimeouts();
this._view.resetControls();
application.showLoader();
this._preparePlayer({
data: this._program,
startTime: startTime,
type: Constants.RESTART_VIDEO_TYPE
});
}
GA.onEvent(
Constants.ANALYTICS_EVENT_CATEGORY_ACTION,
Constants.ANALYTICS_EVENT_ACTION_STARTOVER
);
}
},
/**
* Attempts to rewind the video.
*
* @private
*/
_onRewind: function () {
if (this.playerInterface.isPaused() ||
this.playerInterface.isPlaying() && this._playbackStatus.active) {
if (!PlayerManager.isTrickplayEnabled()) {
this._showSeekingNotSupportedMessage();
return;
}
if (!this._canRewind()) {
this._showSeekingProhibitedMessage();
return;
}
this._seeking = Constants.PLAYER_SEEK_DIRECTION_BACKWARD;
// Stop progress timeouts before starting fast forward.
this._stopProgressTimeouts();
this._seeker.rewind();
}
},
/**
* Gets executed when the speed changes.
*
* @param {number} speed - The speed.
* @private
*/
_onSpeedChanged: function (speed) {
this._seekSpeed = speed;
if (speed) {
this._view.updateSeekSpeed(speed);
}
},
/**
* Attempts to fast forward the video.
*
* @private
*/
_onFastForward: function () {
if (this.playerInterface.isPaused() ||
this.playerInterface.isPlaying() && this._playbackStatus.active) {
if (!PlayerManager.isTrickplayEnabled()) {
this._showSeekingNotSupportedMessage();
return;
}
if (!this._canFastForward()) {
this._showSeekingProhibitedMessage();
return;
}
this._seeking = Constants.PLAYER_SEEK_DIRECTION_FORWARD;
this._view.setProgressMaxPointerPosition();
// Stop progress timeouts before starting fast forward.
this._stopProgressTimeouts();
this._seeker.fastForward();
}
},
/**
* Stops restart and live progress timeouts.
*
* @private
*/
_stopProgressTimeouts: function () {
this._stopRestartProgressTimeout();
this._stopLiveProgressTimeout();
},
/**
* Stops the live progress timeout.
*
* @private
*/
_stopLiveProgressTimeout: function () {
clearInterval(this._liveProgressInterval);
},
/**
* Stops the replay progress timeout.
*
* @private
*/
_stopRestartProgressTimeout: function () {
clearInterval(this._liveProgressInterval);
},
/**
* Function solves selecting record button.
*
* @private
*/
_onRecord: function () {
var program = this._program,
view = this._view,
config = {
text: l10n.get('player.warningbox.recording'),
icon: 'icon-alert-v2'
},
hasRecording = recordingManager.hasRecording(program.getId(), program.getSeriesId()),
flow = hasRecording.episode || hasRecording.series ? 'delete' : 'default';
if (featureManager.isRecordingEnabled()) {
if (hasRecording.episode || hasRecording.series) {
// Deleting of recordings only allowed from recording section.
view.showWarningBox({
happy: true,
icon: 'icon-check-v2',
text: l10n.get('player.warningbox.alreadyrecording')
});
} else {
if (program && program.canRecord()) {
this._view.hideUI({
skipAnim: true
});
application.route('record', {
item: program,
callingComponent: 'player',
callback: Utils.bind(this._onRecordCallback, this),
flow: flow
});
}
}
} else {
view.showWarningBox(config);
}
},
/**
* Returns true if the stream can be fast forwarded.
*
* @returns {boolean} - True if the stream can be fast forwarded.
* @private
*/
_canFastForward: function () {
var trickplaySettings = PlayerManager.getTrickplaySettings(),
maxSeekTime = trickplaySettings.maxSeekValue,
startTime = trickplaySettings.startTime * 1000,
livePosition = trickplaySettings.currentLivePosition - startTime;
if (!PlayerManager.isTrickplayEnabled()) {
return false;
}
if (!this._program.canSeek()) {
if (!this._pauseTime) {
return false;
}
return livePosition < maxSeekTime * 1000;
}
return true;
},
/**
* Shows menu.
*
* @private
*/
_onShownMenu: function () {
this._view.closeExpandedContents();
this._view.hideUI({
skipAnim: true
});
application.focusMenu('player');
},
/**
* Shows or hides current program's info.
*
* @param {boolean} show - Flag to show or hide program info.
* @param {Object} programDetails - Program info details.
* @private
*/
_onInfo: function (show, programDetails) {
GA.onEvent(
Constants.ANALYTICS_EVENT_CATEGORY_ACTION,
Constants.ANALYTICS_EVENT_ACTION_OPEN_DETAILS,
{
eventLabel: AppUtils.getAnalyticsEventLabel(this._type)
}
);
this._view.showUI(true);
this._view.showProgramInfo(show, programDetails);
},
/**
* Shows or hides the miniEPG.
*/
_onMiniEPG: function () {
this._view.showUI(true);
this._view.showMiniEPG(false);
this._view.getMiniEPG().focus();
},
/**
* On mini epg program selected.
*
* @param {Object} channel - The selected program's channel to switch.
* @private
*/
_onMiniEPGProgram: function (channel) {
this._view.focus();
this._view.closeExpandedContents();
this._zapToChannel(channel);
GA.onEvent(
Constants.ANALYTICS_EVENT_CATEGORY_ACTION,
Constants.ANALYTICS_EVENT_ACTION_MINIEPG_PROGRAM,
{
eventLabel: Constants.ANALYTICS_EVENT_LABEL_TYPE_LIVETV
});
},
/**
* Cancel mini epg selection after childlock esceped or cancelled.
*
* @private
*/
_onMiniEPGCancelled: function () {
this._view.focus();
this._view.getMiniEPG().focus();
},
/**
* Returns true if the stream can be rewound.
*
* @returns {boolean} - True if the stream can be rewound.
* @private
*/
_canRewind: function () {
return PlayerManager.isTrickplayEnabled();
},
/**
* Shows the seeking prohibited message.
*
* @private
*/
_showSeekingProhibitedMessage: function () {
var config = {
text: l10n.get('player.warningbox.seek'),
icon: 'icon-alert-v2'
};
this._view.showWarningBox(config);
},
/**
* Shows the seeking not supported message.
*
* @private
*/
_showSeekingNotSupportedMessage: function () {
var config = {
text: l10n.get('player.warningbox.liveonseek'),
icon: 'icon-alert-v2'
};
this._view.showWarningBox(config);
},
/**
* The record callback.
*
* @param {Object} e - The record callback.
* @private
*/
_onRecordCallback: function (e) {
var config = {
happy: true,
icon: 'icon-check-v2'
},
hasRecording = recordingManager.hasRecording(e.item.getId(), e.item.getSeriesId());
if (e.removed) {
if (e.item.getEndTime() * 1000 > application.getDate()) {
// Future item gets canceled.
config.text = l10n.get('recordings.notification.cancelled', {item: e.item.getTitle()});
} else {
// Old items get removed.
config.text = l10n.get('recordings.notification.removed', {item: e.item.getTitle()});
}
if (hasRecording.episode || hasRecording.series) {
this._view.onRecording();
} else {
this._view.onRecord();
}
} else {
config.text = l10n.get('recordings.notification.successful.' + e.type, {series: e.item.getTitle()});
this._view.onRecording();
}
this._view.showWarningBox(config);
},
/**
* Shows the program is already recorded message.
*
* @param {Object} item - The item.
* @private
*/
_showProgramAlreadyRecorded: function (item) {
var config = {
icon: 'icon-alert-v2',
text: l10n.get('recordings.notification.recording', {
series: item.getTitle()
})
};
this._view.showWarningBox(config);
},
/**
* Shows the program can not be recorded message.
*
* @param {Object} item - The item.
* @private
*/
_showProgramNotRecordable: function (item) {
var config = {
icon: 'icon-alert-v2',
text: l10n.get('recordings.notification.not_recordable', {
series: item.getTitle()
})
};
this._view.showWarningBox(config);
},
/**
* Gets executed when the current time changes.
*
* @param {number|Object} data - The seek data.
* @private
*/
_onCurrentTimeChanged: function (data) {
if (!this._seeker.isActive()) {
return;
}
this._onSeekCurrentTime(data);
}
};
});