angular.module("videoPlayer", [])
.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
// Allow same origin resource loads.
'self'
])
}).service('intranetDetect', function() {
var that = this;
that.nashost = undefined;
that.timer = undefined;
that.findGameInScope = function(scope) {
var game = undefined;
if (scope.game && scope.game.season) {
game = scope.game;
} else if (scope && scope.$parent) {
game = that.findGameInScope(scope.$parent);
}
return game;
};
}).directive('videoPlayer', function() {
return {
restrict: 'E',
replace: true,
scope: {
slId: '=',
slWidth: '=',
slHeight: '=',
showProgress: '=',
onProgressClick: '&',
playbackContext: '=',
setIsSeeking: '&',
registerVideoPlayer: '&'
},
template: '
',
controller: function ($scope, $timeout, $http, $filter, mixpanelAPI, intranetDetect) {
$scope.video = {
id : $scope.slId + '-video',
url : {
folder: '',
name: ''
},
duration: 0,
frameRate: 29.997,
speed : 1.0,
frameTracker : null,
startPosition : 0,
hls : null,
isHls : false
};
$scope.isSeeking = false;
$scope.onSeekedCallback = null;
$scope.durationPlaybackRunning = false;
$scope.cancelSeek = function() {
$scope.onSeekedCallback = null;
$scope.setIsSeekingInternal(false);
// We would need to do additional cleanup here to stop the browser from loading the remainder of the video. Not supported by HTML 5 video.
};
$scope.setIsSeekingInternal = function (isSeekingFlag) {
$scope.isSeeking = isSeekingFlag;
$scope.setIsSeeking({isSeekingFlag : isSeekingFlag});
}
$scope.setVideo = function (videoParams, startFramePosition) {
if ($scope.video.url.folder != videoParams.url.folder || $scope.video.url.name != videoParams.url.name) {
if ($scope.isSeeking) {
$scope.cancelSeek();
}
$scope.video.elem.off('seeked');
if ($scope.video.isHls) {
$scope.video.hls.detachMedia();
}
$scope.video.url.folder = videoParams.url.folder;
$scope.video.url.name = videoParams.url.name;
$scope.video.vidid = videoParams.vidid;
$scope.video.frameRate = videoParams.frameRate;
if (intranetDetect.nashost != undefined) {
var bucketRef = sportConfig.videosBucketPrefix;
try {
var game = intranetDetect.findGameInScope($scope);
if (game && game.season) {
var vidPeriod = $scope.video.vidid.split('-').pop() - 1;
videoParams.url.folder = game['periods'][vidPeriod]['video']['nasURL'] +'/'+ bucketRef + game.season.name +'/';
$scope.video.url.folder = videoParams.url.folder;
}
} catch (e) {
console.error('Could not load game for intranet detection', e);
}
}
var startPosition = -1;
if(typeof startFramePosition != 'undefined' && startFramePosition != -1){
startPosition = startFramePosition / $scope.video.frameRate;
}
if(new URL('x:' + videoParams.url.name).pathname.endsWith('.m3u8')){
if ($scope.video.hls == null) {
var config = {debug : false, autoStartLoad: false, enableCEA708Captions: false, maxFragLookUpTolerance: 0, xhrSetup: function(xhr, url) {
xhr.withCredentials = true; // do send cookies
}};
$scope.video.hls = new Hls(config);
$scope.video.hls.on(Hls.Events.ERROR,function(event,data) {
mixpanelAPI.send('hlsError', {"type": data.type, "isFatal": data.fatal});
//console.log('Caught HLS error: ' + data.type + ' is fatal: ' + data.fatal);
});
$scope.video.hls.on(Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT,function(event,data) {
//console.log("Manifest load timeout "+ data['url']);
mixpanelAPI.send('hlsManifestLoadTimeout', {"video": data['url']});
});
$scope.video.hls.on(Hls.ErrorDetails.LEVEL_LOAD_TIMEOUT,function(event,data) {
//console.log("Level load timeout "+ data['url']);
mixpanelAPI.send('hlsLevelLoadTimeout', {"video": data['url']});
});
$scope.video.hls.on(Hls.ErrorDetails.FRAG_LOAD_TIMEOUT,function(event,data) {
//console.log("Fragment load timeout "+ data['frag']['url'] + " start: " + data['frag']['start']);
mixpanelAPI.send('hlsLevelFragmentTimeout', {"video": data['frag']['url'], 'start': data['frag']['start']});
});
$scope.video.hls.on(Hls.Events.FRAG_LOADING,function(event,data) {
//console.log("Fragment loading "+ data['frag']['url'] + " start: " + data['frag']['start']);
mixpanelAPI.send('hlsFragmentLoading', {"video": data['frag']['url'], 'start': data['frag']['start']});
});
$scope.video.hls.on(Hls.Events.FRAG_LOADED,function(event,data) {
//console.log("Fragment loaded "+ data['frag']['url'] + " start: " + data['frag']['start'] + " treq: " + data['stats']['trequest'] + ' tload:' + data['stats']['tload'] + ' delta: ' + (data['stats']['tload']-data['stats']['trequest']));
mixpanelAPI.send('hlsFragmentLoaded', {
'video': data['frag']['url'],
'start': data['frag']['start'],
'requestTime': data['stats']['trequest'],
'loadedTime': data['stats']['tload'],
'delta': (data['stats']['tload']-data['stats']['trequest'])
});
});
$scope.video.hls.on(Hls.Events.MANIFEST_LOADING,function(event,data) {
//console.log("Manifest loading "+ data['url']);
mixpanelAPI.send('hlsManifestLoading', {"video": data['url']});
});
$scope.video.hls.on(Hls.Events.MANIFEST_LOADED,function(event,data) {
//console.log("Manifest loaded "+ data['url'] + " treq: " + data['stats']['trequest'] + ' tload:' + data['stats']['tload'] + ' delta: ' + (data['stats']['tload']-data['stats']['trequest']));
mixpanelAPI.send('hlsManifestLoaded', {
'video': data['url'],
'requestTime': data['stats']['trequest'],
'loadedTime': data['stats']['tload'],
'delta': (data['stats']['tload']-data['stats']['trequest'])
});
});
$scope.video.hls.on(Hls.Events.MANIFEST_PARSED,function(event,data) {
$scope.video.hls.startLoad($scope.video.startPosition);
});
}
$scope.video.startPosition = startPosition;
$scope.video.hls.attachMedia(document.getElementById($scope.video.id));
$scope.video.hls.loadSource(videoParams.url.folder + videoParams.url.name);
$scope.video.isHls = true;
} else {
document.getElementById($scope.video.id).src = videoParams.url.folder + videoParams.url.name;
$scope.video.isHls = false;
}
$scope.video.frameTracker = VideoFrame({
id : $scope.video.id,
frameRate: parseFloat($scope.video.frameRate)
});
$scope.video.elem[0].playbackRate = $scope.video.speed;
$scope.video.elem.on('seeked', function () {
if ($scope.isSeeking == true) {
$scope.$apply(function () {
$scope.setIsSeekingInternal(false);
var seekDoneTime = Date.now();
mixpanelAPI.send('seekedVideo', {
"video": $scope.video.url.name,
"frame": $scope.seekTargetFrame,
"reseeks": $scope.reseeks,
"seekReadyTime": ($scope.seekReadyTime - $scope.startSeekTime),
"seekTime": (seekDoneTime - $scope.seekReadyTime),
"totalTime": (seekDoneTime - $scope.startSeekTime)
});
if (typeof $scope.onSeekedCallback !== 'undefined' && $scope.onSeekedCallback !== null) {
$scope.onSeekedCallback();
$scope.onSeekedCallback = null;
}
});
}
});
}
};
$scope.setSpeed = function (speed) {
$scope.video.speed = speed;
// Missing: do a little dance to set speed if playback is active, and we are playing only to a given target.
$scope.video.elem[0].playbackRate = speed;
};
$scope.seekToFrame = function (frameNum, onDoneCallback) {
$scope.seekTo({frame: frameNum}, onDoneCallback);
};
$scope.seekToSeconds = function (seconds, onDoneCallback) {
$scope.seekTo({seconds: seconds}, onDoneCallback);
};
$scope.seekTo = function (params, onDoneCallback) {
if ($scope.isSeeking == false) {
$scope.setIsSeekingInternal(true);
}
if (typeof params.seconds !== 'undefined') {
var targetFrame = params.seconds * $scope.video.frameRate;
} else {
var targetFrame = params.frame;
}
$scope.seekContext = $scope.video.url.folder + $scope.video.url.name + targetFrame;
$scope.startSeekTime = Date.now();
$scope.startSeek(targetFrame, onDoneCallback);
};
$scope.startSeek = function(targetFrame, onDoneCallback) {
if ($scope.isSeeking == true && $scope.seekContext == ($scope.video.url.folder + $scope.video.url.name + targetFrame)) {
if ($scope.video.elem[0].seekable.length > 0) {
$scope.seekReadyTime = Date.now();
$scope.seekTargetFrame = targetFrame;
$scope.reseeks = 0;
$scope.onSeekedCallback = onDoneCallback;
$scope.video.frameTracker.seekTo({frame: targetFrame});
// if ($scope.video.url.folder.startsWith('https://media1.sportlogiq.com') && $scope.video.elem[0].paused) {
// $scope.play();
// }
$timeout(function () {
if ($scope.isSeeking == true
&& $scope.video.elem[0].seeking
&& $scope.seekContext == ($scope.video.url.folder + $scope.video.url.name + targetFrame)) {
// B-frames Chrome bug exception, if after 1 second we didn't get the seeked event, seek 1 frame after...
// Fix for certain videos not autoplaying.
// Reason still unknown, but, seeking ahead a couple of frames
// seems to fix the issue.
targetFrame += 2;
$scope.seekContext = $scope.video.url.folder + $scope.video.url.name + targetFrame;
$scope.reseeks += 1;
$scope.startSeek(targetFrame, onDoneCallback);
}
}, 1000);
} else {
$timeout(function() {
$scope.startSeek(targetFrame, onDoneCallback);
}, 100);
}
}
};
$scope.progressClick = function ($event) {
var secs = ($event.offsetX / $scope.video.elem[0].width) * $scope.video.duration;
$scope.seekToSeconds(secs);
if (typeof $scope.onProgressClick !== 'undefined') {
$scope.onProgressClick({secs: secs});
}
}
$scope.play = function () {
$scope.playbackContext.isPaused = false;
if ($scope.durationPlaybackRunning == true) {
$scope.checkForPlaybackDurationEnd();
}
$scope.video.elem[0].play();
};
$scope.pause = function () {
$scope.video.elem[0].pause();
$scope.playbackContext.isPaused = true;
};
$scope.playDuration = function (duration, onDoneCallback) {
$scope.startTime = $scope.video.elem[0].currentTime;
$scope.duration = duration;
$scope.onDoneCallback = onDoneCallback;
$scope.durationPlaybackRunning = true;
$scope.play();
};
$scope.seekFrameAndPlayDuration = function (frameNum, duration, onDoneCallback) {
$scope.seekToFrame (frameNum, function (){
$scope.playDuration(duration, onDoneCallback);
});
};
$scope.seekSecondAndPlayDuration = function (second, duration, onDoneCallback) {
$scope.seekToSeconds (second, function (){
$scope.playDuration(duration, onDoneCallback);
});
};
$scope.checkForPlaybackDurationEnd = function () {
if ($scope.playbackContext.isPaused == false) {
var currentTime = $scope.video.elem[0].currentTime;
if (currentTime >= ($scope.startTime + $scope.duration)) {
$scope.pause();
$scope.durationPlaybackRunning = false;
if (typeof $scope.onDoneCallback !== 'undefined') {
$scope.onDoneCallback();
}
} else {
var remainingTime = (($scope.startTime + $scope.duration) - currentTime) / $scope.video.elem[0].playbackRate ;
$timeout(function() {
$scope.checkForPlaybackDurationEnd();
}, remainingTime * 1000);
}
}
}
$scope.registerVideoPlayer({
id: $scope.slId,
handlers: {
extractClip: function(frame, prefix, suffix, event, successCb, errorCb) {
if (frame > 0) {
var formatEventTime = $filter('formatEventTime');
var formatGameTime = $filter('formatGameTime');
var formatPeriodNumberText = $filter('formatPeriodNumberText');
var clipDetails = event.shorthand
+ ' by '+ event.playerInfo.firstName +' '+ event.playerInfo.lastName
+ ', '+ formatGameTime(event) +' '+ formatEventTime(event)
+ ' '+ formatPeriodNumberText(event.period) + ' period'
var curTime = parseInt(frame) / parseFloat(event.framerate);
var vidId = $scope.video.vidid;
var rqPayload = {
'method': 'POST',
'url': '/api/0.1/videos/'+ vidId +'/clipextract/'+ (curTime - prefix) +'/'+ (prefix + suffix),
'data': {
'details': clipDetails,
'email': 'false', // send bools are strings "true" or "false"
'baseUrl': ''
},
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'transformRequest': function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
}
};
$http(rqPayload).then(function(response) {
if (successCb instanceof Function) {
$scope.$eval(successCb);
}
}, function(response) {
if (errorCb instanceof Function) {
$scope.$eval(errorCb);
}
});
}
},
setVideo: function (videoParams, startFramePosition) {
if(typeof startFramePosition === 'undefined') {
startFramePosition = -1;
}
$scope.setVideo(videoParams, startFramePosition);
},
setSpeed: function (speed) {
$scope.setSpeed(speed);
},
seekToFrame: function (frameNum, onDoneCallback) {
$scope.seekToFrame (frameNum, onDoneCallback);
},
seekToSeconds: function (seconds, onDoneCallback) {
$scope.seekToSeconds (seconds, onDoneCallback);
},
playDuration: function (duration, onDoneCallback) {
$scope.playDuration (duration, onDoneCallback);
},
cancelPlayDuration: function () {
$scope.pause();
$scope.durationPlaybackRunning = false;
},
seekFrameAndPlayDuration: function (frameNum, duration, onDoneCallback) {
$scope.seekFrameAndPlayDuration(frameNum, duration, onDoneCallback);
},
seekSecondAndPlayDuration: function (second, duration, onDoneCallback) {
$scope.seekSecondAndPlayDuration(second, duration, onDoneCallback);
},
loadSeekFrameAndPlayDuration: function (videoParams, frameNum, duration, onDoneCallback) {
$scope.setVideo(videoParams, frameNum);
$scope.seekFrameAndPlayDuration (frameNum, duration, onDoneCallback);
},
play: function () {
$scope.play ();
},
pause: function () {
$scope.pause ();
},
cancelSeek: function() {
$scope.cancelSeek();
},
getCurrentFrame: function () {
return $scope.video.frameTracker.get();
},
getCurrentTime: function () {
return $scope.video.frameTracker.currentTime;
},
getDuration: function () {
return $scope.video.frameTracker.duration;
},
deactivate: function() {
$scope.durationPlaybackRunning = false;
$scope.cancelSeek();
$scope.pause ();
}
}
});
}, // end of controller
link: function(scope,elem,attr){
scope.video.elem = elem.find('video');
if (scope.showProgress) {
scope.video.elem.on('durationchange', function () {
if (scope.video.elem[0].duration != 'NaN') {
scope.video.duration = scope.video.elem[0].duration;
}
});
scope.video.elem.on('timeupdate', function () {
scope.$apply(function () {
scope.video.currentTime = scope.video.elem[0].currentTime;
});
});
}
} // end of link
}; // end of directoive factory
})
.directive('eventVideoPlayer', function() {
return {
restrict: 'E',
replace: true,
scope: {
slId: '=',
canViewClips: '=',
periods: '=',
slWidth: '=',
slHeight: '=',
playbackContext: '=?',
registerVideoPlayer: '&',
onEventPlaybackStart: '&',
onEventPlaybackComplete: '&'
},
templateUrl: 'views/eventVideoPlayer.html',
controller: function ($scope, $timeout, usersPlaylists) {
$scope.period = null;
$scope.isClipSeeking = false;
$scope.isClipPlayingBack = false;
if (typeof $scope.playbackContext == 'undefined') {
$scope.playbackContext = {};
}
$scope.playbackContext.isPaused = true;
$scope.showVideoPlaceholder = false;
if ($scope.canViewClips === false) {
$scope.showVideoPlaceholder = true;
}
$scope.setIsSeeking = function (isSeekingFlag) {
$scope.isClipSeeking = isSeekingFlag;
if ($scope.canViewClips === true) {
$scope.showVideoPlaceholder = isSeekingFlag;
}
};
// Periods is the entire set of periods for the current game. It will change when the current game changes, so make
// sure the next time a video is played after a game change that the period information will be updated.
$scope.$watch('periods', function (newVal) {
$scope.period = null;
});
$scope.registerVideoPlayerInternal = function (id, methods) {
$scope.videoPlayer = methods;
};
$scope.playbackEvent = function(event) {
$scope.event = event;
if ($scope.canViewClips == true) {
if ($scope.isClipSeeking == true) {
$scope.videoPlayer.cancelSeek();
}
if ($scope.isClipPlayingBack == true) {
$scope.videoPlayer.cancelPlayDuration();
$scope.isClipPlayingBack = false;
}
var playbackOffsets = {
default: {pre: 5.0, post: 10.0},
shot: {pre: 5.0, post: 7.5},
carry: {pre: 5.0, post: 10.0},
dumpout: {pre: 5.0, post: 5.5},
dumpin: {pre: 5.0, post: 10.0},
lpr: {pre: 5.0, post: 12.0},
controlledbreakout: {pre: 5.0, post: 15.0}
}
if ($scope.period == null || $scope.period.id != event.period) {
if ($scope.periods) {
for (var i = 0; i < $scope.periods.length; i++) {
if ($scope.periods[i].id == event.period) {
$scope.period = $scope.periods[i];
}
}
}
}
var playbackPreEventOffset = playbackOffsets.default.pre;
var playbackPostEventOffset = playbackOffsets.default.post;
if (!(typeof playbackOffsets[event['name']] === 'undefined')) {
playbackPreEventOffset = playbackOffsets[event['name']].pre;
playbackPostEventOffset = playbackOffsets[event['name']].post;
}
if (event.vidparam) {
var vidparam = event.vidparam;
} else {
var vidparam = $scope.period.video;
}
var targetFrame = event['frame'] - Math.ceil(playbackPreEventOffset * vidparam['frameRate']);
$scope.videoPlayer.setVideo({
vidid: vidparam['id'],
url: {
folder: 'https://' + vidparam['rootURL'] + '/',
name: vidparam['fileName']
},
frameRate: vidparam['frameRate']
}, targetFrame);
$scope.videoPlayer.seekToFrame(targetFrame,
function () {
if (typeof $scope.onEventPlaybackStart !== 'undefined') {
$scope.onEventPlaybackStart({id : $scope.slId, event: event});
}
$scope.isClipPlayingBack = true;
$scope.videoPlayer.playDuration(
playbackPreEventOffset + playbackPostEventOffset,
function () {
$scope.isClipPlayingBack = false;
if (typeof $scope.onEventPlaybackComplete !== 'undefined') {
$scope.onEventPlaybackComplete({id : $scope.slId, event: event});
}
});
});
} else {
$scope.isClipSeeking = true;
$timeout(function() {
$scope.isClipSeeking = false;
}, 3000);
}
};
$scope.registerVideoPlayer({
id: $scope.slId,
handlers : {
extractEventClip: function(prefix, suffix, event, successCb, errorCb) {
$scope.videoPlayer.extractClip(usersPlaylists.currentlyPlaying.frame, prefix, suffix, event, successCb, errorCb);
},
playbackEvent: function (event) {
// Hacky way to see which event is playing
usersPlaylists.currentlyPlaying = event;
$scope.playbackEvent (event);
},
cancelPlaybackEvent: function () {
$scope.videoPlayer.cancelPlayDuration (event);
},
play: function () {
$scope.videoPlayer.play ();
},
pause: function () {
$scope.videoPlayer.pause ();
},
setSpeed: function (newSpeed) {
$scope.videoPlayer.setSpeed(newSpeed);
},
deactivateVideo: function () {
$scope.videoPlayer.deactivate();
}
}
});
} // end of controller
}; // end of directoive factory
})
.directive('eventPlaylistVideoPlayer', function() {
return {
restrict: 'E',
replace: true,
scope: {
slId: '=',
canViewClips: '=',
canSharePlaylist: "=",
permissions: "=",
periods: '=',
slWidth: '=',
slHeight: '=',
onEventPlaybackStart: '&',
onSkipFwd: '&',
onSkipBack: '&',
onTogglePlayPause: '&',
onSetSpeed: '&',
playbackContext: '=',
registerVideoPlayer: '&'
},
templateUrl: 'views/eventPlaylistVideoPlayer.html',
controller: function ($scope, $timeout, mixpanelAPI, usersPlaylists, playlistCreator) {
$scope.blurMe = function ($event) {
$event.target.blur();
}
$scope.playlistCreator = playlistCreator;
$scope.clipExtractPrefix = 15;
$scope.clipExtractSuffix = 15;
$scope.clipExtractShow = true;
// Setup context for Mixpanel
$scope.context = {
view: $scope.slId,
}
$scope.internalPlaybackContext = {
isPaused : true,
speed : 1.0,
playbackHandlers : null,
skipBackTriggered : false
};
$scope.playbackContext.event = null;
$scope.registerVideoPlayerInternal = function (id, handlers) {
$scope.internalPlaybackContext.playbackHandlers = handlers;
}
$scope.playbackEventList = function (eventList) {
$scope.internalPlaybackContext.list = eventList;
if ($scope.internalPlaybackContext.list.length > 0) {
$scope.internalPlaybackContext.current = 0;
$scope.internalPlaybackContext.event = $scope.internalPlaybackContext.list[$scope.internalPlaybackContext.current];
$scope.playbackContext.event = $scope.internalPlaybackContext.event;
$scope.internalPlaybackContext.playbackHandlers.playbackEvent($scope.playbackContext.event);
}
}
$scope.playListItemPlayCurrent = function (id) {
if ($scope.internalPlaybackContext.current < $scope.internalPlaybackContext.list.length) {
$scope.playbackContext.event = $scope.internalPlaybackContext.list[$scope.internalPlaybackContext.current];
$scope.internalPlaybackContext.playbackHandlers.playbackEvent($scope.playbackContext.event);
}
}
$scope.playListItemPlaybackStart = function (id, event) {
if (typeof $scope.onEventPlaybackStart !== 'undefined') {
$scope.onEventPlaybackStart({id : $scope.slId, event: event});
}
}
$scope.playListItemPlaybackComplete = function (id) {
$scope.internalPlaybackContext.current += 1;
if ($scope.internalPlaybackContext.current < $scope.internalPlaybackContext.list.length) {
$scope.playListItemPlayCurrent();
}
}
$scope.extractEventClip = function(prefix, suffix) {
$scope.clipExtractShow = false;
$scope.internalPlaybackContext.playbackHandlers.extractEventClip(prefix, suffix, $scope.playbackContext.event, function(response) {
$timeout(function() {
$scope.clipExtractShow = true;
}, 5000)
}, function(response) {
alert('Your clip extraction could not be processed at this time.')
console.error('clip extraction failed processing: ', response);
});
};
$scope.skipFwd = function () {
$scope.internalPlaybackContext.playbackHandlers.cancelPlaybackEvent();
$scope.internalPlaybackContext.current += 1;
if ($scope.internalPlaybackContext.current > $scope.internalPlaybackContext.list.length) {
$scope.internalPlaybackContext.current = $scope.internalPlaybackContext.list.length;
}
$scope.playListItemPlayCurrent();
if (typeof $scope.onSkipFwd !== 'undefined') {
$scope.onSkipFwd();
}
}
$scope.skipBack = function () {
$scope.internalPlaybackContext.playbackHandlers.cancelPlaybackEvent();
if ($scope.internalPlaybackContext.skipBackTriggered) {
$scope.internalPlaybackContext.current -= 1;
} else {
$scope.internalPlaybackContext.skipBackTriggered = true;
}
if ($scope.internalPlaybackContext.current < 0) {
$scope.internalPlaybackContext.current = 0;
}
$scope.playListItemPlayCurrent();
$timeout(function() {
$scope.internalPlaybackContext.skipBackTriggered = false;
}, 1250);
if (typeof $scope.onSkipBack !== 'undefined') {
$scope.onSkipBack();
}
}
$scope.setSpeed = function (newSpeed) {
$scope.internalPlaybackContext.playbackHandlers.setSpeed(newSpeed);
$scope.internalPlaybackContext.speed = newSpeed;
}
$scope.onSetSpeedInternal = function (newSpeed) {
$scope.onSetSpeed ({id : $scope.slId, newSpeed: newSpeed});
}
$scope.togglePlayPauseInternal = function () {
if ($scope.internalPlaybackContext.isPaused) {
if ($scope.internalPlaybackContext.current >= $scope.internalPlaybackContext.list.length) {
$scope.playbackEventList($scope.internalPlaybackContext.list);
} else {
$scope.internalPlaybackContext.playbackHandlers.play();
}
} else {
$scope.internalPlaybackContext.playbackHandlers.pause();
}
if (typeof $scope.onTogglePlayPause !== 'undefined') {
$scope.onTogglePlayPause();
}
}
$scope.registerVideoPlayer({
id: $scope.slId,
handlers : {
playbackSingleEvent: function (event) {
var eventList = [event];
$scope.playbackEventList (eventList);
},
playbackEventList: function (eventList) {
$scope.playbackEventList (eventList);
},
setSpeed: function (newSpeed) {
$scope.setSpeed(newSpeed);
},
deactivateVideo: function () {
// // Reset the removedEvents array to destroy state
// $scope.playlistCreator.removedEvents = [];
// Makes sure that the list prop is defined
if ($scope.internalPlaybackContext.list) {
// Reset all isRemoved props to false to reset state
$scope.internalPlaybackContext.list.forEach(function(item) {
item.isRemoved = false;
});
}
$scope.internalPlaybackContext.playbackHandlers.deactivateVideo();
}
}
});
} // end of controller
}; // end of directoive factory
});