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.instances[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 // Log this to console. 128 minplayer.console.log(data); 129 130 // If an error occurs within the html5 media player, then try 131 // to fall back to the flash player. 132 if (_this.currentPlayer == 'html5') { 133 _this.options.file.player = 'minplayer'; 134 _this.loadPlayer(); 135 } 136 else { 137 _this.error(data); 138 } 139 }); 140 141 // Bind to the fullscreen event. 142 plugin.bind('fullscreen', function(event, data) { 143 _this.resize(); 144 }); 145 }); 146 }; 147 148 /** 149 * Sets an error on the player. 150 * 151 * @param {string} error The error to display on the player. 152 */ 153 minplayer.prototype.error = function(error) { 154 error = error || ''; 155 if (this.elements.error) { 156 157 // Set the error text. 158 this.elements.error.text(error); 159 if (error) { 160 this.elements.error.show(); 161 } 162 else { 163 this.elements.error.hide(); 164 } 165 } 166 }; 167 168 /** 169 * Adds key events to the player. 170 */ 171 minplayer.prototype.addKeyEvents = function() { 172 173 // Bind keyup to the current window. 174 jQuery(window).bind('keyup', {obj: this}, function(event) { 175 // Escape out of fullscreen if they press ESC or Q. 176 var isFull = event.data.obj.display.hasClass('fullscreen'); 177 if (isFull && (event.keyCode === 113 || event.keyCode === 27)) { 178 event.data.obj.display.removeClass('fullscreen'); 179 } 180 }); 181 }; 182 183 /** 184 * Returns all the media files available for this player. 185 * 186 * @return {array} All the media files for this player. 187 */ 188 minplayer.prototype.getFiles = function() { 189 var files = []; 190 var mediaSrc = null; 191 192 // Get the files involved... 193 if (this.elements.media) { 194 mediaSrc = this.elements.media.attr('src'); 195 if (mediaSrc) { 196 files.push({'path': mediaSrc}); 197 } 198 jQuery('source', this.elements.media).each(function() { 199 files.push({ 200 'path': jQuery(this).attr('src'), 201 'mimetype': jQuery(this).attr('type'), 202 'codecs': jQuery(this).attr('codecs') 203 }); 204 }); 205 } 206 207 return files; 208 }; 209 210 /** 211 * Returns the full media player object. 212 * @param {array} files An array of files to chose from. 213 * @return {object} The best media file to play in the current browser. 214 */ 215 minplayer.prototype.getMediaFile = function(files) { 216 217 // If there are no files then return null. 218 if (!files) { 219 return null; 220 } 221 222 // If the file is a single string, then return the file object. 223 if (typeof files === 'string') { 224 return new minplayer.file({'path': files}); 225 } 226 227 // If the file is already a file object then just return. 228 if (files.path) { 229 return new minplayer.file(files); 230 } 231 232 // Add the files and get the best player to play. 233 var i = files.length, bestPriority = 0, mFile = null, file = null; 234 while (i--) { 235 file = files[i]; 236 237 // Get the minplayer file object. 238 if (typeof file === 'string') { 239 file = new minplayer.file({'path': file}); 240 } 241 else { 242 file = new minplayer.file(file); 243 } 244 245 // Determine the best file for this browser. 246 if (file.priority > bestPriority) { 247 mFile = file; 248 } 249 } 250 251 // Return the best minplayer file. 252 return mFile; 253 }; 254 255 /** 256 * Loads a media player based on the current file. 257 */ 258 minplayer.prototype.loadPlayer = function() { 259 260 // Do nothing if there isn't a file. 261 if (!this.options.file) { 262 this.error('No media found.'); 263 return; 264 } 265 266 if (!this.options.file.player) { 267 this.error('Cannot play media: ' + this.options.file.mimetype); 268 return; 269 } 270 271 // Reset the error. 272 this.error(); 273 274 // Only destroy if the current player is different than the new player. 275 var player = this.options.file.player.toString(); 276 277 // If there isn't media or if the players are different. 278 if (!this.media || (player !== this.currentPlayer)) { 279 280 // Set the current media player. 281 this.currentPlayer = player; 282 283 // Do nothing if we don't have a display. 284 if (!this.elements.display) { 285 this.error('No media display found.'); 286 return; 287 } 288 289 // Store the queue. 290 var queue = this.media ? this.media.queue : {}; 291 292 // Destroy the current media. 293 if (this.media) { 294 this.media.destroy(); 295 } 296 297 // Get the class name and create the new player. 298 pClass = minplayer.players[this.options.file.player]; 299 300 // Create the new media player. 301 this.media = new pClass(this.elements.display, this.options); 302 303 // Restore the queue. 304 this.media.queue = queue; 305 306 // Now get the media when it is ready. 307 this.get('media', function(media) { 308 309 // Load the media. 310 media.load(); 311 }); 312 } 313 // If the media object already exists... 314 else if (this.media) { 315 316 // Now load the different media file. 317 this.media.load(this.options.file); 318 } 319 }; 320 321 /** 322 * Load a set of files or a single file for the media player. 323 * 324 * @param {array} files An array of files to chose from to load. 325 */ 326 minplayer.prototype.load = function(files) { 327 328 // Set the id and class. 329 var id = '', pClass = ''; 330 331 // If no file was provided, then get it. 332 this.options.files = files || this.options.files; 333 this.options.file = this.getMediaFile(this.options.files); 334 335 // Now load the player. 336 this.loadPlayer(); 337 }; 338 339 /** 340 * Called when the player is resized. 341 */ 342 minplayer.prototype.resize = function() { 343 344 // Call onRezie for each plugin. 345 this.eachPlugin(function(name, plugin) { 346 plugin.onResize(); 347 }); 348 }; 349