1 /** The minplayer namespace. */ 2 var minplayer = minplayer || {}; 3 4 /** All the media player implementations */ 5 minplayer.players = minplayer.players || {}; 6 7 /** 8 * @constructor 9 * @extends minplayer.players.base 10 * @class The YouTube media player. 11 * 12 * @param {object} context The jQuery context. 13 * @param {object} options This components options. 14 */ 15 minplayer.players.youtube = function(context, options) { 16 17 /** The quality of the YouTube stream. */ 18 this.quality = 'default'; 19 20 // Derive from players base. 21 minplayer.players.base.call(this, context, options); 22 }; 23 24 /** Derive from minplayer.players.base. */ 25 minplayer.players.youtube.prototype = new minplayer.players.base(); 26 27 /** Reset the constructor. */ 28 minplayer.players.youtube.prototype.constructor = minplayer.players.youtube; 29 30 /** 31 * @see minplayer.players.base#getPriority 32 * @return {number} The priority of this media player. 33 */ 34 minplayer.players.youtube.getPriority = function() { 35 return 10; 36 }; 37 38 /** 39 * @see minplayer.players.base#canPlay 40 * @return {boolean} If this player can play this media type. 41 */ 42 minplayer.players.youtube.canPlay = function(file) { 43 44 // Check for the mimetype for youtube. 45 if (file.mimetype === 'video/youtube') { 46 return true; 47 } 48 49 // If the path is a YouTube path, then return true. 50 return (file.path.search(/^http(s)?\:\/\/(www\.)?youtube\.com/i) === 0); 51 }; 52 53 /** 54 * Return the ID for a provided media file. 55 * 56 * @param {object} file A {@link minplayer.file} object. 57 * @return {string} The ID for the provided media. 58 */ 59 minplayer.players.youtube.getMediaId = function(file) { 60 var regex = /^http[s]?\:\/\/(www\.)?youtube\.com\/watch\?v=([a-zA-Z0-9]+)/i; 61 if (file.path.search(regex) === 0) { 62 return file.path.replace(regex, '$2'); 63 } 64 else { 65 return file.path; 66 } 67 }; 68 69 /** 70 * Register this youtube player so that multiple players can be present 71 * on the same page without event collision. 72 */ 73 minplayer.players.youtube.prototype.register = function() { 74 75 /** 76 * Register the standard youtube api ready callback. 77 */ 78 window.onYouTubePlayerAPIReady = function() { 79 80 // Iterate over each media player. 81 jQuery.each(minplayer.get(null, 'player'), function(id, player) { 82 83 // Make sure this is the youtube player. 84 if (player.currentPlayer == 'youtube') { 85 86 // Create a new youtube player object for this instance only. 87 var playerId = id + '-player'; 88 89 // Set this players media. 90 player.media.player = new YT.Player(playerId, { 91 events: { 92 'onReady': function(event) { 93 player.media.onReady(event); 94 }, 95 'onStateChange': function(event) { 96 player.media.onPlayerStateChange(event); 97 }, 98 'onPlaybackQualityChange': function(newQuality) { 99 player.media.onQualityChange(newQuality); 100 }, 101 'onError': function(errorCode) { 102 player.media.onError(errorCode); 103 } 104 } 105 }); 106 } 107 }); 108 } 109 }; 110 111 /** 112 * Translates the player state for the YouTube API player. 113 * 114 * @param {number} playerState The YouTube player state. 115 */ 116 minplayer.players.youtube.prototype.setPlayerState = function(playerState) { 117 switch (playerState) { 118 case YT.PlayerState.CUED: 119 break; 120 case YT.PlayerState.BUFFERING: 121 this.onWaiting(); 122 break; 123 case YT.PlayerState.PAUSED: 124 this.onPaused(); 125 break; 126 case YT.PlayerState.PLAYING: 127 this.onPlaying(); 128 break; 129 case YT.PlayerState.ENDED: 130 this.onComplete(); 131 break; 132 default: 133 break; 134 } 135 }; 136 137 /** 138 * Called when an error occurs. 139 * 140 * @param {string} event The onReady event that was triggered. 141 */ 142 minplayer.players.youtube.prototype.onReady = function(event) { 143 minplayer.players.base.prototype.onReady.call(this); 144 this.onLoaded(); 145 }; 146 147 /** 148 * Checks to see if this player can be found. 149 * @return {bool} TRUE - Player is found, FALSE - otherwise. 150 */ 151 minplayer.players.youtube.prototype.playerFound = function() { 152 var iframe = this.display.find('iframe#' + this.options.id + '-player'); 153 return (iframe.length > 0); 154 }; 155 156 /** 157 * Called when the player state changes. 158 * 159 * @param {object} event A JavaScript Event. 160 */ 161 minplayer.players.youtube.prototype.onPlayerStateChange = function(event) { 162 this.setPlayerState(event.data); 163 }; 164 165 /** 166 * Called when the player quality changes. 167 * 168 * @param {string} newQuality The new quality for the change. 169 */ 170 minplayer.players.youtube.prototype.onQualityChange = function(newQuality) { 171 this.quality = newQuality; 172 }; 173 174 /** 175 * Determines if the player should show the playloader. 176 * 177 * @return {bool} If this player implements its own playLoader. 178 */ 179 minplayer.players.youtube.prototype.hasPlayLoader = function() { 180 return true; 181 }; 182 183 /** 184 * @see minplayer.players.base#create 185 * @return {object} The media player entity. 186 */ 187 minplayer.players.youtube.prototype.create = function() { 188 minplayer.players.base.prototype.create.call(this); 189 190 // Insert the YouTube iframe API player. 191 var tag = document.createElement('script'); 192 tag.src = 'http://www.youtube.com/player_api?enablejsapi=1'; 193 var firstScriptTag = document.getElementsByTagName('script')[0]; 194 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 195 196 // Now register this player. 197 this.register(); 198 199 // Create the iframe for this player. 200 var iframe = document.createElement('iframe'); 201 iframe.setAttribute('id', this.options.id + '-player'); 202 iframe.setAttribute('type', 'text/html'); 203 iframe.setAttribute('width', '100%'); 204 iframe.setAttribute('height', '100%'); 205 iframe.setAttribute('frameborder', '0'); 206 207 // Get the source. 208 var src = 'http://www.youtube.com/embed/'; 209 src += this.mediaFile.id + '?'; 210 211 // Determine the origin of this script. 212 var origin = location.protocol; 213 origin += '//' + location.hostname; 214 origin += (location.port && ':' + location.port); 215 216 // Add the parameters to the src. 217 src += jQuery.param({ 218 'wmode': 'opaque', 219 'controls': 0, 220 'enablejsapi': 1, 221 'origin': origin, 222 'autoplay': this.options.autoplay, 223 'loop': this.options.loop 224 }); 225 226 // Set the source of the iframe. 227 iframe.setAttribute('src', src); 228 229 // Return the player. 230 return iframe; 231 }; 232 233 /** 234 * @see minplayer.players.base#load 235 */ 236 minplayer.players.youtube.prototype.load = function(file) { 237 minplayer.players.base.prototype.load.call(this, file); 238 if (file && this.isReady()) { 239 this.player.loadVideoById(file.id, 0, this.quality); 240 } 241 }; 242 243 /** 244 * @see minplayer.players.base#play 245 */ 246 minplayer.players.youtube.prototype.play = function() { 247 minplayer.players.base.prototype.play.call(this); 248 if (this.isReady()) { 249 this.player.playVideo(); 250 } 251 }; 252 253 /** 254 * @see minplayer.players.base#pause 255 */ 256 minplayer.players.youtube.prototype.pause = function() { 257 minplayer.players.base.prototype.pause.call(this); 258 if (this.isReady()) { 259 this.player.pauseVideo(); 260 } 261 }; 262 263 /** 264 * @see minplayer.players.base#stop 265 */ 266 minplayer.players.youtube.prototype.stop = function() { 267 minplayer.players.base.prototype.stop.call(this); 268 if (this.isReady()) { 269 this.player.stopVideo(); 270 } 271 }; 272 273 /** 274 * @see minplayer.players.base#seek 275 */ 276 minplayer.players.youtube.prototype.seek = function(pos) { 277 minplayer.players.base.prototype.seek.call(this, pos); 278 if (this.isReady()) { 279 this.player.seekTo(pos, true); 280 } 281 }; 282 283 /** 284 * @see minplayer.players.base#setVolume 285 */ 286 minplayer.players.youtube.prototype.setVolume = function(vol) { 287 minplayer.players.base.prototype.setVolume.call(this, vol); 288 if (this.isReady()) { 289 this.player.setVolume(vol * 100); 290 } 291 }; 292 293 /** 294 * @see minplayer.players.base#getVolume 295 */ 296 minplayer.players.youtube.prototype.getVolume = function(callback) { 297 if (this.isReady()) { 298 callback(this.player.getVolume()); 299 } 300 }; 301 302 /** 303 * @see minplayer.players.base#getDuration. 304 */ 305 minplayer.players.youtube.prototype.getDuration = function(callback) { 306 if (this.isReady()) { 307 callback(this.player.getDuration()); 308 } 309 }; 310 311 /** 312 * @see minplayer.players.base#getCurrentTime 313 */ 314 minplayer.players.youtube.prototype.getCurrentTime = function(callback) { 315 if (this.isReady()) { 316 callback(this.player.getCurrentTime()); 317 } 318 }; 319 320 /** 321 * @see minplayer.players.base#getBytesStart. 322 */ 323 minplayer.players.youtube.prototype.getBytesStart = function(callback) { 324 if (this.isReady()) { 325 callback(this.player.getVideoStartBytes()); 326 } 327 }; 328 329 /** 330 * @see minplayer.players.base#getBytesLoaded. 331 */ 332 minplayer.players.youtube.prototype.getBytesLoaded = function(callback) { 333 if (this.isReady()) { 334 callback(this.player.getVideoBytesLoaded()); 335 } 336 }; 337 338 /** 339 * @see minplayer.players.base#getBytesTotal. 340 */ 341 minplayer.players.youtube.prototype.getBytesTotal = function(callback) { 342 if (this.isReady()) { 343 callback(this.player.getVideoBytesTotal()); 344 } 345 }; 346