1 /** The minplayer namespace. */ 2 var minplayer = minplayer || {}; 3 4 /** All the media player implementations */ 5 minplayer.players = minplayer.players || {}; 6 7 /** 8 * @constructor 9 * @extends minplayer.display 10 * @class The HTML5 media player implementation. 11 * 12 * @param {object} context The jQuery context. 13 * @param {object} options This components options. 14 * @param {object} queue The event queue to pass events around. 15 */ 16 minplayer.players.html5 = function(context, options, queue) { 17 18 // Derive players base. 19 minplayer.players.base.call(this, context, options, queue); 20 }; 21 22 /** Derive from minplayer.players.base. */ 23 minplayer.players.html5.prototype = new minplayer.players.base(); 24 25 /** Reset the constructor. */ 26 minplayer.players.html5.prototype.constructor = minplayer.players.html5; 27 28 /** 29 * @see minplayer.players.base#getPriority 30 * @return {number} The priority of this media player. 31 */ 32 minplayer.players.html5.getPriority = function() { 33 return 10; 34 }; 35 36 /** 37 * @see minplayer.players.base#canPlay 38 * @return {boolean} If this player can play this media type. 39 */ 40 minplayer.players.html5.canPlay = function(file) { 41 switch (file.mimetype) { 42 case 'video/ogg': 43 return !!minplayer.playTypes.videoOGG; 44 case 'video/mp4': 45 case 'video/x-mp4': 46 case 'video/m4v': 47 case 'video/x-m4v': 48 return !!minplayer.playTypes.videoH264; 49 case 'video/x-webm': 50 case 'video/webm': 51 case 'application/octet-stream': 52 return !!minplayer.playTypes.videoWEBM; 53 case 'audio/ogg': 54 return !!minplayer.playTypes.audioOGG; 55 case 'audio/mpeg': 56 return !!minplayer.playTypes.audioMP3; 57 case 'audio/mp4': 58 return !!minplayer.playTypes.audioMP4; 59 default: 60 return false; 61 } 62 }; 63 64 /** 65 * @see minplayer.plugin.construct 66 */ 67 minplayer.players.html5.prototype.construct = function() { 68 69 // Call base constructor. 70 minplayer.players.base.prototype.construct.call(this); 71 72 // For the HTML5 player, we will just pass events along... 73 if (this.player) { 74 75 this.player.addEventListener('abort', (function(player) { 76 return function() { 77 player.trigger('abort'); 78 }; 79 })(this), false); 80 this.player.addEventListener('loadstart', (function(player) { 81 return function() { 82 player.onReady(); 83 }; 84 })(this), false); 85 this.player.addEventListener('loadeddata', (function(player) { 86 return function() { 87 player.onLoaded(); 88 }; 89 })(this), false); 90 this.player.addEventListener('loadedmetadata', (function(player) { 91 return function() { 92 player.onLoaded(); 93 }; 94 })(this), false); 95 this.player.addEventListener('canplaythrough', (function(player) { 96 return function() { 97 player.onLoaded(); 98 }; 99 })(this), false); 100 this.player.addEventListener('ended', (function(player) { 101 return function() { 102 player.onComplete(); 103 }; 104 })(this), false); 105 this.player.addEventListener('pause', (function(player) { 106 return function() { 107 player.onPaused(); 108 }; 109 })(this), false); 110 this.player.addEventListener('play', (function(player) { 111 return function() { 112 player.onPlaying(); 113 }; 114 })(this), false); 115 this.player.addEventListener('playing', (function(player) { 116 return function() { 117 player.onPlaying(); 118 }; 119 })(this), false); 120 this.player.addEventListener('error', (function(player) { 121 return function() { 122 player.trigger('error', 'An error occured - ' + this.error.code); 123 }; 124 })(this), false); 125 this.player.addEventListener('waiting', (function(player) { 126 return function() { 127 player.onWaiting(); 128 }; 129 })(this), false); 130 this.player.addEventListener('durationchange', (function(player) { 131 return function() { 132 player.duration.set(this.duration); 133 player.trigger('durationchange', {duration: this.duration}); 134 }; 135 })(this), false); 136 this.player.addEventListener('progress', (function(player) { 137 return function(event) { 138 player.bytesTotal.set(event.total); 139 player.bytesLoaded.set(event.loaded); 140 }; 141 })(this), false); 142 143 // Say we are ready. 144 this.onReady(); 145 } 146 }; 147 148 /** 149 * @see minplayer.players.base#playerFound 150 * @return {boolean} TRUE - if the player is in the DOM, FALSE otherwise. 151 */ 152 minplayer.players.html5.prototype.playerFound = function() { 153 return (this.display.find(this.mediaFile.type).length > 0); 154 }; 155 156 /** 157 * @see minplayer.players.base#create 158 * @return {object} The media player entity. 159 */ 160 minplayer.players.html5.prototype.create = function() { 161 minplayer.players.base.prototype.create.call(this); 162 var element = jQuery(document.createElement(this.mediaFile.type)) 163 .attr(this.options.attributes) 164 .append( 165 jQuery(document.createElement('source')).attr({ 166 'src': this.mediaFile.path 167 }) 168 ); 169 170 // Fix the fluid width and height. 171 element.eq(0)[0].setAttribute('width', '100%'); 172 element.eq(0)[0].setAttribute('height', '100%'); 173 return element; 174 }; 175 176 /** 177 * @see minplayer.players.base#getPlayer 178 * @return {object} The media player object. 179 */ 180 minplayer.players.html5.prototype.getPlayer = function() { 181 return this.elements.media.eq(0)[0]; 182 }; 183 184 /** 185 * @see minplayer.players.base#load 186 */ 187 minplayer.players.html5.prototype.load = function(file) { 188 189 if (file) { 190 191 // Get the current source. 192 var src = this.elements.media.attr('src'); 193 if (!src) { 194 src = jQuery('source', this.elements.media).eq(0).attr('src'); 195 } 196 197 // If the source is different. 198 if (src != file.path) { 199 200 // Change the source... 201 var code = '<source src="' + file.path + '">'; 202 this.elements.media.removeAttr('src').empty().html(code); 203 } 204 } 205 206 // Always call the base first on load... 207 minplayer.players.base.prototype.load.call(this, file); 208 }; 209 210 /** 211 * @see minplayer.players.base#play 212 */ 213 minplayer.players.html5.prototype.play = function() { 214 minplayer.players.base.prototype.play.call(this); 215 if (this.isReady()) { 216 this.player.play(); 217 } 218 }; 219 220 /** 221 * @see minplayer.players.base#pause 222 */ 223 minplayer.players.html5.prototype.pause = function() { 224 minplayer.players.base.prototype.pause.call(this); 225 if (this.isReady()) { 226 this.player.pause(); 227 } 228 }; 229 230 /** 231 * @see minplayer.players.base#stop 232 */ 233 minplayer.players.html5.prototype.stop = function() { 234 minplayer.players.base.prototype.stop.call(this); 235 if (this.isReady()) { 236 this.player.pause(); 237 this.player.src = ''; 238 } 239 }; 240 241 /** 242 * @see minplayer.players.base#seek 243 */ 244 minplayer.players.html5.prototype.seek = function(pos) { 245 minplayer.players.base.prototype.seek.call(this, pos); 246 if (this.isReady()) { 247 this.player.currentTime = pos; 248 } 249 }; 250 251 /** 252 * @see minplayer.players.base#setVolume 253 */ 254 minplayer.players.html5.prototype.setVolume = function(vol) { 255 minplayer.players.base.prototype.setVolume.call(this, vol); 256 if (this.isReady()) { 257 this.player.volume = vol; 258 } 259 }; 260 261 /** 262 * @see minplayer.players.base#getVolume 263 */ 264 minplayer.players.html5.prototype.getVolume = function(callback) { 265 if (this.isReady()) { 266 callback(this.player.volume); 267 } 268 }; 269 270 /** 271 * @see minplayer.players.base#getDuration 272 */ 273 minplayer.players.html5.prototype.getDuration = function(callback) { 274 if (this.isReady()) { 275 callback(this.player.duration); 276 } 277 }; 278 279 /** 280 * @see minplayer.players.base#getCurrentTime 281 */ 282 minplayer.players.html5.prototype.getCurrentTime = function(callback) { 283 if (this.isReady()) { 284 callback(this.player.currentTime); 285 } 286 }; 287 288 /** 289 * @see minplayer.players.base#getBytesLoaded 290 */ 291 minplayer.players.html5.prototype.getBytesLoaded = function(callback) { 292 if (this.isReady()) { 293 var loaded = 0; 294 295 // Check several different possibilities. 296 if (this.bytesLoaded.value) { 297 loaded = this.bytesLoaded.value; 298 } 299 else if (this.player.buffered && 300 this.player.buffered.length > 0 && 301 this.player.buffered.end && 302 this.player.duration) { 303 loaded = this.player.buffered.end(0); 304 } 305 else if (this.player.bytesTotal != undefined && 306 this.player.bytesTotal > 0 && 307 this.player.bufferedBytes != undefined) { 308 loaded = this.player.bufferedBytes; 309 } 310 311 // Return the loaded amount. 312 callback(loaded); 313 } 314 }; 315 316 /** 317 * @see minplayer.players.base#getBytesTotal 318 */ 319 minplayer.players.html5.prototype.getBytesTotal = function(callback) { 320 if (this.isReady()) { 321 322 var total = 0; 323 324 // Check several different possibilities. 325 if (this.bytesTotal.value) { 326 total = this.bytesTotal.value; 327 } 328 else if (this.player.buffered && 329 this.player.buffered.length > 0 && 330 this.player.buffered.end && 331 this.player.duration) { 332 total = this.player.duration; 333 } 334 else if (this.player.bytesTotal != undefined && 335 this.player.bytesTotal > 0 && 336 this.player.bufferedBytes != undefined) { 337 total = this.player.bytesTotal; 338 } 339 340 // Return the loaded amount. 341 callback(total); 342 } 343 }; 344