Skip to content
This repository has been archived by the owner on Jun 29, 2018. It is now read-only.

Commit

Permalink
[#928933] Ensure duration value is consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottDowne committed Nov 6, 2013
1 parent b645bf1 commit 32ea3fe
Showing 1 changed file with 80 additions and 81 deletions.
161 changes: 80 additions & 81 deletions wrappers/youtube/popcorn.HTMLYouTubeVideoElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
catchRoguePauseEvent = false,
catchRoguePlayEvent = false,
mediaReady = false,
durationReady = false,
loopedPlay = false,
player,
playerPaused = true,
Expand All @@ -90,7 +91,7 @@
lastLoadedFraction = 0,
currentTimeInterval,
timeUpdateInterval,
firstPlay = true;
firstPlay = false;

// Namespace all events we'll produce
self._eventNamespace = Popcorn.guid( "HTMLYouTubeVideoElement::" );
Expand Down Expand Up @@ -124,28 +125,6 @@
onMuted();
}

function getDuration() {
if( !mediaReady ) {
// loadedmetadata properly sets the duration, so nothing to do here yet.
return impl.duration;
}

var oldDuration = impl.duration,
newDuration = player.getDuration();

// Deal with duration=0 from YouTube
if( newDuration ) {
if( oldDuration !== newDuration ) {
impl.duration = newDuration;
self.dispatchEvent( "durationchange" );
}
} else {
setTimeout( getDuration, 50 );
}

return newDuration;
}

function onPlayerError(event) {
// There's no perfect mapping to HTML5 errors from YouTube errors.
var err = { name: "MediaError" };
Expand Down Expand Up @@ -185,6 +164,53 @@
self.dispatchEvent( "error" );
}

// This function needs duration and first play to be ready.
function onFirstPlay() {
addMediaReadyCallback(function() {
bufferedInterval = setInterval( monitorBuffered, 50 );
});

// Set initial paused state
if( impl.autoplay || !impl.paused ) {
impl.paused = false;
addMediaReadyCallback(function() {
onPlay();
});
} else {
// if a pause happens while seeking, ensure we catch it.
// in youtube seeks fire pause events, and we don't want to listen to that.
// except for the case of an actual pause.
catchRoguePauseEvent = false;
player.pauseVideo();
}

// Ensure video will now be unmuted when playing due to the mute on initial load.
if( !impl.muted ) {
player.unMute();
}

impl.readyState = self.HAVE_METADATA;
self.dispatchEvent( "loadedmetadata" );
currentTimeInterval = setInterval( monitorCurrentTime,
CURRENT_TIME_MONITOR_MS );

self.dispatchEvent( "loadeddata" );

impl.readyState = self.HAVE_FUTURE_DATA;
self.dispatchEvent( "canplay" );

mediaReady = true;
var i = mediaReadyCallbacks.length;
while( i-- ) {
mediaReadyCallbacks[ i ]();
delete mediaReadyCallbacks[ i ];
}

// We can't easily determine canplaythrough, but will send anyway.
impl.readyState = self.HAVE_ENOUGH_DATA;
self.dispatchEvent( "canplaythrough" );
}

function onPlayerStateChange( event ) {

switch( event.data ) {
Expand All @@ -196,54 +222,14 @@

// playing
case YT.PlayerState.PLAYING:
if( firstPlay ) {
if( !firstPlay ) {
// fake ready event
firstPlay = false;

addMediaReadyCallback(function() {
bufferedInterval = setInterval( monitorBuffered, 50 );
});

// Set initial paused state
if( impl.autoplay || !impl.paused ) {
impl.paused = false;
addMediaReadyCallback(function() {
onPlay();
});
} else {
// if a pause happens while seeking, ensure we catch it.
// in youtube seeks fire pause events, and we don't want to listen to that.
// except for the case of an actual pause.
catchRoguePauseEvent = false;
player.pauseVideo();
}

// Ensure video will now be unmuted when playing due to the mute on initial load.
if( !impl.muted ) {
player.unMute();
}
firstPlay = true;

impl.duration = player.getDuration();
impl.readyState = self.HAVE_METADATA;
self.dispatchEvent( "loadedmetadata" );
currentTimeInterval = setInterval( monitorCurrentTime,
CURRENT_TIME_MONITOR_MS );

self.dispatchEvent( "loadeddata" );

impl.readyState = self.HAVE_FUTURE_DATA;
self.dispatchEvent( "canplay" );

mediaReady = true;
var i = mediaReadyCallbacks.length;
while( i-- ) {
mediaReadyCallbacks[ i ]();
delete mediaReadyCallbacks[ i ];
// Duration ready happened first, we're now ready.
if ( durationReady ) {
onFirstPlay();
}

// We can't easily determine canplaythrough, but will send anyway.
impl.readyState = self.HAVE_ENOUGH_DATA;
self.dispatchEvent( "canplaythrough" );
} else if ( catchRoguePlayEvent ) {
catchRoguePlayEvent = false;
player.pauseVideo();
Expand Down Expand Up @@ -294,6 +280,8 @@
if( !( playerReady && player ) ) {
return;
}
durationReady = false;
firstPlay = false;
clearInterval( currentTimeInterval );
clearInterval( bufferedInterval );
player.stopVideo();
Expand Down Expand Up @@ -369,6 +357,27 @@
// Get video ID out of youtube url
aSrc = regexYouTube.exec( aSrc )[ 1 ];

var xhrURL = "https://gdata.youtube.com/feeds/api/videos/" + aSrc + "?v=2&alt=jsonc&callback=?";
// Get duration value.
Popcorn.getJSONP( xhrURL, function( resp ) {
var warning = "failed to retreive duration data, reason: ";
if ( resp.error ) {
console.warn( warning + resp.error.message );
return ;
} else if ( !resp.data ) {
console.warn( warning + "no response data" );
return;
}
impl.duration = resp.data.duration;
self.dispatchEvent( "durationchange" );
durationReady = true;

// First play happened first, we're now ready.
if ( firstPlay ) {
onFirstPlay();
}
});

player = new YT.Player( elem, {
width: "100%",
height: "100%",
Expand All @@ -385,10 +394,6 @@
impl.networkState = self.NETWORK_LOADING;
self.dispatchEvent( "loadstart" );
self.dispatchEvent( "progress" );

// Queue a get duration call so we'll have duration info
// and can dispatch durationchange.
getDuration();
}

function monitorCurrentTime() {
Expand All @@ -411,10 +416,6 @@
lastLoadedFraction = fraction;

onProgress();

if ( fraction >= 1 ) {
clearInterval( bufferedInterval );
}
}
}

Expand Down Expand Up @@ -615,7 +616,7 @@

duration: {
get: function() {
return getDuration();
return impl.duration;
}
},

Expand Down Expand Up @@ -691,14 +692,12 @@
throw "INDEX_SIZE_ERR: DOM Exception 1";
},
end: function( index ) {
var duration;
if ( index === 0 ) {
duration = getDuration();
if ( !duration ) {
if ( !impl.duration ) {
return 0;
}

return duration * player.getVideoLoadedFraction();
return impl.duration * lastLoadedFraction;
}

//throw fake DOMException/INDEX_SIZE_ERR
Expand Down

0 comments on commit 32ea3fe

Please sign in to comment.