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