/************************
ajax.js
Etienne Scott
23 mars 2007
Gestion des requètes AJAX
************************/

/******************************
Effectue une requête asynchrone
******************************/
function AjaxRequestAsyn(filename, callback)
{
	try
	{
		if (window.XMLHttpRequest)
		{ 
			var xhr = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			var xhr = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			var xhr = null;
		}
		xhr.onreadystatechange = function()
		{
			if (xhr.readyState == 4)
			{
				var resultat = xhr.responseText;
				eval(callback + '(resultat);');
			}
		};
		xhr.open("GET", filename, true);
		xhr.send(null);
	}
	catch (err)
	{
		return false
	}
}

/*****************************
Effectue une requête synchrone
*****************************/
function AjaxRequestSyn(filename)
{
	try
	{
		if (window.XMLHttpRequest)
		{ 
			var xhr = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			var xhr = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			var xhr = null;
		}
		xhr.open("GET", filename, false);
		xhr.send(null);
		if (xhr.readyState == 4) {
			return xhr.responseText;
		}
		else
		{
			return false;
		}
	}
	catch (err)
	{
		return false;
	}
}

/*******************************************
Effectue une requête asynchrone de type POST
*******************************************/
function AjaxRequestAsynPost(filename, data, callback)
{
	try
	{
		if (window.XMLHttpRequest)
		{ 
			var xhr = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			var xhr = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			var xhr = null;
		}
		xhr.onreadystatechange = function()
		{
			if (xhr.readyState == 4)
			{
				var resultat = xhr.responseText;
				eval(callback + '(resultat);');
			}
		};
		xhr.open("POST", filename, true);
		xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		xhr.send(data);
	}
	catch (err)
	{
		return false
	}
}

/******************************************
Effectue une requête synchrone de type POST
******************************************/
function AjaxRequestSynPost(filename, data)
{
	try
	{
		if (window.XMLHttpRequest)
		{ 
			var xhr = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			var xhr = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			var xhr = null;
		}
		xhr.open("POST", filename, false);
		xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		xhr.send(data);
		if (xhr.readyState == 4) {
			return xhr.responseText;
		}
		else
		{
			return false;
		}
	}
	catch (err)
	{
		return false
	}
}

/** 
 * flowplayer.js 3.1.2. The Flowplayer API
 * 
 * Copyright 2009 Flowplayer Oy
 * 
 * This file is part of Flowplayer.
 * 
 * Flowplayer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Flowplayer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Flowplayer.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Date: 2009-02-25 16:24:29 -0500 (Wed, 25 Feb 2009)
 * Revision: 166 
 */
(function() {
 
/* 
	FEATURES 
	--------
	- $f() and flowplayer() functions	
	- handling multiple instances 
	- Flowplayer programming API 
	- Flowplayer event model	
	- player loading / unloading	
	- jQuery support
*/ 
 

/*jslint glovar: true, browser: true */
/*global flowplayer, $f */

// {{{ private utility methods
	
	function log(args) {
		console.log("$f.fireEvent", [].slice.call(args));	
	}

		
	// thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
	function clone(obj) {	
		if (!obj || typeof obj != 'object') { return obj; }		
		var temp = new obj.constructor();	
		for (var key in obj) {	
			if (obj.hasOwnProperty(key)) {
				temp[key] = clone(obj[key]);
			}
		}		
		return temp;
	}

	// stripped from jQuery, thanks John Resig 
	function each(obj, fn) {
		if (!obj) { return; }
		
		var name, i = 0, length = obj.length;
	
		// object
		if (length === undefined) {
			for (name in obj) {
				if (fn.call(obj[name], name, obj[name]) === false) { break; }
			}
			
		// array
		} else {
			for (var value = obj[0];
				i < length && fn.call( value, i, value ) !== false; value = obj[++i]) {				
			}
		}
	
		return obj;
	}

	
	// convenience
	function el(id) {
		return document.getElementById(id); 	
	}	

	
	// used extensively. a very simple implementation. 
	function extend(to, from, skipFuncs) {
		if (typeof from != 'object') { return to; }
		
		if (to && from) {			
			each(from, function(name, value) {
				if (!skipFuncs || typeof value != 'function') {
					to[name] = value;		
				}
			});
		}
		
		return to;
	}
	
	// var arr = select("elem.className"); 
	function select(query) {
		var index = query.indexOf("."); 
		if (index != -1) {
			var tag = query.substring(0, index) || "*";
			var klass = query.substring(index + 1, query.length);
			var els = [];
			each(document.getElementsByTagName(tag), function() {
				if (this.className && this.className.indexOf(klass) != -1) {
					els.push(this);		
				}
			});
			return els;
		}
	}
	
	// fix event inconsistencies across browsers
	function stopEvent(e) {
		e = e || window.event;
		
		if (e.preventDefault) {
			e.stopPropagation();
			e.preventDefault();
			
		} else {
			e.returnValue = false;	
			e.cancelBubble = true;
		} 
		return false;
	}

	// push an event listener into existing array of listeners
	function bind(to, evt, fn) {
		to[evt] = to[evt] || [];
		to[evt].push(fn);		
	}
	
	
	// generates an unique id
   function makeId() {
      return "_" + ("" + Math.random()).substring(2, 10);   
   }
	
//}}}	
	

// {{{ Clip

	var Clip = function(json, index, player) {
		
		// private variables
		var self = this;
		var cuepoints = {};
		var listeners = {};  
		self.index = index;
		
		// instance variables
		if (typeof json == 'string') {
			json = {url:json};	
		}
	
		extend(this, json, true);	
		
		// event handling 
		each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),
			function() {
			
			var evt = "on" + this;
				
			// before event
			if (evt.indexOf("*") != -1) {
				evt = evt.substring(0, evt.length -1); 
				var before = "onBefore" + evt.substring(2); 
				
				self[before] = function(fn) {
					bind(listeners, before, fn);
					return self;
				};				
			}  
			
			self[evt] = function(fn) {
				bind(listeners, evt, fn);
				return self;
			};
			
			
			// set common clip event listeners to player level
			if (index == -1) {
				if (self[before]) {
					player[before] = self[before];		
				}				
				if (self[evt])  {
					player[evt] = self[evt];		
				}
			}
			
		});			  
		
		extend(this, { 
			 
			onCuepoint: function(points, fn) {    
				
				// embedded cuepoints
				if (arguments.length == 1) {
					cuepoints.embedded = [null, points];
					return self;
				}
				
				if (typeof points == 'number') {
					points = [points];	
				}
				
				var fnId = makeId();  
				cuepoints[fnId] = [points, fn]; 
				
				if (player.isLoaded()) {
					player._api().fp_addCuepoints(points, index, fnId);	
				}  
				
				return self;
			},
			
			update: function(json) {
				extend(self, json);

				if (player.isLoaded()) {
					player._api().fp_updateClip(json, index);	
				}
				var conf = player.getConfig(); 
				var clip = (index == -1) ? conf.clip : conf.playlist[index];
				extend(clip, json, true);
			},
			
			
			// internal event for performing clip tasks. should be made private someday
			_fireEvent: function(evt, arg1, arg2, target) { 				
				
				if (evt == 'onLoad') { 
					each(cuepoints, function(key, val) {
						if (val[0]) {
							player._api().fp_addCuepoints(val[0], index, key); 		
						}
					}); 
					return false;
				}
				
				// target clip we are working against
				target = target || self;	
				
				if (evt == 'onCuepoint') {
					var fn = cuepoints[arg1];
					if (fn) {
						return fn[1].call(player, target, arg2);
					}
				}  

				// 1. clip properties, 2-3. metadata, 4. updates, 5. resumes from nested clip
				if (arg1 && "onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(evt) != -1) {					
					
					// update clip properties
					extend(target, arg1);					
					
					if (!target.duration) {
						target.duration = arg1.metaData.duration; 	
					} else {
						target.fullDuration = arg1.metaData.duration;	
					}  					
				}  				
				
				var ret = true;
				each(listeners[evt], function() {
					ret = this.call(player, target, arg1, arg2);		
				}); 
				return ret;				
			}			
			
		});
		
		
		// get cuepoints from config
		if (json.onCuepoint) {
			var arg = json.onCuepoint;
			self.onCuepoint.apply(self, typeof arg == 'function' ? [arg] : arg);
			delete json.onCuepoint;
		} 
		
		// get other events
		each(json, function(key, val) {
			
			if (typeof val == 'function') {
				bind(listeners, key, val);
				delete json[key];
			}
			
		});

		
		// setup common clip event callbacks for Player object too (shortcuts)
		if (index == -1) {
			player.onCuepoint = this.onCuepoint;	
		}

	};

//}}}


// {{{ Plugin
		
	var Plugin = function(name, json, player, fn) {
	
		var listeners = {};
		var self = this;   
		var hasMethods = false;
	
		if (fn) {
			extend(listeners, fn);	
		}   
		
		// custom callback functions in configuration
		each(json, function(key, val) {
			if (typeof val == 'function') {
				listeners[key] = val;
				delete json[key];	
			}
		});  
		
		// core plugin methods		
		extend(this, {
  
			// speed and fn are optional
			animate: function(props, speed, fn) { 
				if (!props) {
					return self;	
				}
				
				if (typeof speed == 'function') { 
					fn = speed; 
					speed = 500;
				}
				
				if (typeof props == 'string') {
					var key = props;
					props = {};
					props[key] = speed;
					speed = 500; 
				}
				
				if (fn) {
					var fnId = makeId();
					listeners[fnId] = fn;
				}
		
				if (speed === undefined) { speed = 500; }
				json = player._api().fp_animate(name, props, speed, fnId);	
				return self;
			},
			
			css: function(props, val) {
				if (val !== undefined) {
					var css = {};
					css[props] = val;
					props = css;					
				}
				json = player._api().fp_css(name, props);
				extend(self, json);
				return self;
			},
			
			show: function() {
				this.display = 'block';
				player._api().fp_showPlugin(name);
				return self;
			},
			
			hide: function() {
				this.display = 'none';
				player._api().fp_hidePlugin(name);
				return self;
			},
			
			// toggle between visible / hidden state
			toggle: function() {
				this.display = player._api().fp_togglePlugin(name);
				return self;
			},			
			
			fadeTo: function(o, speed, fn) {
				
				if (typeof speed == 'function') { 
					fn = speed; 
					speed = 500;
				}
				
				if (fn) {
					var fnId = makeId();
					listeners[fnId] = fn;
				}				
				this.display = player._api().fp_fadeTo(name, o, speed, fnId);
				this.opacity = o;
				return self;
			},
			
			fadeIn: function(speed, fn) { 
				return self.fadeTo(1, speed, fn);				
			},
	
			fadeOut: function(speed, fn) {
				return self.fadeTo(0, speed, fn);	
			},
			
			getName: function() {
				return name;	
			},
			
			getPlayer: function() {
				return player;	
			},
			
			// internal method. should be made private some day
         _fireEvent: function(evt, arg, arg2) {
				
            // update plugins properties & methods
            if (evt == 'onUpdate') {
               var json = player._api().fp_getPlugin(name); 
					if (!json) { return;	}					
					
               extend(self, json);
               delete self.methods;
					
               if (!hasMethods) {
                  each(json.methods, function() {
                     var method = "" + this;       
							
                     self[method] = function() {
                        var a = [].slice.call(arguments);
                        var ret = player._api().fp_invoke(name, method, a); 
                        return ret === 'undefined' || ret === undefined ? self : ret;
                     };
                  });
                  hasMethods = true;         
               }
            }
            
            // plugin callbacks
            var fn = listeners[evt];

				if (fn) {
					fn.apply(self, arg);
					
					// "one-shot" callback
					if (evt.substring(0, 1) == "_") {
						delete listeners[evt];  
					} 
            }         
         } 					
			
		});

	};


//}}}


function Player(wrapper, params, conf) {   
	
	// private variables (+ arguments)
	var 
		self = this, 
		api = null, 
		html, 
		commonClip, 
		playlist = [], 
		plugins = {},
		listeners = {},
		playerId,
		apiId,
		
		// n'th player on the page
		playerIndex,
		
		// active clip's index number
		activeIndex,
		
		swfHeight,
		wrapperHeight;	

  
// {{{ public methods 
	
	extend(self, {
			
		id: function() {
			return playerId;	
		}, 
		
		isLoaded: function() {
			return (api !== null);	
		},
		
		getParent: function() {
			return wrapper;	
		},
		
		hide: function(all) {
			if (all) { wrapper.style.height = "0px"; }
			if (api) { api.style.height = "0px"; } 
			return self;
		},

		show: function() {
			wrapper.style.height = wrapperHeight + "px";
			if (api) { api.style.height = swfHeight + "px"; }
			return self;
		}, 
					
		isHidden: function() {
			return api && parseInt(api.style.height, 10) === 0;
		},
		
		
		load: function(fn) {
			if (!api && self._fireEvent("onBeforeLoad") !== false) {
			
				// unload all instances
				each(players, function()  {
					this.unload();
				});
							
				html = wrapper.innerHTML;				
				
				// do not use splash as alternate content for flashembed
				if (html && !flashembed.isSupported(params.version)) {
					wrapper.innerHTML = "";					
				}				  
				
				// install Flash object inside given container
				flashembed(wrapper, params, {config: conf});
				
				// onLoad listener given as argument
				if (fn) {
					fn.cached = true;
					bind(listeners, "onLoad", fn);	
				}
			}
			
			return self;	
		},
		
		unload: function() {
			
			// check that API is sane
			try {
				if (!api || api.fp_isFullscreen()) { return self; }				
			} catch (error) {
				return self;
			}
			
			// unload only if in splash state
			if (html.replace(/\s/g,'') !== '') {
				
				if (self._fireEvent("onBeforeUnload") === false) {
					return self;
				}	
				api.fp_close();
				api = null;				
				wrapper.innerHTML = html;				
				self._fireEvent("onUnload");
			} 
			
			return self;
		
		},
		
		getClip: function(index) {
			if (index === undefined) {
				index = activeIndex;	
			}
			return playlist[index];
		},
		
		
		getCommonClip: function() {
			return commonClip;	
		},		
		
		getPlaylist: function() {
			return playlist; 
		},
		
      getPlugin: function(name) {  
         var plugin = plugins[name];
         
			// create plugin if nessessary
         if (!plugin && self.isLoaded()) {
				var json = self._api().fp_getPlugin(name);
				if (json) {
					plugin = new Plugin(name, json, self);
					plugins[name] = plugin;  						
				} 
         }        
         return plugin; 
      },
		
		getScreen: function() { 
			return self.getPlugin("screen");
		}, 
		
		getControls: function() { 
			return self.getPlugin("controls");
		}, 

		getConfig: function(copy) { 
			return copy ? clone(conf) : conf;
		},
		
		getFlashParams: function() { 
			return params;
		},		
		
		loadPlugin: function(name, url, props, fn) { 

			// properties not supplied			
			if (typeof props == 'function') { 
				fn = props; 
				props = {};
			} 
			
			// if fn not given, make a fake id so that plugin's onUpdate get's fired
			var fnId = fn ? makeId() : "_"; 
			self._api().fp_loadPlugin(name, url, props, fnId); 
			
			// create new plugin
			var arg = {};
			arg[fnId] = fn;
			var p = new Plugin(name, null, self, arg);
			plugins[name] = p;
			return p;			
		},
		
		
		getState: function() {
			return api ? api.fp_getState() : -1;
		},
		
		// "lazy" play
		play: function(clip, instream) {
			
			function play() {
				if (clip !== undefined) {
					self._api().fp_play(clip, instream);
				} else {
					self._api().fp_play();	
				}
			}
			
			if (api) {
				play();
				
			} else {
				self.load(function() { 
					play();
				});
			}
			
			return self;
		},
		
		getVersion: function() {
			var js = "flowplayer.js 3.1.2";
			if (api) {
				var ver = api.fp_getVersion();
				ver.push(js);
				return ver;
			}
			return js; 
		},
		
		_api: function() {
			if (!api) {
				throw "Flowplayer " +self.id()+ " not loaded when calling an API method";
			}
			return api;				
		},
		
		setClip: function(clip) {
			self.setPlaylist([clip]);
			return self;
		},
		
		getIndex: function() {
			return playerIndex;	
		}
		
	}); 
	
	
	// event handlers
	each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,HD*,SD*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),
		function() {		 
			var name = "on" + this;
			
			// before event
			if (name.indexOf("*") != -1) {
				name = name.substring(0, name.length -1); 
				var name2 = "onBefore" + name.substring(2);
				self[name2] = function(fn) {
					bind(listeners, name2, fn);	
					return self;
				};						
			}
			
			// normal event
			self[name] = function(fn) {
				bind(listeners, name, fn);	
				return self;
			};			 
		}
	); 
	
	
	// core API methods
	each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip").split(","),		
		function() {		 
			var name = this;
			
			self[name] = function(a1, a2) {
				if (!api) { return self; }
				var ret = null;
				
				// two arguments
				if (a1 !== undefined && a2 !== undefined) { 
					ret = api["fp_" + name](a1, a2);
					
				} else { 
					ret = (a1 === undefined) ? api["fp_" + name]() : api["fp_" + name](a1);
				}
				
				return ret === 'undefined' || ret === undefined ? self : ret;
			};			 
		}
	);
	
	self['ClipFile'] = null;
	self['ClipFileHD'] = null;
	self['setNewClip'] = function(file, fileHD)
	{
		self['ClipFile'] = 
			{
				accelerated: true,
				scaling: 'fit',
				url: file,
				provider: 'lighttpd',
				seekableOnBegin: true
			};
		
		self['ClipFileHD'] = 
			{
				accelerated: true,
				scaling: 'fit',
				url: fileHD,
				provider: 'lighttpd',
				seekableOnBegin: true
			};
		
		if (fileHD.length == 0)
			return self['ClipFile'];
		else if (readCookie('cliphd') == 'true')
			return self['ClipFileHD'];
		else
			return self['ClipFile'];
	};
	
	self['inHD'] = false;
	
	self['gotoHD'] = function(a1, a2)
	{
		self._fireEvent("onBeforeHD");
		self['inHD'] = true;
		createCookie('cliphd', 'true', 604800);
		this.play(self['ClipFileHD']);
		self._fireEvent("onHD");
	};
	
	self['gotoSD'] = function(a1, a2)
	{
		self._fireEvent("onBeforeSD");
		self['inHD'] = false;
		createCookie('cliphd', 'false', 604800);
		this.play(self['ClipFile']);
		self._fireEvent("onSD");
	};
	
//}}}


// {{{ public method: _fireEvent
		
	self._fireEvent = function(a) {		
		
		if (typeof a == 'string') { a = [a]; }
		
		var evt = a[0], arg0 = a[1], arg1 = a[2], arg2 = a[3], i = 0;  		
		
		if (conf.debug) { log(a); }				
		
		// internal onLoad
		if (!api && evt == 'onLoad' && arg0 == 'player') {						
			
			api = api || el(apiId); 
			swfHeight = api.clientHeight;
			
			each(playlist, function() {
				this._fireEvent("onLoad");		
			});
			
			each(plugins, function(name, p) {
				p._fireEvent("onUpdate");		
			}); 
			
			commonClip._fireEvent("onLoad");  
		}
		
		// other onLoad events are skipped
		if (evt == 'onLoad' && arg0 != 'player') { return; }
		
		
		// "normalize" error handling
		if (evt == 'onError') { 
			if (typeof arg0 == 'string' || (typeof arg0 == 'number' && typeof arg1 == 'number'))  {
				arg0 = arg1;
				arg1 = arg2;
			}			 
		}
		
		
      if (evt == 'onContextMenu') {
         each(conf.contextMenu[arg0], function(key, fn)  {
            fn.call(self);
         });
         return;
      }

		if (evt == 'onPluginEvent') { 
			var name = arg0.name || arg0;
			var p = plugins[name];

			if (p) {
				p._fireEvent("onUpdate", arg0);
				p._fireEvent(arg1, a.slice(3));		
			}
			return;
		}		

		// replace whole playlist
		if (evt == 'onPlaylistReplace') {
			playlist = [];
			var index = 0;
			each(arg0, function() {
				playlist.push(new Clip(this, index++, self));
			});		
		}
		
		// insert new clip to the playlist. arg0 = clip, arg1 = index 
		if (evt == 'onClipAdd') {
			
			// instream clip additions are ignored at this point
			if (arg0.isInStream) { return; }
			
			// add new clip into playlist			
			arg0 = new Clip(arg0, arg1, self);
			playlist.splice(arg1, 0, arg0);
			
			// increment index variable for the rest of the clips on playlist 
			for (i = arg1 + 1; i < playlist.length; i++) {
				playlist[i].index++;	
			}
		}
		
		
		var ret = true;
		
		// clip event
		if (typeof arg0 == 'number' && arg0 < playlist.length) {
			
			activeIndex = arg0;
			var clip = playlist[arg0];			
			
			if (clip) {
				ret = clip._fireEvent(evt, arg1, arg2);	
			} 
			
			if (!clip || ret !== false) {

				// clip argument is given for common clip, because it behaves as the target
				ret = commonClip._fireEvent(evt, arg1, arg2, clip);	
			}  
		}
		
		
		// trigger player event
		each(listeners[evt], function() {
			ret = this.call(self, arg0, arg1);		
			
			// remove cached entry
			if (this.cached) {
				listeners[evt].splice(i, 1);	
			}
			
			// break loop
			if (ret === false) { return false;	 }
			i++;
			
		}); 

		return ret;
	};

//}}}
 

// {{{ init
	
   function init() {
		
		// replace previous installation 
		if ($f(wrapper)) {
			$f(wrapper).getParent().innerHTML = ""; 
			playerIndex = $f(wrapper).getIndex();
			players[playerIndex] = self;
			
		// register this player into global array of instances
		} else {
			players.push(self);
			playerIndex = players.length -1;
		}
		
		wrapperHeight = parseInt(wrapper.style.height, 10) || wrapper.clientHeight;     
		
		// flashembed parameters
		if (typeof params == 'string') {
			params = {src: params};	
		}    
		
		// playerId	
		playerId = wrapper.id || "fp" + makeId();
		apiId = params.id || playerId + "_api"; 		
		params.id = apiId;
		conf.playerId = playerId;
		

		// plain url is given as config
		if (typeof conf == 'string') {
			conf = {clip:{url:conf}};	
		} 
		
		if (typeof conf.clip == 'string') {
			conf.clip = {url: conf.clip};	
		}
		
		// common clip is always there
		conf.clip = conf.clip || {};  
		
		
		// wrapper href as common clip's url
		if (wrapper.getAttribute("href", 2) && !conf.clip.url) { 
			conf.clip.url = wrapper.getAttribute("href", 2);			
		} 
		
		commonClip = new Clip(conf.clip, -1, self); 
		
		// playlist
		conf.playlist = conf.playlist || [conf.clip]; 
		
		var index = 0;
		
		each(conf.playlist, function() {
			
			var clip = this;			
			
			/* sometimes clip is given as array. this is not accepted. */
			if (typeof clip == 'object' && clip.length) {
				clip = {url: "" + clip};	
			}			
			
			// populate common clip properties to each clip
			each(conf.clip, function(key, val) {
				if (val !== undefined && clip[key] === undefined && typeof val != 'function') {
					clip[key] = val;	
				}
			});	
			
			// modify playlist in configuration
			conf.playlist[index] = clip;			
			
			// populate playlist array
			clip = new Clip(clip, index, self);
			playlist.push(clip);						
			index++;			
		});				
		
		// event listeners
		each(conf, function(key, val) {
			if (typeof val == 'function') {
				
				// common clip event
				if (commonClip[key]) {
					commonClip[key](val);
					
				// player event
				} else {
					bind(listeners, key, val);	
				}				
				
				// no need to supply for the Flash component
				delete conf[key];	
			}
		});		 
		
		
		// plugins
		each(conf.plugins, function(name, val) {
			if (val) {
				plugins[name] = new Plugin(name, val, self);
			}
		});
		
		
		// setup controlbar plugin if not explicitly defined
		if (!conf.plugins || conf.plugins.controls === undefined) {
			plugins.controls = new Plugin("controls", null, self);	
		}
		
		// setup canvas as plugin
		plugins.canvas = new Plugin("canvas", null, self);
		
		
		// Flowplayer uses black background by default
		params.bgcolor = params.bgcolor || "#000000";
		
		
		// setup default settings for express install
		params.version = params.version || [9, 0];		
		params.expressInstall = 'http://www.flowplayer.org/swf/expressinstall.swf';
		
		
		// click function
		function doClick(e) { 
			if (!self.isLoaded() && self._fireEvent("onBeforeClick") !== false) {
				self.load();		
			} 
			return stopEvent(e);					
		}
		
		// defer loading upon click
		html = wrapper.innerHTML;
		if (html.replace(/\s/g, '') !== '') {	 
			
			if (wrapper.addEventListener) {
				wrapper.addEventListener("click", doClick, false);	
				
			} else if (wrapper.attachEvent) {
				wrapper.attachEvent("onclick", doClick);	
			}
			
		// player is loaded upon page load 
		} else {
			
			// prevent default action from wrapper. (fixes safari problems)
			if (wrapper.addEventListener) {
				wrapper.addEventListener("click", stopEvent, false);	
			}
			
			// load player
			self.load();
		}
	}

	// possibly defer initialization until DOM get's loaded
	if (typeof wrapper == 'string') { 
		flashembed.domReady(function() {
			var node = el(wrapper); 
			
			if (!node) {
				throw "Flowplayer cannot access element: " + wrapper;	
			} else {
				wrapper = node; 
				init();					
			} 
		});
		
	// we have a DOM element so page is already loaded
	} else {		
		init();
	}
	
	
//}}}


}


// {{{ flowplayer() & statics 

// container for player instances
var players = [];


// this object is returned when multiple player's are requested 
function Iterator(arr) {
	
	this.length = arr.length;
	
	this.each = function(fn)  {
		each(arr, fn);	
	};
	
	this.size = function() {
		return arr.length;	
	};	
}

// these two variables are the only global variables
window.flowplayer = window.$f = function() {

	var instance = null;
	var arg = arguments[0];	
	
	// $f()
	if (!arguments.length) {
		each(players, function() {
			if (this.isLoaded())  {
				instance = this;	
				return false;
			}
		});
		
		return instance || players[0];
	} 
	
	if (arguments.length == 1) {
		
		// $f(index);
		if (typeof arg == 'number') { 
			return players[arg];	
	
			
		// $f(wrapper || 'containerId' || '*');
		} else {
			
			// $f("*");
			if (arg == '*') {
				return new Iterator(players);	
			}
			
			// $f(wrapper || 'containerId');
			each(players, function() {
				if (this.id() == arg.id || this.id() == arg || this.getParent() == arg)  {
					instance = this;	
					return false;
				}
			});
			
			return instance;					
		}
	} 			

	// instance builder 
	if (arguments.length > 1) {		

		var swf = arguments[1];
		var conf = (arguments.length == 3) ? arguments[2] : {};
						
		if (typeof arg == 'string') {
			
			// select arg by classname
			if (arg.indexOf(".") != -1) {
				var instances = [];
				
				each(select(arg), function() { 
					instances.push(new Player(this, clone(swf), clone(conf))); 		
				});	
				
				return new Iterator(instances);
				
			// select node by id
			} else {		
				var node = el(arg);
				return new Player(node !== null ? node : arg, swf, conf);  	
			} 
			
			
		// arg is a DOM element
		} else if (arg) {
			return new Player(arg, swf, conf);
		}
	} 
	
	return null; 
};
	
extend(window.$f, {

	// called by Flash External Interface 		
	fireEvent: function() {
		var a = [].slice.call(arguments);
		var p = $f(a[0]);		
		return p ? p._fireEvent(a.slice(1)) : null;
	},
	
	
	// create plugins by modifying Player's prototype
	addPlugin: function(name, fn) {
		Player.prototype[name] = fn;
		return $f;
	},
	
	// utility methods for plugin developers
	each: each,
	
	extend: extend
	
});


/* sometimes IE leaves sockets open (href="javascript:..." links break this)
if (document.all) {
	window.onbeforeunload = function(e) { 
		$f("*").each(function() {
			if (this.isLoaded()) {
				this.close();	
			}
		});
	};	
}
*/

	
//}}}


//{{{ jQuery support

if (typeof jQuery == 'function') {
	
	jQuery.prototype.flowplayer = function(params, conf) {  
		
		// select instances
		if (!arguments.length || typeof arguments[0] == 'number') {
			var arr = [];
			this.each(function()  {
				var p = $f(this);
				if (p) {
					arr.push(p);	
				}
			});
			return arguments.length ? arr[arguments[0]] : new Iterator(arr);
		}
		
		// create flowplayer instances
		return this.each(function() { 
			$f(this, clone(params), conf ? clone(conf) : {});	
		}); 
		
	};
	
}

//}}}


})();
/**
 * tools.flashembed 1.0.3 - The future of Flash embedding.
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/flash-embed.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Date: 2009-01-14 00:41:14 -0500 (Wed, 14 Jan 2009)
 * Revision: 1314 
 */ 
(function() {  
		
//{{{ utility functions 
		
var jQ = typeof jQuery == 'function';

// from "Pro JavaScript techniques" by John Resig
function isDomReady() {
	
	if (domReady.done)  { return false; }
	
	var d = document;
	if (d && d.getElementsByTagName && d.getElementById && d.body) {
		clearInterval(domReady.timer);
		domReady.timer = null;
		
		for (var i = 0; i < domReady.ready.length; i++) {
			domReady.ready[i].call();	
		}
		
		domReady.ready = null;
		domReady.done = true;
	} 
}

// if jQuery is present, use it's more effective domReady method
var domReady = jQ ? jQuery : function(f) {
	
	if (domReady.done) {
		return f();	
	}
	
	if (domReady.timer) {
		domReady.ready.push(f);	
		
	} else {
		domReady.ready = [f];
		domReady.timer = setInterval(isDomReady, 13);
	} 
};	


// override extend opts function 
function extend(to, from) {
	if (from) {
		for (key in from) {
			if (from.hasOwnProperty(key)) {
				to[key] = from[key];
			}
		}
	}
	
	return to;
}	


// JSON.asString() function
function asString(obj) {
	 
	switch (typeOf(obj)){
		case 'string':
			obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
			
			// flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
			obj = obj.replace(/^\s?(\d+)%/, "$1pct");
			return '"' +obj+ '"';
			
		case 'array':
			return '['+ map(obj, function(el) {
				return asString(el);
			}).join(',') +']'; 
			
		case 'function':
			return '"function()"';
			
		case 'object':
			var str = [];
			for (var prop in obj) {
				if (obj.hasOwnProperty(prop)) {
					str.push('"'+prop+'":'+ asString(obj[prop]));
				}
			}
			return '{'+str.join(',')+'}';
	}
	
	// replace ' --> "  and remove spaces
	return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
}


// private functions
function typeOf(obj) {
	if (obj === null || obj === undefined) { return false; }
	var type = typeof obj;
	return (type == 'object' && obj.push) ? 'array' : type;
}


// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
if (window.attachEvent) {
	window.attachEvent("onbeforeunload", function() {
		__flash_unloadHandler = function() {};
		__flash_savedUnloadHandler = function() {};
	});
}

function map(arr, func) {
	var newArr = []; 
	for (var i in arr) {
		if (arr.hasOwnProperty(i)) {
			newArr[i] = func(arr[i]);
		}
	}
	return newArr;
}
	
function getHTML(p, c) {

		
	var e = extend({}, p);	
	
	var ie = document.all;	
	var html = '<object width="' +e.width+ '" height="' +e.height+ '"';
	
	// force id for IE or Flash API cannot be returned
	if (ie && !e.id) {
		e.id = "_" + ("" + Math.random()).substring(9);
	}
	
	if (e.id) {	
		html += ' id="' + e.id + '"';	
	}
	
	// prevent possible caching problems
	e.src += ((e.src.indexOf("?") != -1 ? "&" : "?") + Math.random());		
	
	if (e.w3c || !ie) {
		html += ' data="' +e.src+ '" type="application/x-shockwave-flash"';		
	} else {
		html += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';	
	}
	
	html += '>'; 
	
	if (e.w3c || ie) {
		html += '<param name="movie" value="' +e.src+ '" />'; 	
	}

	// parameters
	e.width = e.height = e.id = e.w3c = e.src = null;
	
	for (var k in e) {
		if (e[k] !== null) {
			html += '<param name="'+ k +'" value="'+ e[k] +'" />';
		}
	}	

	// flashvars
	var vars = "";
	
	if (c) {
		for (var key in c) {
			if (c[key] !== null) {
				vars += key +'='+ (typeof c[key] == 'object' ? asString(c[key]) : c[key]) + '&';
			}
		}
		vars = vars.substring(0, vars.length -1);
		html += '<param name="flashvars" value=\'' + vars + '\' />';
	}
	
	html += "</object>";	
	
	return html;

}

//}}}


function Flash(root, opts, flashvars) {
	
	var version = flashembed.getVersion(); 
	
	// API methods for callback
	extend(this, {
			
		getContainer: function() {
			return root;	
		},
		
		getConf: function() {
			return opts;	
		},
	
		getVersion: function() {
			return version;	
		},	
		
		getFlashvars: function() {
			return flashvars;	
		}, 
		
		getApi: function() {
			return root.firstChild;	
		}, 
		
		getHTML: function() {
			return getHTML(opts, flashvars);	
		}
		
	});

	// variables	
	var required = opts.version; 
	var express = opts.expressInstall;
	
	
	// everything ok -> generate OBJECT tag 
	var ok = !required || flashembed.isSupported(required);
	
	if (ok) {
		opts.onFail = opts.version = opts.expressInstall = null;
		root.innerHTML = getHTML(opts, flashvars);
		
	// fail #1. express install
	} else if (required && express && flashembed.isSupported([6,65])) {
		
		extend(opts, {src: express});
		
		flashvars = {
			MMredirectURL: location.href,
			MMplayerType: 'PlugIn',
			MMdoctitle: document.title
		};
		
		root.innerHTML = getHTML(opts, flashvars);	
		
	// fail #2. 
	} else { 
	
		// fail #2.1 custom content inside container
		if (root.innerHTML.replace(/\s/g, '') !== '') {
			// minor bug fixed here 08.04.2008 (thanks JRodman)			
		
		// fail #2.2 default content
		} else {			
			root.innerHTML = 
				"<h2>Flash version " + required + " or greater is required</h2>" + 
				"<h3>" + 
					(version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed") +
				"</h3>" + 
				
				(root.tagName == 'A' ? "<p>Click here to download latest version</p>" : 
					"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");
				
			if (root.tagName == 'A') {	
				root.onclick = function() {
					location.href= 'http://www.adobe.com/go/getflashplayer';
				};
			}				
		}
	}
	
	// onFail
	if (!ok && opts.onFail) {
		var ret = opts.onFail.call(this);
		if (typeof ret == 'string') { root.innerHTML = ret; }	
	}
	
	// http://flowplayer.org/forum/8/18186#post-18593
	if (document.all) {
		window[opts.id] = document.getElementById(opts.id);
	} 
	
}

window.flashembed = function(root, conf, flashvars) {   
	
//{{{ construction
	
	// root must be found / loaded	
	if (typeof root == 'string') {
		var el = document.getElementById(root);
		if (el) {
			root = el;	
		} else {
			domReady(function() {
				flashembed(root, conf, flashvars);
			});
			return; 		
		} 
	}
	
	// not found
	if (!root) { return; }


	// setup opts
	var opts = {
		
		// very common opts
		width: '100%',
		height: '100%',		
		
		// flashembed defaults
		allowfullscreen: true,
		allowscriptaccess: 'always',
		quality: 'high',	
		
		
		// flashembed specific options
		version: null,
		onFail: null,
		expressInstall: null, 
		w3c: false
	};
	
	
	if (typeof conf == 'string') {
		conf = {src: conf};	
	}
	
	extend(opts, conf);		
	
	return new Flash(root, opts, flashvars);
	
//}}}
	
	
};


//{{{ static methods

extend(window.flashembed, {

	// returns arr[major, fix]
	getVersion: function() {
	
		var version = [0, 0];
		
		if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
			var _d = navigator.plugins["Shockwave Flash"].description;
			if (typeof _d != "undefined") {
				_d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
				var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
				version = [_m, _r];
			}
			
		} else if (window.ActiveXObject) {

			try { // avoid fp 6 crashes
				var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
				
			} catch(e) {
				
				try { 
					_a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
					version = [6, 0];
					_a.AllowScriptAccess = "always"; // throws if fp < 6.47 
					
				} catch(ee) {
					if (version[0] == 6) { return version; }
				}
				try {
					_a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
				} catch(eee) {
				
				}
				
			}
			
			if (typeof _a == "object") {
				_d = _a.GetVariable("$version"); // bugs in fp 6.21 / 6.23
				if (typeof _d != "undefined") {
					_d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
					version = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
				}
			}
		} 
		
		return version;
	},
	
	isSupported: function(version) {
		var now = flashembed.getVersion();
		var ret = (now[0] > version[0]) || (now[0] == version[0] && now[1] >= version[1]);			
		return ret;
	},
	
	domReady: domReady,
	
	// returns a String representation from JSON object 
	asString: asString,
	
	
	getHTML: getHTML
	
});

//}}}


// setup jquery support
if (jQ) {
	
	// tools version number
	jQuery.tools = jQuery.tools || {version: {}};	
	jQuery.tools.version.flashembed = '1.0.3';	

	
	jQuery.fn.flashembed = function(conf, flashvars) {
		
		var el = null;
		
		this.each(function() { 
			el = flashembed(this, conf, flashvars);
		});
		
		return conf.api === false ? this : el;		
	};

}

})();


/**
 * flowplayer.controls.js 3.0.2. Flowplayer JavaScript plugin.
 * 
 * This file is part of Flowplayer, http://flowplayer.org
 *
 * Author: Tero Piirainen, <support@flowplayer.org>
 * Copyright (c) 2008 Flowplayer Ltd
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * SEE: http://www.opensource.org/licenses
 * 
 * Version: 3.0.2 - Wed Apr 15 2009 08:36:14 GMT-0000 (GMT+00:00)
 */

$f.addPlugin("controls", function(wrap, options) {
	
		
//{{{ private functions
		
	function fixE(e) {
		if (typeof e == 'undefined') { e = window.event; }
		if (typeof e.layerX == 'undefined') { e.layerX = e.offsetX; }
		if (typeof e.layerY == 'undefined') { e.layerY = e.offsetY; }
		return e;
	}
	
	function w(e) {
		return e.clientWidth;	
	}
	
	function offset(e) {
		return e.offsetLeft;	
	}
	
	/* a generic dragger utility for hoirzontal dragging */
	function Draggable(o, min, max, offset) { 
		
		var dragging = false;
		
		function foo() { }
		
		o.onDragStart	= o.onDragStart || foo;
		o.onDragEnd		= o.onDragEnd 	 || foo;
		o.onDrag			= o.onDrag 		 || foo;	
		
		function move(x) {
			// must be withing [min, max]
			if (x > max) { return false; }
			if (x < min) { return false; } 
			o.style.left = x + "px";	
			return true;
		}
		
		function end() {
			document.onmousemove = null;
			document.onmouseup   = null;
			o.onDragEnd(parseInt(o.style.left, 10));
			dragging = false;
		}

		function drag(e) {
			e = fixE(e); 
			var x = e.clientX - offset; 
			if (move(x)) {
				dragging = true;
				o.onDrag(x);		
			} 
			return false;
		}
		
		o.onmousedown = function(e)  {
			e = fixE(e);
			o.onDragStart(parseInt(o.style.left, 10)); 
			document.onmousemove		= drag;
			document.onmouseup		= end;
			return false;	
		};
		
		this.dragTo = function(x) {
			if (move(x)) {
				o.onDragEnd(x);		
			}	
		};
		
		this.setMax = function(val) {
			max = val;	
		};
		
		this.isDragging = function() {
			return dragging;	
		};

		return this; 
	}

	function extend(to, from) {
		if (from) {
			for (key in from) {
				if (key) {
					to[key] = from[key];		
				} 
			}
		}
	}
	
	function byClass(name) {
		var els = wrap.getElementsByTagName("*");		
		var re = new RegExp("(^|\\s)" + name + "(\\s|$)");
		for (var i = 0; i < els.length; i++) {
			if (re.test(els[i].className)) {
				return els[i];
			}
		}
	}
	
	// prefix integer with zero when nessessary 
	function pad(val) {
		val = parseInt(val, 10);
		return val >= 10 ? val : "0" + val;
	}
	
	// display seconds in hh:mm:ss format
	function toTime(sec) {
		
		var h = Math.floor(sec / 3600);
		var min = Math.floor(sec / 60);
		sec = sec - (min * 60);
		
		if (h >= 1) {
			min -= h * 60;
			return pad(h) + ":" + pad(min) + ":" + pad(sec);
		}
		
		return pad(min) + ":" + pad(sec);
	}
	
	function getTime(time, duration) {
		return "<span>" + toTime(time) + "</span> / <strong>" + toTime(duration) + "</strong>";	
	}
	
//}}}
	
	
	var self = this;
	
	var opts = {
		playHeadClass: 'playhead',
		trackClass: 'track',
		playClass: 'play',
		pauseClass: 'pause',
		bufferClass: 'buffer',
		progressClass: 'progress',
		
		timeClass: 'time',
		muteClass: 'mute',
		unmuteClass: 'unmute',
		HDClass: 'hdbutton',
		SDClass: 'sdbutton',
		duration: 0,
		
		template:	'<table cellpadding="0" cellspacing="0">' +
						'<tr>' +
							'<td class="play"></td>' +
							'<td class="track">' +
								'<div class="buffer"></div>' +
								'<div class="progress"></div>' +
								'<div class="playhead"></div>' +
							'</td>' +
							'<td class="time"></td>' +
							'<td class="mute"></td>' +
							'<td class="hdbutton"></td>' +
						'</tr>' +
					'</table>'
		/*
		template: '<a class="play">play</a>' +
					 '<div class="track">' +
					 	'<div class="buffer"></div>' +
					 	'<div class="progress"></div>' +
					 	'<div class="playhead"></div>' +
					 '</div>' +
					 '<a class="hdbutton">HD</div>' +
					 '<a class="mute">mute</a>' +
					 '<div class="time"></div>'
		*/
	};
	
	extend(opts, options);
	
	if (typeof wrap == 'string') {
		wrap = document.getElementById(wrap);
	}
	
	if (!wrap) { return; }
	
	// inner HTML
	if (!wrap.innerHTML.replace(/\s/g, '')) {
		wrap.innerHTML = opts.template;
	}
	
	// get elements
	var ball = byClass(opts.playHeadClass);
	var bufferBar = byClass(opts.bufferClass);
	var progressBar = byClass(opts.progressClass);
	var track = byClass(opts.trackClass);
	var time = byClass(opts.timeClass);
	var mute = byClass(opts.muteClass);
	var highdef = byClass(opts.HDClass);
	
	// initial time
	time.innerHTML = getTime(0, opts.duration);
	
	// get dimensions
	var trackWidth = w(track);
	var ballWidth = w(ball);
	
	// initialize draggable playhead
	var head = new Draggable(ball, 0, 0, offset(wrap) + offset(track) + (ballWidth / 2));
	
	// track click moves playHead
	track.onclick = function(e) {
		e = fixE(e);
		if (e.target == ball) { return false; }
		head.dragTo(e.layerX - ballWidth / 2);
	};
	
	// play/pause button
	var play = byClass(opts.playClass);
	
	play.onclick = function() {
		if (self.isLoaded()) {
			self.toggle();
		} else {
			self.play();
		}						
	};
	
	// mute/unmute button
	mute.onclick = function() {
		if (self.getStatus().muted) {
			self.unmute();
		} else {
			self.mute();
		}
	};
	
	// HD/SD button
	highdef.onclick = function() {
		if (self.inHD) {
			self.gotoSD();
		} else {
			self.gotoHD();
		}
	};

	// setup timer
	var timer = null;
	
	function getMax(len, total) {
		temp = parseInt(Math.min(len / total * trackWidth, trackWidth - ballWidth / 2), 10);
		return temp > 0 ? temp : 0;
	}
	
	self.onStart(function(clip) {
		
		trackWidth = w(track);
		var duration = clip.duration || 0;

		time.innerHTML = getTime(0, duration);
		
		// clear previous timer		
		clearInterval(timer);
		 
		// begin timer		
		timer = setInterval(function()  {			
			
			var status = self.getStatus();			

			// time display
			if (status.time)  {				
				time.innerHTML = getTime(status.time, clip.duration);	
			} 
			
			if (status.time === undefined) {
				clearInterval(timer);
				return;
			}
			
			// buffer width
			var x = getMax(status.bufferEnd, duration);
			bufferBar.style.width = x + "px";
			head.setMax(trackWidth);
			
			// progress width
			if (!self.isPaused() && !head.isDragging()) {
				x = getMax(status.time, duration);
				progressBar.style.width = x + 'px';
				if (x)
					ball.style.left = (x -ballWidth / 2 - 1) + 'px';
				else
					ball.style.left = (-ballWidth / 2) + 'px';
			}
			
		}, 100);
	});
	
	self.onBegin(function() {
		play.className = opts.pauseClass;		
	});

	
	// pause / resume states	
	self.onPause(function() {
		play.className = opts.playClass;
	});

	self.onResume(function() {
		play.className = opts.pauseClass;
	});
	
	
	// mute / unmute states	
	self.onMute(function() {
		mute.className = opts.unmuteClass;
	});

	self.onUnmute(function() {
		mute.className = opts.muteClass;
	});
	
	// HD / SD states	
	self.onHD(function() {
		highdef.className = opts.SDClass;
	});

	self.onSD(function() {
		highdef.className = opts.HDClass;
	});
	
	
	// clear timer when clip ends	
	self.onFinish(function(clip) {		
		clearInterval(timer);	
	}); 
	
	self.onUnload(function() {
		time.innerHTML = getTime(0, opts.duration);
	});
	
	
	ball.onDragEnd = function(x) {
		var to = parseInt(x / trackWidth  * 100, 10) + "%";
		progressBar.style.width = (x > 0 ? x : 0) + "px";
		if (self.isLoaded()) {
			self.seek(to);		
		} 
	};
	
	ball.onDrag = function(x) {
		progressBar.style.width = (x > 0 ? x : 0) + "px";	
	};

	
	// return player instance to enable plugin chaining
	return self;
	
});
		
			
			



var pageTracker = _gat._getTracker("UA-3183233-1");
pageTracker._initData();
pageTracker._trackPageview();

