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