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