1 /** The minplayer namespace. */ 2 var minplayer = minplayer || {}; 3 4 // Add a way to instanciate using jQuery prototype. 5 if (!jQuery.fn.minplayer) { 6 7 /** 8 * @constructor 9 * 10 * Define a jQuery minplayer prototype. 11 * 12 * @param {object} options The options for this jQuery prototype. 13 * @return {Array} jQuery object. 14 */ 15 jQuery.fn.minplayer = function(options) { 16 return jQuery(this).each(function() { 17 if (!minplayer.plugin.instances[options.id]) { 18 new minplayer.player(jQuery(this), options); 19 } 20 }); 21 }; 22 } 23 24 /** 25 * @constructor 26 * @extends minplayer.display 27 * @class The core media player class which governs the media player 28 * functionality. 29 * 30 * <p><strong>Usage:</strong> 31 * <pre><code> 32 * 33 * // Create a media player. 34 * var player = jQuery("#player").minplayer({ 35 * 36 * }); 37 * 38 * </code></pre> 39 * </p> 40 * 41 * @param {object} context The jQuery context. 42 * @param {object} options This components options. 43 */ 44 minplayer.player = function(context, options) { 45 46 // Make sure we provide default options... 47 options = jQuery.extend({ 48 id: 'player', 49 controller: 'default', 50 template: 'default', 51 swfplayer: '', 52 wmode: 'transparent', 53 preload: true, 54 autoplay: false, 55 loop: false, 56 width: '100%', 57 height: '350px', 58 debug: false, 59 volume: 80, 60 files: [], 61 file: '', 62 preview: '', 63 attributes: {} 64 }, options); 65 66 // Derive from display 67 minplayer.display.call(this, context, options); 68 }; 69 70 /** Derive from minplayer.display. */ 71 minplayer.player.prototype = new minplayer.display(); 72 73 /** Reset the constructor. */ 74 minplayer.player.prototype.constructor = minplayer.player; 75 76 /** 77 * @see minplayer.plugin.construct 78 */ 79 minplayer.player.prototype.construct = function() { 80 81 // Set the name of this plugin. 82 this.options.name = 'player'; 83 84 // Call the minplayer display constructor. 85 minplayer.display.prototype.construct.call(this); 86 87 /** Variable to store the current media player. */ 88 this.currentPlayer = 'html5'; 89 90 // Add key events to the window. 91 this.addKeyEvents(); 92 93 // Now load these files. 94 this.load(this.getFiles()); 95 }; 96 97 /** 98 * Sets an error on the player. 99 * 100 * @param {string} error The error to display on the player. 101 */ 102 minplayer.player.prototype.error = function(error) { 103 if (this.elements.error) { 104 105 // Set the error text. 106 this.elements.error.text(error); 107 if (error) { 108 this.elements.error.show(); 109 } 110 else { 111 this.elements.error.hide(); 112 } 113 } 114 }; 115 116 /** 117 * Adds key events to the player. 118 */ 119 minplayer.player.prototype.addKeyEvents = function() { 120 121 // Bind keyup to the current window. 122 jQuery(window).bind('keyup', {obj: this}, function(event) { 123 // Escape out of fullscreen if they press ESC or Q. 124 var isFull = event.data.obj.display.hasClass('fullscreen'); 125 if (isFull && (event.keyCode === 113 || event.keyCode === 27)) { 126 event.data.obj.display.removeClass('fullscreen'); 127 } 128 }); 129 }; 130 131 /** 132 * Returns all the media files available for this player. 133 * 134 * @return {array} All the media files for this player. 135 */ 136 minplayer.player.prototype.getFiles = function() { 137 var files = []; 138 var mediaSrc = null; 139 140 // Get the files involved... 141 if (this.elements.media) { 142 mediaSrc = this.elements.media.attr('src'); 143 if (mediaSrc) { 144 files.push({'path': mediaSrc}); 145 } 146 jQuery('source', this.elements.media).each(function() { 147 files.push({ 148 'path': jQuery(this).attr('src'), 149 'mimetype': jQuery(this).attr('type'), 150 'codecs': jQuery(this).attr('codecs') 151 }); 152 }); 153 } 154 155 return files; 156 }; 157 158 /** 159 * Returns the full media player object. 160 * @param {array} files An array of files to chose from. 161 * @return {object} The best media file to play in the current browser. 162 */ 163 minplayer.player.prototype.getMediaFile = function(files) { 164 165 // If there are no files then return null. 166 if (!files) { 167 return null; 168 } 169 170 // If the file is a single string, then return the file object. 171 if (typeof files === 'string') { 172 return new minplayer.file({'path': files}); 173 } 174 175 // If the file is already a file object then just return. 176 if (files.path) { 177 return new minplayer.file(files); 178 } 179 180 // Add the files and get the best player to play. 181 var i = files.length, bestPriority = 0, mFile = null, file = null; 182 while (i--) { 183 file = files[i]; 184 185 // Get the minplayer file object. 186 if (typeof file === 'string') { 187 file = new minplayer.file({'path': file}); 188 } 189 else { 190 file = new minplayer.file(file); 191 } 192 193 // Determine the best file for this browser. 194 if (file.priority > bestPriority) { 195 mFile = file; 196 } 197 } 198 199 // Return the best minplayer file. 200 return mFile; 201 }; 202 203 /** 204 * Load a set of files or a single file for the media player. 205 * 206 * @param {array} files An array of files to chose from to load. 207 */ 208 minplayer.player.prototype.load = function(files) { 209 210 // Set the id and class. 211 var id = '', pClass = ''; 212 213 // If no file was provided, then get it. 214 this.options.files = files || this.options.files; 215 this.options.file = this.getMediaFile(this.options.files); 216 217 // Do nothing if there isn't a file. 218 if (!this.options.file) { 219 this.error('No media found.'); 220 return; 221 } 222 223 if (!this.options.file.player) { 224 this.error('Cannot play media: ' + this.options.file.mimetype); 225 return; 226 } 227 228 // Reset the error. 229 this.error(); 230 231 // Only destroy if the current player is different than the new player. 232 var player = this.options.file.player.toString(); 233 234 // If there isn't media or if the players are different. 235 if (!this.player || (player !== this.currentPlayer)) { 236 237 // Set the current media player. 238 this.currentPlayer = player; 239 240 // The display for this media player. 241 var display = this.elements.display; 242 243 // Do nothing if we don't have a display. 244 if (!display) { 245 this.error('No media display found.'); 246 return; 247 } 248 249 // If the media exists, then destroy it. 250 if (this.player) { 251 this.player.destory(); 252 } 253 254 // Get the class name and create the new player. 255 pClass = minplayer.players[this.options.file.player]; 256 257 // Create the new media player. 258 var _this = this; 259 this.player = new pClass(display, this.options, function(player) { 260 261 // Iterate through each plugin. 262 _this.eachPlugin(function(plugin) { 263 264 // Set the player. 265 plugin.setPlayer(player); 266 267 // Bind to the error event. 268 plugin.bind('error', function(event, data) { 269 _this.error(data); 270 }); 271 272 // Bind to the fullscreen event. 273 plugin.bind('fullscreen', function(event, data) { 274 _this.resize(); 275 }); 276 }); 277 278 // Now load this media. 279 player.load(); 280 }); 281 } 282 283 // If the media object already exists... 284 else if (this.player) { 285 286 // Now load the different media file. 287 this.player.load(this.options.file); 288 } 289 }; 290 291 /** 292 * Called when the player is resized. 293 */ 294 minplayer.player.prototype.resize = function() { 295 296 // Call onRezie for each plugin. 297 this.eachPlugin(function(plugin) { 298 plugin.onResize(); 299 }); 300 }; 301 302 /** 303 * Play the currently loaded media file. Use load first to load a 304 * media file into the media player. 305 */ 306 minplayer.player.prototype.play = function() { 307 if (this.player) { 308 this.player.play(); 309 } 310 }; 311 312 /** 313 * Pause the media. 314 */ 315 minplayer.player.prototype.pause = function() { 316 if (this.player) { 317 this.player.pause(); 318 } 319 }; 320 321 /** 322 * Stop the media. 323 */ 324 minplayer.player.prototype.stop = function() { 325 if (this.player) { 326 this.player.stop(); 327 } 328 }; 329 330 /** 331 * Seek the media to the provided position. 332 * 333 * @param {number} pos The position to seek. 0 to 1. 334 */ 335 minplayer.player.prototype.seek = function(pos) { 336 if (this.player) { 337 this.player.seek(pos); 338 } 339 }; 340 341 /** 342 * Set the volume of the media being played. 343 * 344 * @param {number} vol The volume to set. 0 to 1. 345 */ 346 minplayer.player.prototype.setVolume = function(vol) { 347 if (this.player) { 348 this.player.setVolume(vol); 349 } 350 }; 351 352 /** 353 * Get the current volume setting. 354 * 355 * @param {function} callback The callback that is called when the volume 356 * is known. 357 * @return {number} The current volume level. 0 to 1. 358 */ 359 minplayer.player.prototype.getVolume = function(callback) { 360 return this.player ? this.player.getVolume(callback) : 0; 361 }; 362 363 /** 364 * Get the current media duration. 365 * 366 * @param {function} callback The callback that is called when the duration 367 * is known. 368 * @return {number} The current media duration. 369 */ 370 minplayer.player.prototype.getDuration = function(callback) { 371 return this.player ? this.player.getDuration(callback) : 0; 372 }; 373