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 player.options.autoplay = true; 138 } 139 player.loadNode(data); 140 }; 141 })(this)); 142 }); 143 144 // Play each media sequentially... 145 this.get('media', function(media) { 146 media.ubind(this.uuid + ':ended', (function(player) { 147 return function() { 148 player.options.autoplay = true; 149 player.playNext(); 150 }; 151 })(this)); 152 }); 153 154 // Load the node if one is provided. 155 if (this.options.node) { 156 this.loadNode(this.options.node); 157 } 158 }; 159 160 /** 161 * Gets the full screen element. 162 * 163 * @return {object} The element that will go into fullscreen. 164 */ 165 osmplayer.prototype.fullScreenElement = function() { 166 return this.elements.minplayer; 167 }; 168 169 /** 170 * Reset the osmplayer. 171 * 172 * @param {function} callback Called when it is done resetting. 173 */ 174 osmplayer.prototype.reset = function(callback) { 175 176 // Empty the playqueue. 177 this.playQueue.length = 0; 178 this.playQueue = []; 179 this.playIndex = 0; 180 181 // Clear the playloader. 182 if (this.playLoader && this.options.preview) { 183 this.options.preview = ''; 184 this.playLoader.clear((function(player) { 185 return function() { 186 callback.call(player); 187 }; 188 })(this)); 189 } 190 else if (callback) { 191 callback.call(this); 192 } 193 }; 194 195 /** 196 * The load node function. 197 * 198 * @param {object} node A media node object. 199 * @return {boolean} If the node was loaded. 200 */ 201 osmplayer.prototype.loadNode = function(node) { 202 203 // Make sure this is a valid node. 204 if (!node || (node.hasOwnProperty('length') && (node.length === 0))) { 205 return false; 206 } 207 208 // Reset the player. 209 this.reset(function() { 210 211 // Set the hasMedia flag. 212 this.hasMedia = node && node.mediafiles && node.mediafiles.media; 213 214 // If this node is set and has files. 215 if (node && node.mediafiles) { 216 217 // Load the media files. 218 var media = node.mediafiles.media; 219 if (media) { 220 var file = null; 221 var types = []; 222 223 // For mobile devices, we should only show the main media. 224 if (minplayer.isAndroid || minplayer.isIDevice) { 225 types = ['media']; 226 } 227 else { 228 types = ['intro', 'commercial', 'prereel', 'media', 'postreel']; 229 } 230 231 // Iterate through the types. 232 jQuery.each(types, (function(player) { 233 return function(key, type) { 234 file = player.addToQueue(media[type]); 235 if (file) { 236 file.queueType = type; 237 } 238 }; 239 })(this)); 240 } 241 else { 242 243 // Add a class to the display to let themes handle this. 244 this.display.addClass('nomedia'); 245 } 246 247 // Play the next media 248 this.playNext(); 249 250 // Load the preview image. 251 osmplayer.getImage(node.mediafiles, 'preview', (function(player) { 252 return function(image) { 253 if (player.playLoader && (player.playLoader.display.length > 0)) { 254 player.playLoader.enabled = true; 255 player.playLoader.loadPreview(image.path); 256 player.playLoader.previewFlag.setFlag('media', true); 257 if (!player.hasMedia) { 258 player.playLoader.busy.setFlag('media', false); 259 player.playLoader.bigPlay.setFlag('media', false); 260 } 261 player.playLoader.checkVisibility(); 262 } 263 }; 264 })(this)); 265 } 266 }); 267 }; 268 269 /** 270 * Adds a file to the play queue. 271 * 272 * @param {object} file The file to add to the queue. 273 * @return {object} The file that was added to the queue. 274 */ 275 osmplayer.prototype.addToQueue = function(file) { 276 file = minplayer.getMediaFile(file); 277 if (file) { 278 this.playQueue.push(file); 279 } 280 return file; 281 }; 282 283 /** 284 * Plays the next media file in the queue. 285 */ 286 osmplayer.prototype.playNext = function() { 287 if (this.playQueue.length > this.playIndex) { 288 this.load(this.playQueue[this.playIndex]); 289 this.playIndex++; 290 } 291 else if (this.options.repeat) { 292 this.playIndex = 0; 293 this.playNext(); 294 } 295 else if (this.playQueue.length > 0) { 296 297 // If we have a playlist, let them handle what to do next. 298 if (this.hasPlaylist && this.options.autoNext) { 299 this.trigger('player_ended'); 300 } 301 else { 302 // If there is no playlist, and no repeat, we will 303 // just seek to the beginning and pause. 304 this.options.autoplay = false; 305 this.playIndex = 0; 306 this.playNext(); 307 } 308 } 309 else if (this.media) { 310 this.media.stop(); 311 312 // If there is no media found, then clear the player. 313 if (!this.hasMedia) { 314 this.media.clear(); 315 } 316 } 317 }; 318 319 /** 320 * Returns a node. 321 * 322 * @param {object} node The node to get. 323 * @param {function} callback Called when the node is retrieved. 324 */ 325 osmplayer.getNode = function(node, callback) { 326 if (node && node.mediafiles && node.mediafiles.media) { 327 var mediaFile = minplayer.getMediaFile(node.mediafiles.media.media); 328 if (mediaFile) { 329 var player = minplayer.players[mediaFile.player]; 330 if (player && (typeof player.getNode === 'function')) { 331 player.getNode(mediaFile, function(node) { 332 callback(node); 333 }); 334 } 335 } 336 } 337 }; 338 339 /** 340 * Returns an image provided image array. 341 * 342 * @param {object} mediafiles The mediafiles to search within. 343 * @param {string} type The type of image to look for. 344 * @param {function} callback Called when the image is retrieved. 345 */ 346 osmplayer.getImage = function(mediafiles, type, callback) { 347 348 var image = ''; 349 var images = mediafiles.image; 350 if (images) { 351 352 // If the image type exists, then just use that one... 353 if (images[type]) { 354 image = images[type]; 355 } 356 // Or try the original image... 357 else if (images.image) { 358 image = images.image; 359 } 360 // Otherwise, just try ANY image... 361 else { 362 363 // Or, just pick the first one available. 364 for (type in images) { 365 if (images.hasOwnProperty(type)) { 366 image = images[type]; 367 break; 368 } 369 } 370 } 371 } 372 373 // If the image exists, then callback with that image. 374 if (image) { 375 callback(new minplayer.file(image)); 376 } 377 else { 378 // Get the image from the media player... 379 var mediaFile = minplayer.getMediaFile(mediafiles.media.media); 380 if (mediaFile) { 381 var player = minplayer.players[mediaFile.player]; 382 if (player && (typeof player.getImage === 'function')) { 383 player.getImage(mediaFile, type, function(src) { 384 callback(new minplayer.file(src)); 385 }); 386 } 387 } 388 } 389 }; 390