1 // Add a way to instanciate using jQuery prototype. 2 if (!jQuery.fn.osmplayer) { 3 4 /** 5 * A special jQuery event to handle the player being removed from DOM. 6 * 7 * @this The element that is being triggered with. 8 **/ 9 jQuery.event.special.playerdestroyed = { 10 remove: function(o) { 11 if (o.handler) { 12 o.handler(this); 13 } 14 } 15 }; 16 17 /** 18 * @constructor 19 * 20 * Define a jQuery osmplayer prototype. 21 * 22 * @param {object} options The options for this jQuery prototype. 23 * @return {Array} jQuery object. 24 */ 25 jQuery.fn.osmplayer = function(options) { 26 return jQuery(this).each(function() { 27 options = options || {}; 28 options.id = options.id || jQuery(this).attr('id') || Math.random(); 29 if (!minplayer.plugins[options.id]) { 30 options.template = options.template || 'default'; 31 if (osmplayer[options.template]) { 32 new osmplayer[options.template](jQuery(this), options); 33 } 34 else { 35 new osmplayer(jQuery(this), options); 36 } 37 } 38 }); 39 }; 40 } 41 42 /** 43 * @constructor 44 * @extends minplayer 45 * @class The main osmplayer class. 46 * 47 * <p><strong>Usage:</strong> 48 * <pre><code> 49 * 50 * // Create a media player. 51 * var player = jQuery("#player").osmplayer({ 52 * 53 * }); 54 * 55 * </code></pre> 56 * </p> 57 * 58 * @param {object} context The jQuery context. 59 * @param {object} options This components options. 60 */ 61 osmplayer = function(context, options) { 62 63 // Derive from minplayer 64 minplayer.call(this, context, options); 65 }; 66 67 /** Derive from minplayer. */ 68 osmplayer.prototype = new minplayer(); 69 70 /** Reset the constructor. */ 71 osmplayer.prototype.constructor = osmplayer; 72 73 /** 74 * Creates a new plugin within this context. 75 * 76 * @param {string} name The name of the plugin you wish to create. 77 * @param {object} base The base object for this plugin. 78 * @param {object} context The context which you would like to create. 79 * @return {object} The new plugin object. 80 */ 81 osmplayer.prototype.create = function(name, base, context) { 82 return minplayer.prototype.create.call(this, name, 'osmplayer', context); 83 }; 84 85 /** 86 * Get the default options for this plugin. 87 * 88 * @param {object} options The default options for this plugin. 89 */ 90 osmplayer.prototype.defaultOptions = function(options) { 91 options.playlist = ''; 92 options.node = {}; 93 options.link = 'http://www.mediafront.org'; 94 options.logo = 'http://mediafront.org/assets/osmplayer/logo.png'; 95 minplayer.prototype.defaultOptions.call(this, options); 96 }; 97 98 /** 99 * @see minplayer.plugin.construct 100 */ 101 osmplayer.prototype.construct = function() { 102 103 // Call the minplayer display constructor. 104 minplayer.prototype.construct.call(this); 105 106 // We need to cleanup the player when it has been destroyed. 107 jQuery(this.display).bind('playerdestroyed', (function(player) { 108 return function(element) { 109 if (element === player.display.eq(0)[0]) { 110 for (var plugin in minplayer.plugins[player.options.id]) { 111 for (var index in minplayer.plugins[player.options.id][plugin]) { 112 minplayer.plugins[player.options.id][plugin][index].destroy(); 113 delete minplayer.plugins[player.options.id][plugin][index]; 114 } 115 minplayer.plugins[player.options.id][plugin].length = 0; 116 } 117 delete minplayer.plugins[player.options.id]; 118 minplayer.plugins[player.options.id] = null; 119 } 120 }; 121 })(this)); 122 123 /** The play queue and index. */ 124 this.playQueue = []; 125 this.playIndex = 0; 126 this.hasPlaylist = false; 127 128 /** The playlist for this media player. */ 129 this.create('playlist', 'osmplayer'); 130 131 /** Get the playlist or any other playlist that connects. */ 132 this.get('playlist', function(playlist) { 133 playlist.ubind(this.uuid + ':nodeLoad', (function(player) { 134 return function(event, data) { 135 player.hasPlaylist = true; 136 if (!player.options.autoplay && !!data.autoplay) { 137 if (typeof player.options.originalAutoPlay == 'undefined') { 138 player.options.originalAutoPlay = player.options.autoplay; 139 } 140 player.options.autoplay = true; 141 } 142 player.loadNode(data); 143 }; 144 })(this)); 145 }); 146 147 // Play each media sequentially... 148 this.get('media', function(media) { 149 media.ubind(this.uuid + ':ended', (function(player) { 150 return function() { 151 if (typeof player.options.originalAutoPlay == 'undefined') { 152 player.options.originalAutoPlay = player.options.autoplay; 153 } 154 player.options.autoplay = true; 155 player.playNext(); 156 }; 157 })(this)); 158 }); 159 160 // Load the node if one is provided. 161 this.loadNode(this.options.node); 162 }; 163 164 /** 165 * Gets the full screen element. 166 * 167 * @return {object} The element that will go into fullscreen. 168 */ 169 osmplayer.prototype.fullScreenElement = function() { 170 return this.elements.minplayer; 171 }; 172 173 /** 174 * Reset the osmplayer. 175 * 176 * @param {function} callback Called when it is done resetting. 177 */ 178 osmplayer.prototype.reset = function(callback) { 179 180 // Empty the playqueue. 181 this.playQueue.length = 0; 182 this.playQueue = []; 183 this.playIndex = 0; 184 185 // Clear the playloader. 186 if (this.playLoader && this.options.preview) { 187 this.options.preview = ''; 188 this.playLoader.clear((function(player) { 189 return function() { 190 callback.call(player); 191 }; 192 })(this)); 193 } 194 else if (callback) { 195 callback.call(this); 196 } 197 }; 198 199 /** 200 * The load node function. 201 * 202 * @param {object} node A media node object. 203 * @return {boolean} If the node was loaded. 204 */ 205 osmplayer.prototype.loadNode = function(node) { 206 207 // Make sure this is a valid node. 208 if (!node || (node.hasOwnProperty('length') && (node.length === 0))) { 209 return false; 210 } 211 212 // Reset the player. 213 this.reset(function() { 214 215 // Set the hasMedia flag. 216 this.hasMedia = node && node.mediafiles && node.mediafiles.media; 217 this.hasMedia = this.hasMedia || this.options.file; 218 219 // If this node is set and has files. 220 if (node && node.mediafiles) { 221 222 // Load the media files. 223 var media = node.mediafiles.media; 224 if (media) { 225 var file = null; 226 var types = []; 227 228 // For mobile devices, we should only show the main media. 229 if (minplayer.isAndroid || minplayer.isIDevice) { 230 types = ['media']; 231 } 232 else { 233 types = ['intro', 'commercial', 'prereel', 'media', 'postreel']; 234 } 235 236 // Iterate through the types. 237 jQuery.each(types, (function(player) { 238 return function(key, type) { 239 file = player.addToQueue(media[type]); 240 if (file) { 241 file.queueType = type; 242 } 243 }; 244 })(this)); 245 } 246 else { 247 248 // Add a class to the display to let themes handle this. 249 this.display.addClass('nomedia'); 250 } 251 252 // Play the next media 253 this.playNext(); 254 255 // Load the preview image. 256 osmplayer.getImage(node.mediafiles, 'preview', (function(player) { 257 return function(image) { 258 if (player.playLoader && (player.playLoader.display.length > 0)) { 259 player.playLoader.enabled = true; 260 player.playLoader.loadPreview(image.path); 261 player.playLoader.previewFlag.setFlag('media', true); 262 if (!player.hasMedia) { 263 player.playLoader.busy.setFlag('media', false); 264 player.playLoader.bigPlay.setFlag('media', false); 265 } 266 player.playLoader.checkVisibility(); 267 } 268 }; 269 })(this)); 270 } 271 }); 272 }; 273 274 /** 275 * Adds a file to the play queue. 276 * 277 * @param {object} file The file to add to the queue. 278 * @return {object} The file that was added to the queue. 279 */ 280 osmplayer.prototype.addToQueue = function(file) { 281 file = minplayer.getMediaFile(file); 282 if (file) { 283 this.playQueue.push(file); 284 } 285 return file; 286 }; 287 288 /** 289 * Plays the next media file in the queue. 290 */ 291 osmplayer.prototype.playNext = function() { 292 if (this.playQueue.length > this.playIndex) { 293 this.load(this.playQueue[this.playIndex]); 294 this.playIndex++; 295 } 296 else if (this.options.repeat) { 297 this.playIndex = 0; 298 this.playNext(); 299 } 300 else if (this.playQueue.length > 0) { 301 302 // If we have a playlist, let them handle what to do next. 303 if (this.hasPlaylist && this.options.autoNext) { 304 this.trigger('player_ended'); 305 } 306 else { 307 // If there is no playlist, and no repeat, we will 308 // just seek to the beginning and pause. 309 this.options.autoplay = false; 310 this.playIndex = 0; 311 this.playNext(); 312 } 313 } 314 else if (this.media) { 315 316 // Reset the autoplay variable. 317 if (typeof this.options.originalAutoPlay != 'undefined') { 318 this.options.autoplay = this.options.originalAutoPlay; 319 } 320 321 this.media.stop(); 322 323 // Load the media again. 324 if (this.options.file) { 325 this.load(); 326 } 327 else { 328 this.loadNode(); 329 } 330 } 331 }; 332 333 /** 334 * Returns a node. 335 * 336 * @param {object} node The node to get. 337 * @param {function} callback Called when the node is retrieved. 338 */ 339 osmplayer.getNode = function(node, callback) { 340 if (node && node.mediafiles && node.mediafiles.media) { 341 var mediaFile = minplayer.getMediaFile(node.mediafiles.media.media); 342 if (mediaFile) { 343 var player = minplayer.players[mediaFile.player]; 344 if (player && (typeof player.getNode === 'function')) { 345 player.getNode(mediaFile, function(node) { 346 callback(node); 347 }); 348 } 349 } 350 } 351 }; 352 353 /** 354 * Returns an image provided image array. 355 * 356 * @param {object} mediafiles The mediafiles to search within. 357 * @param {string} type The type of image to look for. 358 * @param {function} callback Called when the image is retrieved. 359 */ 360 osmplayer.getImage = function(mediafiles, type, callback) { 361 362 var image = ''; 363 var images = mediafiles.image; 364 if (images) { 365 366 // If the image type exists, then just use that one... 367 if (images[type]) { 368 image = images[type]; 369 } 370 // Or try the original image... 371 else if (images.image) { 372 image = images.image; 373 } 374 // Otherwise, just try ANY image... 375 else { 376 377 // Or, just pick the first one available. 378 for (type in images) { 379 if (images.hasOwnProperty(type)) { 380 image = images[type]; 381 break; 382 } 383 } 384 } 385 } 386 387 // If the image exists, then callback with that image. 388 if (image) { 389 callback(new minplayer.file(image)); 390 } 391 else { 392 // Get the image from the media player... 393 var mediaFile = minplayer.getMediaFile(mediafiles.media.media); 394 if (mediaFile) { 395 var player = minplayer.players[mediaFile.player]; 396 if (player && (typeof player.getImage === 'function')) { 397 player.getImage(mediaFile, type, function(src) { 398 callback(new minplayer.file(src)); 399 }); 400 } 401 } 402 } 403 }; 404