1 /**
  2  * @author Gillis Haasnoot <gillis.haasnoot@gmail.com>
  3  * @package Banana.Controls
  4  * @summary Youtube iframe player experimental control.
  5  */
  6 
  7 goog.provide('Banana.Controls.YoutubeIFramePlayer');
  8 
  9 /** @namespace Banana.Controls.YoutubeIFramePlayer*/
 10 namespace('Banana.Controls').YoutubeIFramePlayer = Banana.Controls.Panel.extend({
 11 /** @lends Banana.Controls.YoutubeIFramePlayer.prototype */
 12 	
 13 	/**
 14 	 * Creates highly experimental youtube iframe player
 15 	 * 
 16 	 * Example:
 17 	 
 18 		var player = new YoutubeIFramePlayer(400,300);
 19     	player.bind('onPlayerReady',this.getProxy(function(){
 20     	
 21     		p.setVolume(0);
 22     		p.loadVideoById("Hyw7OYU0_mE");
 23     		 		
 24     	}));
 25     	
 26     	//event triggered when duration of the videoitem is known
 27     	player.bind('onDurationKnown',this.getProxy(function(e,time){
 28  
 29     		console.log(time.getTime());
 30     	}))
 31 	 
 32 	 
 33 	 * @constructs
 34 	 * @extends Banana.Controls.Panel
 35 	 */
 36 	init : function(width,height)
 37 	{
 38 		this._super();
 39 		
 40 		this.height = height;
 41 		this.width = width;
 42 		
 43 		this.createRequiredApiStructures();
 44 	},
 45 	
 46 	createRequiredApiStructures : function()
 47 	{
 48 		//load required script files. we do this only once
 49 		//other player instances wont load these scripts again
 50 		if (!window.youtubeApiScripsLoaded)
 51 		{
 52 			var tag = document.createElement('script');
 53 			tag.src = "http://www.youtube.com/player_api?wmode=transparent";
 54 			var firstScriptTag = document.getElementsByTagName('script')[0];
 55 			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
 56 			
 57 			window.youtubeApiScripsLoaded = true;
 58 		}
 59 		
 60 		//make player globally available to get access from onYouTubePlayerReadyevent	
 61 		if (!window.queuedBananaYouTubePlayers)
 62 		{
 63 			window.queuedBananaYouTubePlayers = [];
 64 		}
 65 		
 66 		if (!window.youtubeApiReadyCallback)
 67 		{
 68 			//after api is ready we create the queued players
 69 			window.onYouTubePlayerAPIReady= function(id) 
 70 			{
 71 				for (var i =0; i < window.queuedBananaYouTubePlayers.length; i++)
 72 				{
 73 					window.queuedBananaYouTubePlayers[i]();
 74 				}
 75 				
 76 				window.youtubeApiReady = true;
 77 			}
 78 		}
 79 	},
 80 	
 81 	isApiReady : function()
 82 	{
 83 		return window.youtubeApiReady == true;
 84 	},
 85 	
 86 	unload : function()
 87 	{
 88 		//these are not automatically cleaned by banana
 89 		window.queuedBananaYouTubePlayers = undefined;
 90 	},
 91 	
 92 	createComponents : function()
 93 	{
 94 		this.placeHolder = new Banana.Controls.Panel();
 95 		this.buttonHolder = new Banana.Controls.Panel();
 96 		
 97 		this.addControl(this.placeHolder);
 98 		this.addControl(this.buttonHolder);
 99 	},
100 	
101 	/**
102 	 * We create the player when everything is fully rendered
103 	 */
104 	updateDisplay : function()
105 	{
106 		this.createPlayer();
107 	},
108 	
109 	createPlayer : function()
110 	{
111 		this.placeHolder.clear();
112 		
113 		var dim = this.getDimensions();
114 		
115 		if (!this.height)
116 		{
117 			this.height = dim.height;	
118 		}
119 		
120 		if (!this.width)
121 		{
122 			this.width = dim.width;
123 		}
124 		
125 		//dont add the player again after i.e rerender
126         if (this.added)
127         {
128         	return;
129         }
130         this.added = true;
131         
132         //if player api not available we put them in a que
133         window.queuedBananaYouTubePlayers.push(this.getProxy(function(data){
134 			
135 			return this.getProxy(function(){
136 					
137 				 this.player = new YT.Player(data.id, {
138 					    height: data.height,
139 					    width: data.width,
140 					    playerVars:{'wmode':'transparent',
141 					    			'cc_load_policy':0,
142 					    			'iv_load_policy':3,
143 					    			'showinfo':0,
144 					    			'rel':0,
145 					    			 'modestbranding':1,
146 					    			 'controls':0,
147 					    			 'showsearch':0
148 					    			 
149 					    },
150 					   // videoId: data.data,
151 					    events: {
152 					      'onReady': this.getProxy(function(e){ this.playerIsReady(e);}),
153 					      'onStateChange': this.getProxy(function(e){ this.playerStateChanged(e);}),
154 					      'onError': this.getProxy(function(e){ this.playerIsErrored(e);})
155 					    }
156 					  });
157 			})	
158 		})({'id':this.placeHolder.getClientId(),'data':this.data,'width':this.width,'height':this.height}));
159         
160         //create directly when api is ready
161         if (this.isApiReady())
162         {
163         	window.queuedBananaYouTubePlayers[window.queuedBananaYouTubePlayers.length-1]();
164         }
165 	},
166 	
167 	/**
168 	 * Loads video by id. 
169 	 * this can only be done after the videoplayer is available
170 	 * 
171 	 * @param {int} id
172 	 */
173 	loadVideoById : function(id,startSeconds)
174 	{
175 		if (!this.getPlayer())
176 		{
177 			console.log(this.id,'no player');
178 			return;
179 		}
180 		
181 		//reset duration
182 		this.duration = null;
183 		
184 		this.getPlayer().loadVideoById(id,startSeconds);	
185 	},
186 	
187 	/**
188 	 * Loads video by id. 
189 	 * this can only be done after the videoplayer is available
190 	 * 
191 	 * @param {int} id
192 	 */
193 	cueVideoById : function(id, startSeconds)
194 	{
195 		if (!this.getPlayer())
196 		{
197 			console.log(this.id,'no player');
198 			return;
199 		}
200 		
201 		//reset duration
202 		this.duration = null;
203 		
204 		this.getPlayer().cueVideoById(id,startSeconds);	
205 	},
206 	
207 	/**
208 	 * @param {int}
209 	 */
210 	setVolume : function(v)
211 	{
212 		if (!this.getPlayer())
213 		{
214 			log.error("no player");
215 			return;
216 		}
217 		
218 		this.getPlayer().setVolume(v);
219 	},
220 	
221 	mute : function()
222 	{
223 		if (!this.getPlayer())
224 		{
225 			log.error("no player");
226 			return;
227 		}
228 		
229 		this.isMutedPasv = true;
230 		this.getPlayer().mute();
231 	},
232 	
233 	unMute : function()
234 	{
235 		if (!this.getPlayer())
236 		{
237 			log.error("no player");
238 			return;
239 		}
240 		this.isMutedPasv = false;
241 		this.getPlayer().unMute();
242 	},
243 	
244 	isMuted : function(passive)
245 	{
246 		if (passive)
247 		{
248 			return this.isMutedPasv;
249 		}
250 		
251 		if (!this.getPlayer())
252 		{
253 			log.error("no player");
254 			return null;
255 		}
256 		
257 		return this.getPlayer().isMuted();		
258 	},
259 	
260 	/**
261 	 * @return {int}
262 	 */
263 	getDuration : function()
264 	{
265 		if (!this.getPlayer())
266 		{
267 			log.error("no player");
268 			return;
269 		}
270 		
271 		return this.getPlayer().getDuration();
272 	},
273 	
274 	/**
275 	 * @return {int}
276 	 */
277 	getCurrentTime : function()
278 	{
279 		if (!this.getPlayer())
280 		{
281 			log.error("no player");
282 			return;
283 		}
284 		
285 		return new Banana.Util.DateTimecode(this.getPlayer().getCurrentTime()*1000);
286 	},
287 	
288 	/**
289 	 * @return {int};
290 	 */
291 	getPlayerState: function()
292 	{
293 		if (!this.getPlayer())
294 		{
295 			log.error("no player");
296 			return;
297 		}
298 		
299 		return this.getPlayer().getPlayerState();
300 	},
301 	
302 	/**
303 	 * @param {int} seekTo
304 	 * @param {boolean} allowSeekAhead
305 	 */
306 	seekTo : function(seekTo,allowSeekAhead)
307 	{
308 		if (!this.getPlayer())
309 		{
310 			log.error("no player");
311 			return;
312 		}
313 		
314 		return this.getPlayer().seekTo(seekTo,allowSeekAhead);		
315 	},
316 	
317 	playVideo : function()
318 	{
319 		if (!this.getPlayer())
320 		{
321 			log.error("no player");
322 			return;
323 		}
324 		
325 		return this.getPlayer().playVideo();		
326 	},
327 	
328 	pauseVideo : function()
329 	{
330 		if (!this.getPlayer())
331 		{
332 			log.error("no player");
333 			return;
334 		}
335 
336 		return this.getPlayer().pauseVideo();		
337 	},
338 	
339 	
340 	stopVideo : function()
341 	{
342 		if (!this.getPlayer())
343 		{
344 			log.error("no player");
345 			return;
346 		}
347 		
348 		return this.getPlayer().stopVideo();		
349 	},
350 	
351 	/**
352 	 * @return {Object}
353 	 */
354 	getPlayer : function()
355 	{
356 		if (!this.playerReady)
357 		{
358 			log.error("no player");
359 			return;
360 		}
361 		
362 		return this.player;
363 	},
364 	
365 	playerStateChanged : function(e)
366 	{
367 		///logic to determine media duration
368 		//duration is known some time after media is playin
369 		if (this.duration != this.getDuration())
370 		{
371 			this.duration = this.getDuration();
372 			this.triggerEvent("onDurationKnown",new Banana.Util.DateTimecode(this.duration*1000));
373 		}
374 		
375 		this.triggerEvent('onPlayerStateChanged',e);
376 	},
377 	
378 	/**
379 	 * Fired when player is ready
380 	 */
381 	playerIsReady : function(e)
382 	{
383 		this.playerReady = true;
384 
385 		try
386 		{
387 			this.triggerEvent('onPlayerReady',e);
388 		}
389 		catch(e)
390 		{
391 			console.log(e)
392 		}
393 	},
394 	
395 	/**
396 	 * Fired when player is errored
397 	 */
398 	playerIsErrored : function(e)
399 	{
400 		this.triggerEvent('onPlayerError',e);
401 	}
402 });