Uses player functions only after the player has reported playing event.

This commit is contained in:
damencho 2016-03-25 15:36:41 -05:00
parent 9b09e61877
commit 508fd4a8df
3 changed files with 80 additions and 71 deletions

View File

@ -1125,7 +1125,7 @@ export default {
} }
if (attributes.state === 'stop') { if (attributes.state === 'stop') {
APP.UI.stopSharedVideo(id, attributes); APP.UI.stopSharedVideo(id);
} else if (attributes.state === 'start') { } else if (attributes.state === 'start') {
APP.UI.showSharedVideo(id, value, attributes); APP.UI.showSharedVideo(id, value, attributes);
} else if (attributes.state === 'playing' } else if (attributes.state === 'playing'

View File

@ -1135,7 +1135,7 @@ UI.updateSharedVideo = function (id, url, attributes) {
*/ */
UI.stopSharedVideo = function (id, attributes) { UI.stopSharedVideo = function (id, attributes) {
if (sharedVideoManager) if (sharedVideoManager)
sharedVideoManager.stopSharedVideo(id, attributes); sharedVideoManager.stopSharedVideo(id);
}; };
module.exports = UI; module.exports = UI;

View File

@ -17,7 +17,7 @@ export const SHARED_VIDEO_CONTAINER_TYPE = "sharedvideo";
* @type {string} * @type {string}
*/ */
const defaultSharedVideoLink = "https://www.youtube.com/watch?v=xNXN7CZk8X0"; const defaultSharedVideoLink = "https://www.youtube.com/watch?v=xNXN7CZk8X0";
const updateInterval = 5000; // milliseconds
/** /**
* Manager of shared video. * Manager of shared video.
*/ */
@ -26,7 +26,6 @@ export default class SharedVideoManager {
this.emitter = emitter; this.emitter = emitter;
this.isSharedVideoShown = false; this.isSharedVideoShown = false;
this.isPlayerAPILoaded = false; this.isPlayerAPILoaded = false;
this.updateInterval = 5000; // milliseconds
} }
/** /**
@ -71,6 +70,13 @@ export default class SharedVideoManager {
var firstScriptTag = document.getElementsByTagName('script')[0]; var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// sometimes we receive errors like player not defined
// or player.pauseVideo is not a function
// we need to operate with player after start playing
// self.player will be defined once it start playing
// and will process any initial attributes if any
this.initialAttributes = null;
var self = this; var self = this;
if(self.isPlayerAPILoaded) if(self.isPlayerAPILoaded)
window.onYouTubeIframeAPIReady(); window.onYouTubeIframeAPIReady();
@ -78,14 +84,14 @@ export default class SharedVideoManager {
window.onYouTubeIframeAPIReady = function() { window.onYouTubeIframeAPIReady = function() {
self.isPlayerAPILoaded = true; self.isPlayerAPILoaded = true;
let showControls = APP.conference.isLocalId(self.from) ? 1 : 0; let showControls = APP.conference.isLocalId(self.from) ? 1 : 0;
self.player = new YT.Player('sharedVideoIFrame', { new YT.Player('sharedVideoIFrame', {
height: '100%', height: '100%',
width: '100%', width: '100%',
videoId: self.url, videoId: self.url,
playerVars: { playerVars: {
'origin': location.origin, 'origin': location.origin,
'fs': '0', 'fs': '0',
'autoplay': 1, 'autoplay': 0,
'controls': showControls, 'controls': showControls,
'rel' : 0 'rel' : 0
}, },
@ -97,19 +103,19 @@ export default class SharedVideoManager {
}); });
}; };
// whether we should pause the player as initial status
// sometimes if we try to pause the player before it starts playing
// we can end up with player in buffering mode
this.initialPause = false;
window.onPlayerStateChange = function(event) { window.onPlayerStateChange = function(event) {
if (event.data == YT.PlayerState.PLAYING) { if (event.data == YT.PlayerState.PLAYING) {
self.playerPaused = false; self.playerPaused = false;
// check for initial pause self.player = event.target;
if(self.initialPause) {
self.initialPause = false; if(self.initialAttributes)
self.player.pauseVideo(); {
self.processAttributes(
self.player, self.initialAttributes, self.playerPaused);
self.initialAttributes = null;
} }
self.updateCheck(); self.updateCheck();
} else if (event.data == YT.PlayerState.PAUSED) { } else if (event.data == YT.PlayerState.PAUSED) {
self.playerPaused = true; self.playerPaused = true;
@ -119,6 +125,8 @@ export default class SharedVideoManager {
window.onPlayerReady = function(event) { window.onPlayerReady = function(event) {
let player = event.target; let player = event.target;
// do not relay on autoplay as it is not sending all of the events
// in onPlayerStateChange
player.playVideo(); player.playVideo();
let thumb = new SharedVideoThumb(self.url); let thumb = new SharedVideoThumb(self.url);
@ -140,15 +148,14 @@ export default class SharedVideoManager {
if(APP.conference.isLocalId(self.from)) { if(APP.conference.isLocalId(self.from)) {
self.intervalId = setInterval( self.intervalId = setInterval(
self.updateCheck.bind(self), self.updateCheck.bind(self),
self.updateInterval); updateInterval);
} }
// set initial state of the player if there is enough information if(self.player)
if(attributes.state === 'pause') self.processAttributes(
self.initialPause = true; self.player, attributes, self.playerPaused);
else if(attributes.time > 0) { else {
console.log("Player seekTo:", attributes.time); self.initialAttributes = attributes;
player.seekTo(attributes.time);
} }
}; };
@ -157,13 +164,55 @@ export default class SharedVideoManager {
}; };
} }
/**
* Process attributes, whether player needs to be paused or seek.
* @param player the player to operate over
* @param attributes the attributes with the player state we want
* @param playerPaused current saved state for the player
*/
processAttributes (player, attributes, playerPaused)
{
if(!attributes)
return;
if (attributes.state == 'playing') {
// check received time and current time
let currentPosition = player.getCurrentTime();
let diff = Math.abs(attributes.time - currentPosition);
// if we drift more than the interval for checking
// sync, the interval is in milliseconds
if(diff > updateInterval/1000) {
console.info("DDD Player seekTo:", attributes.time,
" current time is:", currentPosition, " diff:", diff);
player.seekTo(attributes.time);
}
// lets check the volume
if (attributes.volume !== undefined &&
player.getVolume() != attributes.volume) {
player.setVolume(attributes.volume);
console.info("Player change of volume:" + attributes.volume);
}
if(playerPaused)
player.playVideo();
} else if (attributes.state == 'pause') {
// if its not paused, pause it
player.pauseVideo();
}
}
/** /**
* Checks current state of the player and fire an event with the values. * Checks current state of the player and fire an event with the values.
*/ */
updateCheck(sendPauseEvent) updateCheck(sendPauseEvent)
{ {
// ignore update checks if we are not the owner of the video // ignore update checks if we are not the owner of the video
if(!APP.conference.isLocalId(this.from)) // or there is still no player defined
if(!APP.conference.isLocalId(this.from) || !this.player)
return; return;
let state = this.player.getPlayerState(); let state = this.player.getPlayerState();
@ -195,54 +244,15 @@ export default class SharedVideoManager {
return; return;
} }
if (attributes.state == 'playing') {
if(!this.isSharedVideoShown) { if(!this.isSharedVideoShown) {
this.showSharedVideo(id, url, attributes); this.showSharedVideo(id, url, attributes);
return; return;
} }
// ocasionally we get this.player.getCurrentTime is not a function if(!this.player)
// it seems its that player hasn't really loaded this.initialAttributes = attributes;
if(!this.player || !this.player.getCurrentTime
|| !this.player.pauseVideo
|| !this.player.playVideo
|| !this.player.getVolume
|| !this.player.seekTo
|| !this.player.getVolume)
return;
// check received time and current time
let currentPosition = this.player.getCurrentTime();
let diff = Math.abs(attributes.time - currentPosition);
// if we drift more than two times of the interval for checking
// sync, the interval is in milliseconds
if(diff > this.updateInterval*2/1000) {
console.log("Player seekTo:", attributes.time,
" current time is:", currentPosition, " diff:", diff);
this.player.seekTo(attributes.time);
}
// lets check the volume
if (attributes.volume !== undefined &&
this.player.getVolume() != attributes.volume) {
this.player.setVolume(attributes.volume);
console.log("Player change of volume:" + attributes.volume);
}
if(this.playerPaused)
this.player.playVideo();
} else if (attributes.state == 'pause') {
// if its not paused, pause it
if(this.isSharedVideoShown) {
this.player.pauseVideo();
}
else { else {
// if not shown show it, passing attributes so it can this.processAttributes(this.player, attributes, this.playerPaused);
// be shown paused
this.showSharedVideo(id, url, attributes);
}
} }
} }
@ -251,9 +261,8 @@ export default class SharedVideoManager {
* shared video is the one in the id (called when user * shared video is the one in the id (called when user
* left and we want to remove video if the user sharing it left). * left and we want to remove video if the user sharing it left).
* @param id the id of the sender of the command * @param id the id of the sender of the command
* @param attributes
*/ */
stopSharedVideo (id, attributes) { stopSharedVideo (id) {
if (!this.isSharedVideoShown) if (!this.isSharedVideoShown)
return; return;