1
0
mirror of https://github.com/videojs/video.js.git synced 2025-02-04 11:43:27 +02:00

Updated swf object to newest version.

Optimizing player for later loaded sources.
This commit is contained in:
Steve Heffernan 2011-12-01 15:47:12 -08:00
parent ec145f6d4d
commit 7e747e95ab
8 changed files with 125 additions and 79 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -141,10 +141,12 @@ _V_.Component = _V_.Class.extend({
/* Ready - Trigger functions when component is ready /* Ready - Trigger functions when component is ready
================================================================================ */ ================================================================================ */
ready: function(fn){ ready: function(fn){
if (!fn) return;
if (this.isReady) { if (this.isReady) {
fn.call(this); fn.call(this);
} else { } else {
if (this.readyQueue !== undefined) { if (this.readyQueue === undefined) {
this.readyQueue = []; this.readyQueue = [];
} }
this.readyQueue.push(fn); this.readyQueue.push(fn);
@ -152,9 +154,8 @@ _V_.Component = _V_.Class.extend({
}, },
triggerReady: function(){ triggerReady: function(){
if (this.isReady) return;
this.isReady = true; this.isReady = true;
if (this.readyQueue.length > 0) { if (this.readyQueue && this.readyQueue.length > 0) {
// Call all functions in ready queue // Call all functions in ready queue
this.each(this.readyQueue, function(fn){ this.each(this.readyQueue, function(fn){
fn.call(this); fn.call(this);

View File

@ -51,6 +51,9 @@ VideoJS.options = {
// Default of web browser is 300x150. Should rely on source width/height. // Default of web browser is 300x150. Should rely on source width/height.
width: "auto", width: "auto",
height: "auto", height: "auto",
// defaultVolume: 0.85,
defaultVolume: 0.00, // The freakin seaguls are driving me crazy!
// Included control sets // Included control sets
components: [ components: [

View File

@ -62,7 +62,7 @@ _V_.extend({
insertFirst: function(node, parent){ insertFirst: function(node, parent){
if (parent.firstChild) { if (parent.firstChild) {
parent.insertBefore(parent.firstChild, node); parent.insertBefore(node, parent.firstChild);
} else { } else {
parent.appendChild(node); parent.appendChild(node);
} }

View File

@ -13,28 +13,18 @@ _V_.Player = _V_.Component.extend({
// Browsers default to 300x150 if there's no width/height or video size data. // Browsers default to 300x150 if there's no width/height or video size data.
initWidth = width || 300, initWidth = width || 300,
initHeight = height || 150, initHeight = height || 150;
// If the HTML5 video is already playing, we'll adjust
paused = tag.paused;
// Make player findable on elements // Make player findable on elements
tag.player = el.player = this; tag.player = el.player = this;
// Add callback to ready queue
this.ready(ready);
// Wrap video tag in div (el/box) container // Wrap video tag in div (el/box) container
tag.parentNode.insertBefore(el, tag); tag.parentNode.insertBefore(el, tag);
el.appendChild(tag); // Breaks iPhone, fixed in HTML5 setup. el.appendChild(tag); // Breaks iPhone, fixed in HTML5 setup.
// Safari (5.1.1) and Chrome (15) both have issues when you use autoplay and a poster and no controls.
// Chrome just hides the video. Safari hides the video if you move it in the DOM like VJS does.
// This fixes the Safari issue by removing the poster, which is currently never used again after
// the video starts playing.
if (!paused) {
// options.poster = tag.poster
// tag.poster = null;
// tag.play();
}
// Give video tag properties to box // Give video tag properties to box
el.id = this.id = tag.id; // ID will now reference box, not the video tag el.id = this.id = tag.id; // ID will now reference box, not the video tag
el.className = tag.className; el.className = tag.className;
@ -72,11 +62,6 @@ _V_.Player = _V_.Component.extend({
} }
} }
// Add callback to ready queue
this.apiIsReady = false;
this.readyQueue = [];
if (ready) { this.ready(ready); }
// Holder for playback tech components // Holder for playback tech components
this.techs = {}; this.techs = {};
@ -88,11 +73,12 @@ _V_.Player = _V_.Component.extend({
this.addEvent("ended", this.onEnded); this.addEvent("ended", this.onEnded);
this.addEvent("play", this.onPlay); this.addEvent("play", this.onPlay);
this.addEvent("pause", this.onPause); this.addEvent("pause", this.onPause);
this.addEvent("error", this.onError);
// When the API is ready, loop through the components and add to the player. // When the API is ready, loop through the components and add to the player.
this.components = [];
if (this.options.controls) { if (this.options.controls) {
this.addEvent("techready", function(){ this.ready(function(){
this.each(this.options.components, function(set){ this.each(this.options.components, function(set){
this.addComponent(set); this.addComponent(set);
}); });
@ -173,9 +159,20 @@ _V_.Player = _V_.Component.extend({
// And append playback element in player div. // And append playback element in player div.
loadTech: function(techName, source){ loadTech: function(techName, source){
this.triggerEvent("loadingtech");
// Pause and remove current playback technology // Pause and remove current playback technology
if (this.tech) { if (this.tech) {
this.removeTech(tech); this.removeTech(this.tech);
// Turn off any manual progress or timeupdate tracking
if (this.manualProgress) {
this.manualProgressOff()
}
if (this.manualTimeUpdates) {
this.manualTimeUpdatesOff()
}
// If the first time loading, HTML5 tag will exist but won't be initialized // If the first time loading, HTML5 tag will exist but won't be initialized
// So we need to remove it if we're not loading HTML5 // So we need to remove it if we're not loading HTML5
@ -188,28 +185,30 @@ _V_.Player = _V_.Component.extend({
// Turn off API access because we're loading a new tech that might load asynchronously // Turn off API access because we're loading a new tech that might load asynchronously
this.isReady = false; this.isReady = false;
// Finsh API Setup when tech is ready var techReady = function(){
this.addEvent("techready", _V_.proxy(this, function(){
// Reomve this so it's not called twice next load
this.removeEvent("techready", arguments.callee);
// Set up playback technology's event triggers // Set up playback technology's event triggers
this.tech.setupTriggers(); this.setupTriggers();
this.triggerReady(); this.player.triggerReady();
// Manually track progress in cases where the browser/flash player doesn't report it. // Manually track progress in cases where the browser/flash player doesn't report it.
if (!_V_.techSupports(techName, "event", "progress")) { this.manualProgressOn(); } if (!_V_.techSupports(this.name, "event", "progress")) {
this.player.manualProgressOn();
}
// Manually track timeudpates in cases where the browser/flash player doesn't report it. // Manually track timeudpates in cases where the browser/flash player doesn't report it.
if (!_V_.techSupports(techName, "event", "timeupdate")) { this.manualTimeUpdatesOn(); } if (!_V_.techSupports(this.name, "event", "timeupdate")) {
})); this.player.manualTimeUpdatesOn();
}
}
// Initialize new tech if it hasn't been yet and load source // Initialize new tech if it hasn't been yet and load source
// Add tech element to player div // Add tech element to player div
if (this.techs[techName] === undefined) { if (this.techs[techName] === undefined) {
this.techs[techName] = this.tech = new _V_[techName](this, { source: source }); this.techs[techName] = this.tech = new _V_[techName](this, { source: source });
this.tech.ready(techReady)
} else { } else {
this.tech = this.techs[techName]; this.tech = this.techs[techName];
_V_.log("here3")
_V_.insertFirst(this.techs[techName].el, this.el); _V_.insertFirst(this.techs[techName].el, this.el);
this.src(source); this.src(source);
} }
@ -330,6 +329,10 @@ _V_.Player = _V_.Component.extend({
onPause: function(){ onPause: function(){
_V_.removeClass(this.el, "vjs-playing"); _V_.removeClass(this.el, "vjs-playing");
_V_.addClass(this.el, "vjs-paused"); _V_.addClass(this.el, "vjs-paused");
},
onError: function(e) {
_V_.log("Video Error", e);
} }
}); });
@ -342,7 +345,9 @@ _V_.Player.prototype.extend({
if (this.isReady) { if (this.isReady) {
return this.tech[method](arg); return this.tech[method](arg);
} else { } else {
throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."); _V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]")
return false;
// throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]");
} }
}, },
@ -506,6 +511,8 @@ _V_.Player.prototype.extend({
// Case: Array of source objects to choose from and pick the best to play // Case: Array of source objects to choose from and pick the best to play
if (source instanceof Array) { if (source instanceof Array) {
var sources = source;
techLoop: // Named loop for breaking both loops techLoop: // Named loop for breaking both loops
// Loop through each playback technology in the options order // Loop through each playback technology in the options order
for (var i=0,j=this.options.techOrder;i<j.length;i++) { for (var i=0,j=this.options.techOrder;i<j.length;i++) {
@ -517,7 +524,7 @@ _V_.Player.prototype.extend({
if (tech.isSupported()) { if (tech.isSupported()) {
// Loop through each source object // Loop through each source object
for (var a=0,b=this.options.sources;a<b.length;a++) { for (var a=0,b=sources;a<b.length;a++) {
var source = b[a]; var source = b[a];
// Check if source can be played with this technology // Check if source can be played with this technology
@ -540,12 +547,27 @@ _V_.Player.prototype.extend({
// Case: Source object { src: "", type: "" ... } // Case: Source object { src: "", type: "" ... }
} else if (source instanceof Object) { } else if (source instanceof Object) {
this.src(source.src); if (this.tech.canPlaySource(source)) {
this.src(source.src);
} else {
// Send through tech loop to check for a compatible technology.
this.src([source]);
}
// Case: URL String (http://myvideo...) // Case: URL String (http://myvideo...)
} else { } else {
this.apiCall("src", source); if (!this.isReady) {
this.load(); this.ready(function(){
this.src(source);
});
} else {
this.apiCall("src", source);
if (this.options.preload == "auto") {
this.load();
}
if (this.options.autoplay) {
// this.play();
}
}
} }
return this; return this;
}, },

View File

@ -11,7 +11,11 @@ _V_.PlaybackTech = _V_.Component.extend({
}, },
createElement: function(){}, createElement: function(){},
setupTriggers: function(){}, setupTriggers: function(){},
removeTriggers: function(){} removeTriggers: function(){},
canPlaySource: function(source){
return _V_[this.name].canPlaySource(source);
}
}); });
// Create placeholder methods for each that warn when a method // Create placeholder methods for each that warn when a method
@ -28,33 +32,35 @@ _V_.each(_V_.apiMethods, function(methodName){
_V_.HTML5 = _V_.PlaybackTech.extend({ _V_.HTML5 = _V_.PlaybackTech.extend({
name: "HTML5", name: "HTML5",
init: function(player, options){ init: function(player, options, ready){
this.player = player; this.player = player;
this.el = this.createElement(); this.el = this.createElement();
this.ready(ready);
var source = options.source; var source = options.source;
if (source && this.el.currentSrc != source.src) { // If the element source is already set, we may have missed the loadstart event, and want to trigger it.
this.el.src = source.src; // We don't want to set the source again and interrupt playback.
} else if (source) { if (source && this.el.currentSrc == source.src) {
player.triggerEvent("loadstart"); player.triggerEvent("loadstart");
// Otherwise set the source if one was provided.
} else if (source) {
this.el.src = source.src;
} }
// Moving video inside box breaks autoplay on Safari. This forces it to play. // Chrome and Safari both have issues with autoplay.
// Currently triggering play in other browsers as well. // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
player.addEvent("techready", function(){ // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
// This fixes both issues. Need to wait for API, so it updates displays correctly
player.ready(function(){
if (this.options.autoplay && this.paused()) { if (this.options.autoplay && this.paused()) {
this.tag.poster = null; // Chrome Fix. Fixed in Chrome v16.
this.play(); this.play();
} }
this.removeEvent("techready", arguments.callee);
}); });
// Trigger tech ready on player. this.triggerReady();
// TODO: Switch to component ready when available.
setTimeout(_V_.proxy(this, function(){
this.player.triggerEvent("techready");
}), 0);
}, },
createElement: function(){ createElement: function(){
@ -76,7 +82,8 @@ _V_.HTML5 = _V_.PlaybackTech.extend({
player.el.removeChild(el); player.el.removeChild(el);
el = newEl; el = newEl;
player.el.appendChild(el); _V_.log("here")
_V_.insertFirst(el, player.el);
} }
// Update tag settings, in case they were overridden // Update tag settings, in case they were overridden
@ -186,7 +193,7 @@ _V_.HTML5.isSupported = function(){
}; };
_V_.HTML5.canPlaySource = function(srcObj){ _V_.HTML5.canPlaySource = function(srcObj){
return !!document.createElement("video").canPlayType(srcObj.type); // Switch to global check return !!document.createElement("video").canPlayType(srcObj.type);
// TODO: Check Type // TODO: Check Type
// If no Type, check ext // If no Type, check ext
// Check Media Type // Check Media Type
@ -222,18 +229,19 @@ if (_V_.isAndroid()) {
_V_.H5swf = _V_.PlaybackTech.extend({ _V_.H5swf = _V_.PlaybackTech.extend({
name: "H5swf", name: "H5swf",
// swf: "flash/video-js.swf", swf: "flash/video-js.swf",
// swf: "https://s3.amazonaws.com/video-js/3.0b/video-js.swf", // swf: "https://s3.amazonaws.com/video-js/3.0b/video-js.swf",
// swf: "http://video-js.zencoder.com/3.0b/video-js.swf", // swf: "http://video-js.zencoder.com/3.0b/video-js.swf",
swf: "http://video-js.com/test/video-js.swf", // swf: "http://video-js.com/test/video-js.swf",
// swf: "http://video-js.com/source/flash/video-js.swf",
// swf: "http://video-js.com/source/flash/video-js.swf",
// swf: "video-js.swf", // swf: "video-js.swf",
init: function(player, options){ init: function(player, options){
this.player = player; this.player = player;
// this.el = this.createElement(); var placeHolder = this.el = _V_.createElement("div", { id: player.el.id + "_temp_h5swf" });
var source = options.source, var source = options.source,
placeHolder = this.el = _V_.createElement("div", { id: player.el.id + "_temp_h5swf" }),
objId = player.el.id+"_h5swf_api", objId = player.el.id+"_h5swf_api",
playerOptions = player.options; playerOptions = player.options;
@ -244,8 +252,7 @@ _V_.H5swf = _V_.PlaybackTech.extend({
autoplay: playerOptions.autoplay, autoplay: playerOptions.autoplay,
preload: playerOptions.preload, preload: playerOptions.preload,
loop: playerOptions.loop, loop: playerOptions.loop,
muted: playerOptions.muted, muted: playerOptions.muted
poster: playerOptions.poster
}, },
params = { params = {
@ -260,12 +267,16 @@ _V_.H5swf = _V_.PlaybackTech.extend({
'class': 'vjs-tech' 'class': 'vjs-tech'
}; };
if (playerOptions.poster) {
flashvars.poster = playerOptions.poster;
}
// If source was supplied pass as a flash var. // If source was supplied pass as a flash var.
if (source) { if (source) {
flashvars.src = source.src; flashvars.src = source.src;
} }
player.el.appendChild(placeHolder); _V_.insertFirst(placeHolder, player.el);
swfobject.embedSWF(options.swf || this.swf, placeHolder.id, "480", "270", "9.0.124", "", flashvars, params, attributes); swfobject.embedSWF(options.swf || this.swf, placeHolder.id, "480", "270", "9.0.124", "", flashvars, params, attributes);
}, },
@ -276,7 +287,16 @@ _V_.H5swf = _V_.PlaybackTech.extend({
play: function(){ this.el.vjs_play(); }, play: function(){ this.el.vjs_play(); },
pause: function(){ this.el.vjs_pause(); }, pause: function(){ this.el.vjs_pause(); },
src: function(src){ this.el.vjs_src(src); }, src: function(src){
this.el.vjs_src(src);
// Currently the SWF doesn't autoplay if you load a source later.
// e.g. Load player w/ no source, wait 2s, set src.
if (this.player.autoplay) {
// var tech = this;
// setTimeout(function(){ tech.play(); }, 0);
}
},
load: function(){ this.el.vjs_load(); }, load: function(){ this.el.vjs_load(); },
poster: function(){ this.el.vjs_getProperty("poster"); }, poster: function(){ this.el.vjs_getProperty("poster"); },
@ -347,24 +367,26 @@ _V_.H5swf.supports = {
}; };
_V_.H5swf.onSWFReady = function(currSwf){ _V_.H5swf.onSWFReady = function(currSwf){
_V_.log(currSwf, "currSwf")
// Flash seems to be catching errors, so raising them manally // Flash seems to be catching errors, so raising them manally
try { try {
// Delay for real swf ready. // Delay for real swf ready.
setTimeout(function(){ setTimeout(function(){
var el = _V_.el(currSwf), var el = _V_.el(currSwf);
// Get player from box // Get player from box
player = el.parentNode.player; var player = el.parentNode.player,
tech = player.techs["H5swf"];
// Reference player on tech element
el.player = player; el.player = player;
// Update reference to playback technology element // Update reference to playback technology element
player.techs["H5swf"].el = el; tech.el = el;
player.ready(function(){ tech.triggerReady();
// this.src("http://video-js.zencoder.com/oceans-clip.mp4");
});
player.triggerEvent("techready");
},0); },0);

Binary file not shown.