//-- Uniplayer packed file consists of these files:
//-- uniplayer languages
//-- uniplayer core
//-- uniplayer mimes
//-- module flash
//-- module windowsmedia
//-- module vlc
/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

UniplayerLanguages = {
	'en': {
		controlsPrevious: 'Previous',
		controlsPlay: 'Play',
		controlsPause: 'Pause',
		controlsStop: 'Stop',
		controlsNext: 'Next',
		controlsMute: 'Mute',
		controlsVolume: 'Volume',
		controlsTime: 'Time',
		controlsPosition: 'Position',
		controlsFullScreen: 'FullScreen',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'About'
	},
	'uk': {
		controlsPrevious: 'Попереднiй',
		controlsPlay: 'Грати',
		controlsPause: 'Пауза',
		controlsStop: 'Стоп',
		controlsNext: 'Наступний',
		controlsMute: 'Приглушити',
		controlsVolume: 'Гучнiсть',
		controlsTime: 'Час',
		controlsPosition: 'Позицiя',
		controlsFullScreen: 'На весь екран',
		controlsPlaylist: 'Плейлист',
		controlsMenu: 'Меню',
		about: 'Про'
	},
	'ru': {
		controlsPrevious: 'Предыдущий',
		controlsPlay: 'Воспроизведение',
		controlsPause: 'Пауза',
		controlsStop: 'Стоп',
		controlsNext: 'Следующий',
		controlsMute: 'Выключить звук',
		controlsVolume: 'Громкость',
		controlsTime: 'Время',
		controlsPosition: 'Позиция',
		controlsFullScreen: 'На весь экран',
		controlsPlaylist: 'Список',
		controlsMenu: 'Меню',
		about: 'О программе'
	},
	'fr': {
		controlsPrevious: 'Précédent',
		controlsPlay: 'Jouer',
		controlsPause: 'Pause',
		controlsStop: 'Stop',
		controlsNext: 'Prochain',
		controlsMute: 'Muet',
		controlsVolume: 'Volume',
		controlsTime: 'Temps',
		controlsPosition: 'Position',
		controlsFullScreen: 'Plein écran',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'Sur'
	},
	'it': {
		controlsPrevious: 'Precedente',
		controlsPlay: 'Giocare',
		controlsPause: 'Pausa',
		controlsStop: 'Fermare',
		controlsNext: 'Successivo',
		controlsMute: 'Mute',
		controlsVolume: 'Volume',
		controlsTime: 'Tempo',
		controlsPosition: 'Posizione',
		controlsFullScreen: 'FullScreen',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'Circa'
	},
	'de': {
		controlsPrevious: 'Zurück',
		controlsPlay: 'Spielen',
		controlsPause: 'Pause',
		controlsStop: 'Stopp',
		controlsNext: 'Nächster',
		controlsMute: 'Mute',
		controlsVolume: 'Band',
		controlsTime: 'Zeit',
		controlsPosition: 'Position',
		controlsFullScreen: 'FullScreen',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menü',
		about: 'Über'
	},
	'ja': {
		controlsPrevious: '前',
		controlsPlay: '遊び',
		controlsPause: '一時停止',
		controlsStop: '停止',
		controlsNext: '次の',
		controlsMute: 'ミュート',
		controlsVolume: 'ボリューム',
		controlsTime: '時間',
		controlsPosition: '位置',
		controlsFullScreen: 'フルスクリーン',
		controlsPlaylist: 'プレイリスト',
		controlsMenu: 'メニュー',
		about: '約'
	},
	'tr': {
		controlsPrevious: 'Önceki',
		controlsPlay: 'Oyun',
		controlsPause: 'Durma',
		controlsStop: 'Dur',
		controlsNext: 'Sonraki',
		controlsMute: 'Sessiz',
		controlsVolume: 'Hacim',
		controlsTime: 'Zaman',
		controlsPosition: 'Pozisyon',
		controlsFullScreen: 'Tam Ekran',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menü',
		about: 'Hakkında'
	},
	'zh': {
		controlsPrevious: '以前',
		controlsPlay: '玩',
		controlsPause: '暂停',
		controlsStop: '停止',
		controlsNext: '未来',
		controlsMute: '哑',
		controlsVolume: '体积',
		controlsTime: '时间',
		controlsPosition: '位置',
		controlsFullScreen: '全屏',
		controlsPlaylist: '播放列表',
		controlsMenu: '菜单',
		about: '关于'
	},
	'nl': {
		controlsPrevious: 'Vorig',
		controlsPlay: 'Spelen',
		controlsPause: 'Pauzeren',
		controlsStop: 'Stop',
		controlsNext: 'Volgende',
		controlsMute: 'Dempen',
		controlsVolume: 'Volume',
		controlsTime: 'Tijd',
		controlsPosition: 'Positie',
		controlsFullScreen: 'FullScreen',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'Over'
	},
	'fi': {
		controlsPrevious: 'Edellinen',
		controlsPlay: 'Pelata',
		controlsPause: 'Pause',
		controlsStop: 'Tauko',
		controlsNext: 'Ensi',
		controlsMute: 'Mykkä',
		controlsVolume: 'Määrä',
		controlsTime: 'Aika',
		controlsPosition: 'Sijainti',
		controlsFullScreen: 'Koko näyttö',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'Noin'
	},
	'da': {
		controlsPrevious: 'Previous',
		controlsPlay: 'Spil',
		controlsPause: 'Pause',
		controlsStop: 'Stands',
		controlsNext: 'Næste',
		controlsMute: 'Mute',
		controlsVolume: 'Bind',
		controlsTime: 'Time',
		controlsPosition: 'Position',
		controlsFullScreen: 'Fuldskærm',
		controlsPlaylist: 'Playlist',
		controlsMenu: 'Menu',
		about: 'Om'
	},
	'el': {
		controlsPrevious: 'Προηγούμενο',
		controlsPlay: 'Παιχνίδι',
		controlsPause: 'Παύση',
		controlsStop: 'σταμάτημα',
		controlsNext: 'Επόμενο',
		controlsMute: 'Σίγαση',
		controlsVolume: 'Όγκος',
		controlsTime: 'Χρόνος',
		controlsPosition: 'Θέση',
		controlsFullScreen: 'Πλήρους οθόνη',
		controlsPlaylist: 'Λίστ',
		controlsMenu: 'Μενού',
		about: 'Περίπου'
	},
	'es': {
		controlsPrevious: 'Anterior',
		controlsPlay: 'Jugar',
		controlsPause: 'Pausa',
		controlsStop: 'Alto',
		controlsNext: 'Próximo',
		controlsMute: 'Mudo',
		controlsVolume: 'Volumen',
		controlsTime: 'Tiempo',
		controlsPosition: 'Posición',
		controlsFullScreen: 'Pantalla completa',
		controlsPlaylist: 'Lista de reproducción',
		controlsMenu: 'Menú',
		about: 'Sobre'
	},
	'pl': {
		controlsPrevious: 'Poprzedni',
		controlsPlay: 'Grać',
		controlsPause: 'Pauza',
		controlsStop: 'Stop',
		controlsNext: 'Obok',
		controlsMute: 'Niemy',
		controlsVolume: 'Objętość',
		controlsTime: 'Czas',
		controlsPosition: 'Miejsce',
		controlsFullScreen: 'Pełny ekran',
		controlsPlaylist: 'Listy odtwarzania',
		controlsMenu: 'Menu',
		about: 'O'
	},
	'pt': {
		controlsPrevious: 'Anterior',
		controlsPlay: 'Jogar',
		controlsPause: 'Pausa',
		controlsStop: 'Pare',
		controlsNext: 'Próximo',
		controlsMute: 'Mudo',
		controlsVolume: 'Volume',
		controlsTime: 'Tempo',
		controlsPosition: 'Posição',
		controlsFullScreen: 'FullScreen',
		controlsPlaylist: 'Lista',
		controlsMenu: 'Menu',
		about: 'Sobre'
	}
};


/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

Uniplayer = function(options){
	// options start
	this.options = {
		src: '',							// src file on start
		mimetype: '',						// mime-type for file on start
		volume: .8,							// volume (0-1) on start
		position: 0,						// position (0-1) on start
		id: '',								// id for <object> tag, leave empty to do not add an id attribute at all
		width: 1,							// width of movie
		height: 1,							// height of movie
		autoplay: false,					// auto play movie after load
		autoload: false,					// auto load movie at start
		showControls: true,					// show or not uniplayer controls
		showNativeControls: false,			// show or not current module "native" controls
		clearHolder: false,					// clear ar not holder element before writting player there
		preview: '',						// preview image of start movie, leave empty to show 'supply players' if enabled below
		showSupply: true,					// show or not list of supported players on start
		showSupplyLogos: true,				// show it with logotypes?
		showSupplyLogosSmall: false,		// show logos small
		showSupplyLogosTransparent: false,	// show transparent logos (png images used which incorrect displayed in IE<7)
		updaterInterval: 500,				// interval of plugin status updates in milliseconds
		background: '#EDEDED',				// background of movie
		guiPath: 'gui/default/',			// path to GUI folder (with trailing slash)
		language: 'en',
		hideStartLogo: false,
		autoloadModules: false,
		noCache: false,
		repeat: false,
		flashReloadPage: false,
		showTitleSrc: true,
		onlyAudio: false,
		onlyVideo: false
	};
	var autoloadModules = [
		'UniplayerFlashJWPlayer',
		'UniplayerSilverlight',
		'UniplayerRealPlayer',
		'UniplayerDivX',
		'UniplayerVLC',
		'UniplayerQuickTime',
		'UniplayerWindowsMedia',
		'UniplayerFlashFlowplayer'
	];
	// options end - do not edit below
	if(typeof options == 'object'){
		for(var i in options){
			this.options[i] = options[i];
		}
	}
	// options depencies
	if(this.options.autoplay && !this.options.autoload){
		this.options.autoload = true;
	}
	if(this.options.background){
		if(navigator.userAgent.indexOf('MSIE 6')>=0 || navigator.userAgent.indexOf('MSIE 5')>=0){
			this.options.background = '#EDEDED';
			this.options.showSupplyLogosTransparent = false;
		}
		else if(!this.options.showSupplyLogosTransparent){
			this.options.showSupplyLogosTransparent = true;
		}
	}
	
	// setting up
	this.name = 'Uniplayer';
	this.version = '0.4b';
	this.modules = {};
	this.modulesList = [];
	this.supported = {};
	this.mimeTypeCache = {};
	this.holders = {};
	this.listeners = {};
	this.states = {
		stopped: 0,
		loading: 1,
		playing: 2,
		paused: 3,
		failed: 4
	};
	this.current = {
		src: this.options.src || '',
		mimetype: this.options.mimetype || '',
		state: this.states.stopped,
		mute: false,
		pageScreen: false,
		volume: this.options.volume || 0,
		duration: 0,
		position: this.options.position || 0,
		width: this.options.width || 1,
		height: this.options.height || 1
	};
	this.expectedStop = true;	// flag to know when the stop was initiated by the user or not
	this.expectedPlay = false;	// flag to know that player was playing before the stop
	var previous = {};
	// autoload modules
	if(this.options.autoloadModules){
		for(var i=0; i<autoloadModules.length; i++){
			if(typeof window[autoloadModules[i]] == 'function'){
				this.addModule(new window[autoloadModules[i]]);
			}
		}
	}
	var fireChangeEvent = function(type, value){
		if (!this.listeners[type]) {return;}
		for (var i=0; i<this.listeners[type].length; i++) {
			if (this.listeners[type][i]) {
				try{this.listeners[type][i].call(this, value);}catch(e){}
			}
		}
	};
	var updaterChangeTypes = ['src', 'state', 'mute', 'volume', 'duration', 'position'];
	var updaterFunction = function(){
		if(this.current.module){
			try{this.current.state = this.current.module.getState();}catch(e){}
			try{this.current.mute = this.current.module.getMute();}catch(e){}
			try{this.current.volume = this.current.module.getVolume();}catch(e){}
			try{this.current.duration = this.current.module.getDuration();}catch(e){}
			try{this.current.position = this.current.module.getPosition();}catch(e){}
			for(var i=0; i<updaterChangeTypes.length; i++){
				if(previous[updaterChangeTypes[i]] != this.current[updaterChangeTypes[i]]){
					previous[updaterChangeTypes[i]] = this.current[updaterChangeTypes[i]];
					fireChangeEvent.call(this, updaterChangeTypes[i], this.current[updaterChangeTypes[i]]);
				}
			}
			if(this.current.state == this.states.stopped){
				if(this.expectedStop){
					this.expectedStop = false;
					this.expectedPlay = false;
				}
				else if(this.expectedPlay && this.options.repeat){
					this.stop(null, true);
					this.play();
				}
			}
		}
	};
	this.updater = setInterval((function(self){return function(){updaterFunction.call(self);};})(this), this.options.updaterInterval);
	// controls
	this.addControl('getVersion', function(){
		var module = this.current.module ? this.current.module.title : '';
		if(this.current.module && this.current.module.getVersion){
			if(version = this.current.module.getVersion()){
				module+= ' '+version;
			}
		}
 		return this.name +' '+ this.version + (module ? ' ('+ module +')' : '');
	});
	this.addControl('getState', function(){
		return this.current.state;
	});
	this.addControl('play', function(){
		if(this.current.module.play){
			this.expectedPlay = true;
			if(this.options.noCache){
				var baseSrc = this.current.src;
				var seedIndex = 0;
				if((seedIndex = baseSrc.indexOf('seed=')) > 0){
					baseSrc = baseSrc.substring(0, seedIndex - 1);
				}
				var url = baseSrc + (baseSrc.indexOf('?') >= 0 ? '&' : '?') + 'seed=' + Math.floor(Math.random()*100000000);
				this.current.src = url;
			}
			return this.current.module.play();
		}
	});
	this.addControl('pause', function(){
		if(this.current.module.pause){
			return this.current.module.pause();
		}
	});
	this.addControl('prev', function(){
		fireChangeEvent.call(this, 'prev', true);
	});
	this.addControl('next', function(){
		fireChangeEvent.call(this, 'next', true);
	});
	this.addControl('stop', function(e, unexpected){
		if(this.current.module.stop){
			if(!unexpected){
				this.expectedStop = true;
			}
			return this.current.module.stop();
		}
	});
	this.addControl('fullScreen', function(){
		if(this.current.module.fullScreen){
			return this.current.module.fullScreen();
		}
	});
	this.addControl('mute', function(){
		if(this.current.module.setMute && this.current.module.getMute){
			var turn = !this.current.module.getMute();
			this.current.module.setMute(turn);
			return turn;
		}
	});
	this.addControl('volume', function(volume){
		if(typeof(volume) != 'undefined' && this.current.module.setVolume){	
			this.current.module.setVolume(parseFloat(volume));
		}
		return this.current.module.getVolume ? this.current.module.getVolume() : this.current.volume;
	});
	this.addControl('position', function(position){
		if(typeof(position) != 'undefined' && this.current.module.setPosition){
			this.current.module.setPosition(parseFloat(position));
		}
		return this.current.module.getPosition ? this.current.module.getPosition() : this.current.position;
	});
};


UniplayerException = function(e){
	this.error = e || null;
	this.message = this.error ? this.error.message : '';
};


Uniplayer.prototype.addEventListener = function(type, listener){
	if (!this.listeners[type]) {this.listeners[type] = [];}
	this.listeners[type].push(listener);
};


Uniplayer.prototype.removeEventListener = function(type, listener){
	if (!this.listeners[type]) {return;}
	for (var i=0; i<this.listeners[type].length; i++) {
		if (this.listeners[type][i] == listener) {
			delete this.listeners[type][i];
		}
	}
};


Uniplayer.prototype.log = function(e){
	if(typeof(this.options.logger) != 'undefined'){
		if(typeof(this.options.logger) == 'object'){
			this.options.logger.log('Uniplayer: '+e.message);
		}
		else if(this.options.logger === 'alert'){
			alert('Uniplayer Exception\n\n' + e.message);
		}
	}
};


Uniplayer.prototype.setOptions = function(options){
	if(typeof options != 'object'){
		return false;
	}
	for(var i in options){
		this.options[i] = options[i];
	}
	return true;
};


Uniplayer.prototype.getMimeType = function(src){
	try{
		if(!src){
			throw new UniplayerException({message:'No source to get mime type of'});
		}
	}
	catch(e){
		this.log(e);
		return '';
	}
	var mimetype = this.mimeTypeCache[src] || '';
	if(!mimetype){
		var qp = -1;
		if(qp = src.indexOf('?') >= 0){
			src = src.substring(0, qp);
		}
		var ext = UniplayerUtils.getExtension(src);
		if(ext && this.mimes){	// get from file 'uniplayer-mimes.js' if exists
			mimetype = this.mimes[ext];
		}
		if(!mimetype){	// get from server's HTTP header
			mimetype = this.queryMimeType(src);
		}
	}
	this.mimeTypeCache[src] = mimetype;
	return mimetype;
};


Uniplayer.prototype.queryMimeType = function(src){		// works only on same domain due to security reasons
	var jarvey, result = '';
	if(jarvey = new XMLHttpRequest){
		var logindata, user, pass;
		if(logindata = src.substring(src.indexOf('//')+2, src.indexOf('@'))){	// detect user:pass@ in the src
			src = src.replace(logindata+'@', '');
			logindata = logindata.split(':');
			user = logindata[0] || '';
			pass = logindata[1] || '';
		}
		try{
			jarvey.open('HEAD', src, false, user, pass);
			jarvey.send(null);
			if(jarvey.status && jarvey.status.toString().substring(0, 1).valueOf() < 4){
				result = jarvey.getResponseHeader('Content-Type').split(';')[0].replace(/(^\s+)|(\s+$)/g, '');
			}
			else{
				throw new UniplayerException({message:'Seems file is not accessible'});
			}
		}
		catch(e){
			this.log(e);
		}
	}
	return result;
};


Uniplayer.prototype.addModule = function(module){
	try{
		if(typeof(module) != 'object' || !module.name || !(module.supported instanceof Array)){
			throw new UniplayerException({message:'Cannot add an incorrect module'});
		}
		if(this.modules[module.name]){
			throw new UniplayerException({message:'This module already registered'});
		}
	}
	catch(e){
		this.log(e);
		return;
	}
	module.player = this;	// back reference
	this.modules[module.name] = module;
	this.modulesList.push(module.name);
	for(var i=0; i<module.supported.length; i++){
		if (this.options.onlyAudio && module.supported[i].indexOf('audio/') < 0) continue;
		if (this.options.onlyVideo && module.supported[i].indexOf('video/') < 0) continue;
		if(!this.supported[module.supported[i]]){
			this.supported[module.supported[i]] = [];
		}
		this.supported[module.supported[i]].push(module.name);
	}
	module.present = this.pluginExists(module.needle, module.progid, module.classid);
};


Uniplayer.prototype.addModules = function(modules){
	if(!(modules instanceof Array)) return;
	for(var i=0; i<modules.length; i++){
		this.addModule(modules[i]);
	}
};


Uniplayer.prototype.getModule = function(src, mimetype){
	var modulesList = [], moduleName = '';
	try{
		if(!this.modulesList.length){
			throw new UniplayerException({message:'No modules found'});
		}
	}
	catch(e){
		this.log(e);
		return moduleName;
	}
	if(!mimetype){
		mimetype = this.getMimeType(src);
	}
	if(mimetype && this.supported[mimetype]){
		modulesList = this.supported[mimetype];
	}
	//else{
	//	modulesList = this.modulesList;
	//}
	for(var i=0; i<modulesList.length; i++){
		if(this.modules[modulesList[i]].present){
			moduleName = modulesList[i];	// present module found
			break;
		}
	}
	if(!moduleName){
		moduleName = modulesList[0];	// if no present modules found, use first supported module
	}
	return moduleName;
};


Uniplayer.prototype.installModule = function(moduleName){
	if(this.modules[moduleName].pluginspage){
		if (confirm(this.modules[moduleName].title+' plug-in is needed to play this media.\nDo you wish to open the page "'+this.modules[moduleName].pluginspage+'" to perform  manual install of this plug-in?')) {
			// perform manual install
			window.open(this.modules[moduleName].pluginspage);
		}
	}
	else {
		// just notify about missing plugin
		alert(this.modules[moduleName].title+' plug-in is needed to play this media.\nPlease install this module manually and reload this page');
	}
};


Uniplayer.prototype.pluginExists = function(needle, progid, classid){
	if (needle == 'Html5') {
		result = navigator.userAgent.indexOf('MSIE') == -1;
	}
	else {
		if (progid == 'ShockwaveFlash.ShockwaveFlash') {
			var getFlashVersion = function(){
				try {
					try {
						// avoid fp6 minor version lookup issues
						// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
						var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
						try {
							axo.AllowScriptAccess = 'always';
						}
						catch(e) {
							return '6,0,0';
						}
			    	}
			    	catch(e) {}
					return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
				}
				catch(e) {
					try {
						if (navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin) {
							return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
						}
					}
					catch(e) {}
				}
				return '0,0,0';
			}
			var majorVersion = getFlashVersion().split(',').shift();
			return (majorVersion >= 9);
		}
		var np, result = false;
		if(typeof(ActiveXObject) == 'function'){
			try{
				var axo = new ActiveXObject(progid);
				result = axo ? true : false;
				delete axo;
			}
			catch(e){}
		}
		else if(np=navigator.plugins){
			var re=new RegExp((needle instanceof Array)?needle.join('.*'):needle, 'i');
			for(var i=0; i<np.length; i++){
				if(re.test(np[i].name) || re.test(np[i].description)){
					result = true;
					break;
				}
			}
		}
	}
	return result;
};


Uniplayer.prototype.write = function(holder, GUI){
	try{
		if(typeof holder == 'string'){
			holder = document.getElementById(holder);
		}
		else if(!holder){
			holder = document.body;
		}
		if(!holder){
			throw new UniplayerException({message:'Cannot write player'});
		}
		if(!GUI && typeof(UniplayerGUIDefault) == 'function'){
			GUI = new UniplayerGUIDefault(this);
		}
		if(!GUI || !GUI.getHTML){
			throw new UniplayerException({message:'No GUI available'});
		}
		if(this.options.clearHolder){
			holder.innerHTML = '';
		}
		this.GUI = GUI;
		holder.innerHTML+= GUI.getHTML();
		this.holders.main = UniplayerUtils.getElementsByClassName('upGUI', 'div', holder)[0];
		this.holders.wrapper = UniplayerUtils.getElementsByClassName('upGUIWrapper', 'div', holder)[0];
		this.holders.movie = UniplayerUtils.getElementsByClassName('upGUIMovie', 'div', holder)[0];
		this.holders.controls = UniplayerUtils.getElementsByClassName('upGUIControls', 'div', holder)[0];
		if(!this.holders.main || !this.holders.wrapper || !this.holders.movie || !this.holders.controls){
			throw new UniplayerException({message:'Cannot write broken GUI'});
		}
	}
	catch(e){
		this.log(e);
		return;
	}
	var self = this;
	// background
	this.holders.movie.style.backgroundColor = this.options.background;
	// autoload / preview / showSupply
	if(this.options.autoload && this.current.src){
		this.load(this.current.src, this.current.mimetype);
	}
	else if(this.options.preview && GUI.getPreview){
		this.holders.movie.innerHTML = GUI.getPreview(this.options.preview);
		this.holders.movie.firstChild.onclick = function() {
			self.play();
		}
	}
	else if(this.options.showSupply && GUI.getSupply){
		this.holders.movie.innerHTML = GUI.getSupply();
	}
	else if(!this.options.hideStartLogo){
		this.holders.movie.innerHTML = GUI.getPreview();
	}
	// sizing
//	this.holders.main.style.width = this.options.width + (this.holders.controls.style.width ? parseInt(this.holders.controls.style.width) : 0) + 'px';
	this.holders.main.style.height = this.options.height + (this.options.showControls ? (this.holders.controls.offsetHeight + 2) : 0) + 'px';		// 2 for border
	if(this.options.showControls){
		// buttons
		// focus/hover emulation
		var buttons = UniplayerUtils.getElementsByClassName('upGUIButton', 'a', holder);
		var buttonFocus = function(){
			this.className += ' hover';
		};
		var buttonBlur = function(){
			this.className = this.className.replace(' hover', '');
		};
		for(var i=0; i<buttons.length; i++){
			buttons[i].onfocus = buttonFocus;
			buttons[i].onblur = buttonBlur;
		}
		var buttonMenu = UniplayerUtils.getElementsByClassName('upGUIButtonMenu', 'a', holder)[0];
		var buttonPrev = UniplayerUtils.getElementsByClassName('upGUIButtonPrev', 'a', holder)[0];
			if(buttonPrev){buttonPrev.onclick = function() {self.prev(); return false;};}
		var buttonPlay = UniplayerUtils.getElementsByClassName('upGUIButtonPlay', 'a', holder)[0];
			if(buttonPlay){buttonPlay.onclick = function() {self.play(); return false;};}
		var buttonPause = UniplayerUtils.getElementsByClassName('upGUIButtonPause', 'a', holder)[0];
			if(buttonPause){buttonPause.onclick = function() {self.pause(); return false;};}
		
		if(buttonMenu || buttonPause){
  		this.addEventListener('state', function(state){
  			switch(state){
  				case self.states.playing:
  					if(buttonMenu){buttonMenu.className = buttonMenu.className.replace(' disabled', '');}
  					if(buttonPause){buttonPause.style.visibility = 'visible';}
  				break;
  				case self.states.loading:
  					if(buttonMenu){buttonMenu.className+= ' disabled';}
  				break;
  				default:
  					if(buttonMenu){buttonMenu.className = buttonMenu.className.replace(' disabled', '');}
  					if(buttonPause && buttonPause.style.visibility == 'visible'){buttonPause.style.visibility = 'hidden';}
  				break;
  			}
  		});
		}
			
		var buttonStop = UniplayerUtils.getElementsByClassName('upGUIButtonStop', 'a', holder)[0];
			if(buttonStop){buttonStop.onclick = function() {self.stop(); return false;};}
		var buttonNext = UniplayerUtils.getElementsByClassName('upGUIButtonNext', 'a', holder)[0];
			if(buttonNext){buttonNext.onclick = function() {self.next(); return false;};}
		var buttonFullScreen = UniplayerUtils.getElementsByClassName('upGUIButtonFullScreen', 'a', holder)[0];
			if(buttonFullScreen){
				buttonFullScreen.onclick = function(){
					if(this.className.indexOf('disabled') < 0){
						self.fullScreen();
					}
					return false;
				}
			}
		// volume
		var volumeSet = UniplayerUtils.getElementsByClassName('upGUIVolume', 'div', holder)[0];
		if(volumeSet){
			var buttonMute = UniplayerUtils.getElementsByClassName('upGUIButtonMute', 'a', volumeSet)[0];
				if(buttonMute){
					buttonMute.onclick = function() {self.mute(); return false;};
					this.addEventListener('mute', function(mute){
						if(mute){
							buttonMute.className+= ' disabled';
						}
						else{
							buttonMute.className = buttonMute.className.replace(' disabled', '');
						}
					});
				}
			var volumeSlider = UniplayerUtils.getElementsByClassName('upGUISlider', 'div', volumeSet)[0];
			var volumePointer = UniplayerUtils.getElementsByClassName('upGUIPointer', 'a', volumeSet)[0];
			if(volumeSlider && volumePointer){
				this.volumeSlider = new UniplayerSlider(volumePointer, volumeSlider);
				this.volumeSlider.set(this.options.volume);
				this.volumeSlider.onChange = function(volume){
					self.volume(volume);
				};
				this.addEventListener('volume', function(volume){
					self.volumeSlider.set(volume);
				});
			}
		}
		// time
		var timeMonitor = UniplayerUtils.getElementsByClassName('upGUITime', 'div', holder)[0];
		if(timeMonitor){
			timeMonitor.onselectstart = function(){return false;};
			timeMonitor.ondragstart = function(){return false;};
			timeMonitor.onclick = function(){
				if(self.current.state == self.states.paused){
					GUI.timeReverse = !GUI.timeReverse;
					GUI.setTime(timeMonitor, self.current.position*self.current.duration, self.current.duration);
				}
				else if(self.current.state == self.states.playing){
					GUI.timeReverse = !GUI.timeReverse;
				}
			};
			this.addEventListener('duration', function(duration){
				GUI.setTime(timeMonitor, duration, duration, true);
			});
		}
		// position
		var positionSet = UniplayerUtils.getElementsByClassName('upGUIPosition', 'div', holder)[0];
		if(positionSet){
			var positionSlider = UniplayerUtils.getElementsByClassName('upGUISlider', 'div', positionSet)[0];
			var positionPointer = UniplayerUtils.getElementsByClassName('upGUIPointer', 'a', positionSet)[0];
			if(positionSlider && positionPointer){
				this.positionSlider = new UniplayerSlider(positionPointer, positionSlider);
				this.positionSlider.onChange = function(position){
					self.position(position);
				};
				this.addEventListener('position', function(position){
					self.positionSlider.set(position);
					if(timeMonitor){
						var stopped = (!position && self.current.state == self.states.stopped);
						GUI.setTime(timeMonitor, (stopped ? self.current.duration : position*self.current.duration), self.current.duration, stopped);
					}
				});
			}
		}
		// title
		var titleMonitor = UniplayerUtils.getElementsByClassName('upGUITitle', 'nobr', holder)[0];
		if(titleMonitor){
			GUI.titleMonitor = titleMonitor;
			this.addEventListener('src', function(src){
				GUI.setTitle(null, src);
				if(buttonFullScreen){
					if(self.current.module && (typeof self.current.module.fullScreen != 'function')){
						buttonFullScreen.className += ' disabled';
					}
					else{
						buttonFullScreen.className = buttonFullScreen.className.replace(' disabled', '');
					}
				}
			});
		}
		// menu
		var menu = UniplayerUtils.getElementsByClassName('upGUIMenu', 'div', holder)[0];
		if(menu && buttonMenu){
			buttonMenu.onclick = function(){
				(menu.style.display = (menu.style.display == 'block' ? 'none' : 'block')) == 'block'
				? (this.className += ' active')
				: (this.className = this.className.replace(' active',''))
			};
		}
		// version
		var version = UniplayerUtils.getElementsByClassName('upGUIVersion', 'span', holder)[0];
		if(version){
			version.innerHTML = this.version;
		}
	}
};


Uniplayer.prototype.loadPlay = function(src, mimetype, moduleName){
	this.stop();
	var resetAutoplay = false;
	if (!this.options.autoplay) {
		this.options.autoplay = true;
		resetAutoplay = true;
	}
	this.load(src, mimetype, moduleName);
	if (resetAutoplay) {
		this.options.autoplay = false;
	}
};


Uniplayer.prototype.load = function(src, mimetype, moduleName){
	try{
		if(!src){
			src = this.current.src;
		}
		if(!src){
			throw new UniplayerException({message:'No file to play'});
		}
		if (!mimetype) {
			mimetype = this.getMimeType(src);
		}
		if(!moduleName){
			moduleName = this.getModule(src, mimetype);
		}
		if(!moduleName){
			var ext = UniplayerUtils.getExtension(src);
			var message = '';
			if(ext){
				message = 'Unknown file format "'+ext+'"'
			}
			else{
				message = 'Cannot play this URL: ' + decodeURIComponent(src);
			}
			this.GUI.setTitle(message, src);
			throw new UniplayerException({message:message});
		}
	}
	catch(e){
		this.log(e);
		return;
	}
	this.current.src = src;
	this.current.mimetype = mimetype;
	if(this.current.module != this.modules[moduleName]){
		if(this.current.module){
			try {
				this.current.module.stop();
			}
			catch(e){
				this.log(e);
			}
		}
		this.current.module = this.modules[moduleName];
		try{
			this.current.movie = this.current.module.build();
			this.holders.main.style.height = this.current.height + this.holders.controls.offsetHeight + 2 + 'px';		// 2 for border
			// test modules
			if(this.current.module.test && !this.current.module.test()){
				for(var i in this.modules){
					if(i == moduleName){continue;}
					if(this.modules[i].test){
						if(this.modules[i].test()){
							this.current.module = this.modules[i];
							break;
						}
					}
				}
			}
		}
		catch(e){
			this.log(e);
		}
	}
	else{
		try{
			this.current.module.reload();
			if(this.options.autoplay){
				this.current.module.play();
			}
		}
		catch(e){
			this.log(e);
		}
	}
};


Uniplayer.prototype.addControl = function(name, fn){
	if(!name || typeof(fn) != 'function'){
		return false;
	}
	var self = this;
	this[name] = function(){
		var args = arguments;
		try{
			if(name == 'play' && !self.current.module && self.current.src && !self.options.autoload && !self.options.autoplay){
				self.options.autoplay = true;
				self.load(self.current.src, self.current.mimetype);
				self.options.autoplay = false;
				return true;
			}
			else if(typeof self.current.movie == 'undefined'){
				throw new UniplayerException({message:'No movie to control ' + name});
			}
			if(!self.current.module.present){
				if (name == 'play') {
					self.installModule(self.current.module.name);
				}
				return false;
			}
			if(self.current.module.name.indexOf('flash') == 0){
				try{
					return fn.apply(self, args);
				}
				catch(e){	// dirty-fix for flash-player - it sometimes fails to listen js commands until page reload.
					if(self.options.flashReloadPage && name != 'fullScreen'){
						window.location.reload();
					}
					else {
						//self.log(e);
					}
				}
			}
			else{
				return fn.apply(self, args);
			}
		}
		catch(e){
			self.log(e);
		}
	};
};


Uniplayer.prototype.pageScreen = function(resize){
	if(!this.current.movie){return;}
	if(!this.current.pageScreen){
		// remove body scrollbars
		document.body.className += 'upGUINoScroll';
		// get wrapper position
		var sx = (typeof pageXOffset != 'undefined') ? pageXOffset : document.body.scrollLeft;
		var sy = (typeof pageYOffset != 'undefined') ? pageYOffset : document.body.scrollTop;
		var ax = UniplayerUtils.getAbsLeft(this.holders.wrapper);
		var ay = UniplayerUtils.getAbsTop(this.holders.wrapper);
		// set wrapper position
		with(this.holders.wrapper.style){
			top = sy - ay + 'px';
			left = sx - ax + 'px';
		}
		// connect window resize
		if(typeof window.onresize == 'function'){window._onresize = window.onresize;}
		var self = this;
		window.onresize = function(){
			if(self.current.pageScreen){
				self.pageScreen.call(self, true);
			}
			if(typeof window._onresize == 'function'){window._onresize.call();}
		}
		// connect 'esc' button
		if(typeof document.onkeydown == 'function'){document._onkeydown = document.onkeydown;}
		document.onkeydown = function(e){
			var keynum, out;
			if(window.event){
				keynum = window.event.keyCode;
			}
			else if(e.which){
				keynum = e.which;
			}
			if(keynum == 27 && self.current.pageScreen){
				self.pageScreen.call(self);
				out = false;
			}
			else{
				out = true;
			}
			if(typeof document._onkeydown == 'function'){document._onkeydown.call();}
			return out;
		}
		this.current.pageScreen = true;
		resize = true;
	}
	if(resize){
		// set movie size
		var cw = (document.documentElement.clientWidth ? document.documentElement.clientWidth : (window.innerWidth ? window.innerWidth : document.body.offsetWidth));
		var ch = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight));
		if(typeof ActiveXObject != 'undefined'){
			cw-= 20;
			ch-= 4;
		}
		this.current.movie.width = cw;
		this.current.movie.height = ch - this.holders.controls.offsetHeight;
		this.holders.wrapper.style.width = this.current.movie.width + 'px';
	}
	else{
		// revert body scrollbars
		document.body.className = document.body.className.replace('upGUINoScroll', '');
		// revert movie size and wrapper position
		this.current.movie.width = this.current.width;
		this.current.movie.height = this.current.height;
		this.holders.wrapper.style.width = this.current.movie.width + 'px';
		with(this.holders.wrapper.style){
			top = 'auto';
			left = 'auto';
		}
		// revert events
		document.onkeydown = (typeof document._onkeydown == 'function') ? document._onkeydown : null;
		window.onresize = (typeof window._onresize == 'function') ? window._onresize : null;
		this.current.pageScreen = false;
	}
	return this.current.pageScreen;
};


Uniplayer.prototype.UniplayerObject = function(options, html5){
	var obj, ax = typeof(ActiveXObject) == 'function';
	if (html5) {
		obj = document.createElement(html5);
		if(options.id){
			obj.setAttribute('id', options.id);
		}
		obj.setAttribute('src', options.src);
		if (options.type) {
			obj.setAttribute('type', options.type);
		}
		if (html5 == 'video') {
			obj.setAttribute('width', options.width);
			obj.setAttribute('height', options.height);
		}
	}
	else {
		if(ax){
			// object
			obj = '<object';
			if(options.id){
				obj+= ' id="'+options.id+'"';
			}
			obj+= ' width="'+options.width+'"';
			obj+= ' height="'+options.height+'"';
			obj+= ' classid="'+options.classid+'"';
			if(options.codebase){
				obj+= ' codebase="'+options.codebase+'"';
			}
			obj+= '>';
			obj+= '</object>';
		}
		else{
			// embed
			obj = document.createElement('embed');
			if(options.id){
				obj.setAttribute('id', options.id);
			}
			obj.setAttribute('src', options.src);
			obj.setAttribute('width', options.width);
			obj.setAttribute('height', options.height);
			obj.setAttribute('type', options.type);
			if(options.pluginspage){
				obj.setAttribute('pluginspage', options.pluginspage);
			}
		}
	}
	
	this.addParam = function(name, value, axOnly){
		if(!name) return;
		if(typeof value == 'boolean'){
			value = value ? 'true' : 'false';
		}
		if (html5) {
			if (name == 'src' && value instanceof Array) {
				var source;
				for (var i=0; i<value.length; i++) {
					source = document.createElement('source');
					source.setAttribute('src', value[i]);
					obj.appendChild(source);
				}
			}
			else {
				obj.setAttribute(name, value);
			}
		}
		else {
			if(ax){
				obj = obj.replace('</object>', '<param name="'+name+'" value="'+value+'"/></object>');
			}
			else if(!axOnly){
				obj.setAttribute(name, value);
			}
		}
	};
	
	this.write = function(to, append){
		if(!to || !to.tagName) return;
		if(!append){
			to.innerHTML = '';
		}
		if(ax){
			to.innerHTML+= obj;
		}
		else{
			to.appendChild(obj);
		}
		return to.lastChild;
	};
};


UniplayerUtils = {
	getExtension: function(src){
		src = decodeURIComponent(src);
		src = src.substring(src.lastIndexOf('/')+1);
		return src.substring(src.lastIndexOf('.')+1).toLowerCase();
	},
	timeToString: function(time, negative, loading){
		if(!time){return loading ? 'loading ' : '0:00';}
		var addZero = function(number){
			return (number < 10 ? ('0' + number) : number.toString());
		};
		time = parseInt(time);
		if(time < 60){
			return (negative ? '-' : '') + '0:' + addZero(time);
		}
		else{
			var seconds = 0, minutes = 0, hours = 0;
			seconds = time % 60;
			minutes = (time - seconds) / 60;
			if(minutes > 60){
				var m = minutes % 60;
				hours = (minutes - m) / 60;
				minutes = m;
			}
			return (negative ? '-' : '') + (hours ? (hours + ':') : '') + addZero(minutes) +':'+ addZero(seconds);
		}
	},
	getAbsLeft: function(obj, limiter){
		if(!limiter){limiter = document.body;}
		var element = obj;
		var offset = 0;
		while(element){
			if(element == limiter){break;}
			offset += element.offsetLeft;
			element = element.offsetParent;
		}
		return offset;
	},
	getAbsTop: function(obj, limiter){
		if(!limiter){limiter = document.body;}
		var element = obj;
		var offset = 0;
		while(element){
			if(element == limiter){break;}
			offset += element.offsetTop;
			element = element.offsetParent;
		}
		return offset;
	},
	getMousePosition: function(e){
		var x=0, y=0;
		if(!e || (typeof(e.pageX) != 'number' && typeof(e.clientX) != 'number')){return {x: x, y: y};}
		if(typeof(e.pageX) == 'number'){
			var x = e.pageX;
			var y = e.pageY;
		}
		else{
			var x = e.clientX;
			var y = e.clientY;
			if(!(
				(window.navigator.userAgent.indexOf('Opera') + 1)
				|| (window.ScriptEngine && ScriptEngine().indexOf('InScript') + 1)
				|| window.navigator.vendor == 'KDE'
			)){
				if(document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)){
					x += document.documentElement.scrollLeft;
					y += document.documentElement.scrollTop;
				}
				else if(document.body && (document.body.scrollTop || document.body.scrollLeft)){
					x += document.body.scrollLeft;
					y += document.body.scrollTop;
				}
			}
		}
		return {x: x, y: y};
	},
	/*
	Developed by Robert Nyman, http://www.robertnyman.com
	Code/licensing: http://code.google.com/p/getelementsbyclassname/
	*/
	getElementsByClassName: function (className, tag, elm){
		if (document.getElementsByClassName) {
			getElementsByClassName = function (className, tag, elm) {
				elm = elm || document;
				var elements = elm.getElementsByClassName(className),
					nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
					returnElements = [],
					current;
				for(var i=0, il=elements.length; i<il; i+=1){
					current = elements[i];
					if(!nodeName || nodeName.test(current.nodeName)) {
						returnElements.push(current);
					}
				}
				return returnElements;
			};
		}
		else if (document.evaluate) {
			getElementsByClassName = function (className, tag, elm) {
				tag = tag || "*";
				elm = elm || document;
				var classes = className.split(" "),
					classesToCheck = "",
					xhtmlNamespace = "http://www.w3.org/1999/xhtml",
					namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
					returnElements = [],
					elements,
					node;
				for(var j=0, jl=classes.length; j<jl; j+=1){
					classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
				}
				try	{
					elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
				}
				catch (e) {
					elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
				}
				while ((node = elements.iterateNext())) {
					returnElements.push(node);
				}
				return returnElements;
			};
		}
		else {
			getElementsByClassName = function (className, tag, elm) {
				tag = tag || "*";
				elm = elm || document;
				var classes = className.split(" "),
					classesToCheck = [],
					elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
					current,
					returnElements = [],
					match;
				for(var k=0, kl=classes.length; k<kl; k+=1){
					classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
				}
				for(var l=0, ll=elements.length; l<ll; l+=1){
					current = elements[l];
					match = false;
					for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
						match = classesToCheck[m].test(current.className);
						if (!match) {
							break;
						}
					}
					if (match) {
						returnElements.push(current);
					}
				}
				return returnElements;
			};
		}
		return getElementsByClassName(className, tag, elm);
	},
	loadCSS: function(src){
		if(!src){return false;}
		var holder = document.getElementsByTagName('head')[0];
		if(!holder){
			holder = document.createElement('head');
			document.body.parentNode.insertBefore(holder, document.body);
		}
		var link = document.createElement('link');
		link.rel = 'stylesheet';
		link.href = src;
		holder.appendChild(link);
		return true;
	},
	animate: function(obj, prop, start, stop, step, interval, callback){
		if(!obj || !prop || typeof(start) != 'number' || typeof(stop) != 'number' || start == stop){return;}
		if(!step){step = 1;}
		if(!interval){interval = 20;}
		var timer;
		var handler = (function(pos){
			var freeze = false;
			return function(){
				if(pos > stop){
					pos-= step;
					if(pos <= stop){
						pos = stop;
						freeze = true;
					}
				}
				else if(pos < stop){
					pos+= step;
					if(pos >= stop){
						pos = stop;
						freeze = true;
					}
				}
				else{
					freeze = true;
				}
				if(freeze){
					clearInterval(timer);
					if(typeof callback == 'function'){
						callback.call(obj);
					}
				}
				obj.style[prop] = pos + 'px';
			};
		})(start);
		return timer = setInterval(handler, interval);
	}
};


UniplayerSlider = function(pointer, holder){
	if(!pointer || (typeof(pointer.tagName) == 'undefined' && !(pointer=document.getElementById(pointer)))){return;}
	if(!holder || (typeof(holder.tagName) == 'undefined' && !(holder=document.getElementById(holder)))){holder = document.body;}
	var self = this;
	this.pointer = pointer;
	this.holder = holder;
	this.vertical = false;
	this.seekInterval = .05; // float percent
	this.pointer.onclick = function(){return false;};
	this.pointer.ondragstart = function(){return false;};
	this.pointer.onselectstart = function(){return false;};
	this.set = function(percent, change){
		if(percent < 0){percent = 0;}
		else if(percent > 1){percent = 1;}
		self.pointer.style[self.vertical ? 'top' : 'left'] = Math.floor(percent*100) + '%';
		if(change && typeof(self.onChange) == 'function'){
			self.onChange.call(self, percent);
		}
	};
	// events
	var drag = function(e){
		if(!e && !(e = window.event)){return true;}
		if(document.onmousemove == moving){return false;} // multiclick protection
		self.mouse = UniplayerUtils.getMousePosition(e);
		self.offset = self.vertical ? UniplayerUtils.getAbsTop(self.pointer, self.holder) : UniplayerUtils.getAbsLeft(self.pointer, self.holder);
		self.limit = self.vertical ? self.holder.offsetHeight : self.holder.offsetWidth;
		self._onmousemove = document.onmousemove;
		self._onmouseup = document.onmouseup;
		document.onmousemove = moving;
		document.onmouseup = drop;
		self.holder.style.cursor = 'pointer';
		return false;
	};
	var drop = function(e){
		document.onmousemove = self._onmousemove;
		document.onmouseup = self._onmouseup;
		self.holder.style.cursor = 'default';
		return false;
	};
	var moving = function(e){
		if(!e && !(e = window.event)){return true;}
		var mouse = UniplayerUtils.getMousePosition(e);
		var delta = self.vertical ? (mouse.y - self.mouse.y) : (mouse.x - self.mouse.x);
		var offset = self.offset + delta;
		self.set(offset/self.limit, true);
	};
	var point = function(e){
		if(!e && !(e = window.event)){return true;}
		var mouse = UniplayerUtils.getMousePosition(e);
		var offset = self.vertical ? UniplayerUtils.getAbsTop(self.holder) : UniplayerUtils.getAbsLeft(self.holder);
		var delta = (self.vertical ? mouse.y : mouse.x) - offset - Math.round(self.pointer.offsetWidth/2);
		var limit = self.vertical ? self.holder.offsetHeight : self.holder.offsetWidth;
		if(delta >= 0 || delta <= limit){
			self.set(delta/limit, true);
		}
	};
	var seek = function(e){
		if(!e && !(e = window.event)){return true;}
		var dir;
		if(e.keyCode == 37){
			dir = 'left';
		}
		else if(e.keyCode == 39){
			dir = 'right';
		}
		else{return true;}
		var offset = self.vertical ? self.pointer.offsetTop : self.pointer.offsetLeft;
		var limit = self.vertical ? self.holder.offsetHeight : self.holder.offsetWidth;
		var delta = Math.round(dir == 'right' ? (offset + limit*self.seekInterval) : (offset - limit*self.seekInterval));
		if(delta < 0){
			delta = 0;
		}
		else if(delta > limit){
			delta = limit;
		}
		self.set(delta/limit, true);
	};
	this.holder.onclick = point;
	this.pointer.onmousedown = drag;
	if(navigator.userAgent.indexOf('Firefox') >= 0 && navigator.userAgent.indexOf('Mac') >= 0){
		this.pointer.onkeypress = seek;		// workaround to support repeating in FF on Mac
	}
	else{
		this.pointer.onkeydown = seek;
	}
};


UniplayerGUIDefault = function(player){
	var lang = UniplayerLanguages[player.options.language];
	var HTMLControls = '<div class="upGUITitleHolder"><nobr class="upGUITitle"></nobr></div><div class="upGUIButtonSet"><a href="javascript:" class="upGUIButton upGUIButtonPrev" title="'+lang.controlsPrevious+'"></a><a href="javascript:" class="upGUIButton upGUIButtonPlay" title="'+lang.controlsPlay+'"></a><a href="javascript:" class="upGUIButton upGUIButtonPause" title="'+lang.controlsPause+'"></a><a href="javascript:" class="upGUIButton upGUIButtonStop" title="'+lang.controlsStop+'"></a><a href="javascript:" class="upGUIButton upGUIButtonNext" title="'+lang.controlsNext+'"></a></div><div class="upGUIVolume"><a href="javascript:" class="upGUIButton upGUIButtonMute" title="'+lang.controlsMute+'"></a><div class="upGUISlider" title="'+lang.controlsVolume+'"><div class="upGUISliderTail"></div><a href="javascript:" class="upGUIButton upGUIPointer"></a></div></div><div class="upGUIPosition"><div class="upGUITime" title="'+lang.controlsTime+'"></div><div class="upGUISlider" title="'+lang.controlsPosition+'"><div class="upGUISliderTail"></div><a href="javascript:" class="upGUIButton upGUIPointer"></a></div></div><a href="javascript:" class="upGUIButton upGUIButtonFullScreen" title="'+lang.controlsFullScreen+'"></a><a href="javascript:" class="upGUIButton upGUIButtonPlaylist" title="'+lang.controlsPlaylist+'"></a><div class="upGUIMenu"><a class="upGUIMenuAbout" href="http://code.google.com/p/uniplayer/" target="_blank">'+lang.about+' Uniplayer <span class="upGUIVersion"></span></a></div><a href="javascript:" class="upGUIButton upGUIButtonMenu" title="'+lang.controlsMenu+'"></a>';
	this.getHTML = function(){
		if(player.options.showControls && player.options.width < 210){
			player.options.width = 210;
		}
		if(player.options.showControls || player.options.showSupply){
			UniplayerUtils.loadCSS(player.options.guiPath + 'uniplayer.css');
		}
		return '<div class="upGUI"><div class="upGUIWrapper"><div class="upGUIMovie"></div><div class="upGUIControls" style="height: 46px; display: '+(player.options.showControls ? 'block' : 'none')+'">'+(player.options.showControls ? HTMLControls : '')+'</div></div></div>';
	};
	this.getPreview = function(src){
		return '<div style="' + (src ? 'cursor:pointer;' : '') + 'background:' + player.options.background + ' url('+(src || (player.options.guiPath + 'img/logo_transparent.png'))+') no-repeat center center;height:'+(player.options.height+'px')+'"></div>';
	};
	this.getSupply = function(){
		var src, out = '', amount = 0;
		for(var i=0; i<player.modulesList.length; i++){
			if(!player.modules[player.modulesList[i]].present){
				continue;
			}
			amount++;
			if(player.options.showSupplyLogos){
				src = player.options.guiPath + 'unilogos/' + (player.options.showSupplyLogosSmall ? 'small/' : '') + player.modules[player.modulesList[i]].name + (player.options.showSupplyLogosTransparent ? '.png' : '.gif');
				out+= '<li class="upGUISupplyLogo"><img src="'+src+'" alt="'+player.modules[player.modulesList[i]].title+'" title="'+player.modules[player.modulesList[i]].title+'"/></li>';
			}
			else{
				out+= '<li>'+player.modules[player.modulesList[i]].title+'</li>';
			}
		}
		out+= '</ul>';
		out = '<ul class="upGUISupply" style="height:'+(player.options.height+'px')+'"><li class="upGUISupplyTitle'+(player.options.showSupplyLogosTransparent?' transparent':'')+'">with '+amount+' plugin'+(amount>1?'s':'')+' for your system</li>' + out;
		return out;
	};
	this.timeReverse = false;
	this.setTime = function(timeMonitor, position, duration, ignoreTimeReverse){
		if(!timeMonitor){return;}
		var timeReverse = this.timeReverse && !ignoreTimeReverse;
		if(duration && timeReverse){
			position = duration - position;
		}
		timeMonitor.innerHTML = UniplayerUtils.timeToString(position, timeReverse);
	};
	this.setTitle = function(title, src){
		if(!this.titleMonitor){return;}
		var titleMonitor = this.titleMonitor;
		if(player.options.showTitleSrc){titleMonitor.title = src ? decodeURIComponent(src) : '';}
		if(typeof title != 'string'){
			if(src){
				src = decodeURIComponent(src);
				var qp, sh, dt;
				if((qp = src.indexOf('?')) >= 0){
					src = src.substring(0, qp);
				}
				if((sh = src.lastIndexOf('/')) >= 0){
					src = src.substring(sh + 1);
				}
				if((dt = src.lastIndexOf('.')) >= 0){
					src = src.substring(0, dt);
				}
				title = src.replace(/[\_\+\.\s+]/g, ' ');
			}
			else{
				title = 'No file loaded';
			}
		}
		titleMonitor.style.left = 0;
		titleMonitor.innerHTML = title;
		var titleDiff = titleMonitor.offsetWidth - titleMonitor.offsetParent.offsetWidth;
		if(titleDiff > 0){
			var titleMoving = false;
			var titleMoved = false;
			var titleAnimation;
			var move = function(){
				if(!titleMoving){
					titleMoving = true;
					var start = this.offsetLeft;
					var stop = titleMoved ? 0 : -titleDiff;
					titleAnimation = UniplayerUtils.animate(titleMonitor, 'left', start, stop, 2, 30, function(){titleMoved = !titleMoved; titleMoving = false;});
				}
				return true;
			};
			var pause = function(){
				if(titleMoving){
					clearInterval(titleAnimation);
					titleMoving = false;
				}
				return true;
			};
			var stop = function(){
				pause();
				titleMoved = false;
				titleMonitor.style.left = 0;
				return true;
			};
			titleMonitor.onmouseover = move;
			titleMonitor.onmouseout = pause;
			titleMonitor.onclick = stop;
		}
		else{
			titleMonitor.onmouseover = null;
			titleMonitor.onmouseout = null;
			titleMonitor.onclick = null;
		}
	};
};

/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

Uniplayer.prototype.mimes = (function(){
	var a = 'audio/';
	var v = 'video/';
	return {
		//-- audio
		'flac':a+'flac',
		'mp3':a+'mpeg',
		'm4a':a+'aac',
		'm4b':a+'aac',
		'm4p':a+'aac',
		'm4r':a+'aac',
		'aac':a+'aac',
		'adts':a+'aac',
		'wav':a+'wav',
		'bwf':a+'wav',
		'aiff':a+'aiff',
		'aif':a+'aiff',
		'aifc':a+'aiff',
		'cdda':a+'aiff',
		'au':a+'basic',
		'snd':a+'basic',
		'ulw':a+'basic',
		'mid':a+'midi',
		'midi':a+'midi',
		'smf':a+'midi',
		'kar':a+'midi',
		'qcp':a+'vnd.qcelp',
		'gsm':a+'x-gsm',
		'amr':a+'amr',
		'caf':a+'x-caf',
		'ac3':a+'ac3',
		'm2a':a+'mpeg',
		'swa':a+'mpeg',
		'wma':a+'x-ms-wma',
		'wax':a+'x-ms-wax',
		'mpga':a+'mpeg',
		'mpega':a+'mpeg',
		'3gpp2':a+'3gpp2',
		'oga':a+'ogg',
		//-- video
		'3gp':v+'3gpp',
		'3gpp':v+'3gpp',
		'3g2':v+'3gpp2',
		'3gp2':v+'3gpp2',
		'h261':v+'h261',
		'h263':v+'h263',
		'h264':v+'h264',
		'jpgv':v+'jpeg',
		'jpm':v+'jpm',
		'jpgm':v+'jpm',
		'mj2':v+'mj2',
		'mjp2':v+'mj2',
		'mp4':v+'mp4',
		'mp4v':v+'mp4',
		'mpg4':v+'mp4',
		'm4u':v+'x-mpegurl',
		'mp2':v+'mpeg',
		'mpm':v+'mpeg',
		'mpa':v+'mpeg',
		'mpeg':v+'mpeg',
		'mpg':v+'mpeg',
		'mpe':v+'mpeg',
		'mpv':v+'mpeg',
		'mp2v':v+'mpeg-2',
		'mpv2':v+'mpeg-2',
		'm1s':v+'mpeg',
		'm1a':v+'mpeg',
		'm75':v+'mpeg',
		'm15':v+'mpeg',
		'm1v':v+'mpeg',
		'm2v':v+'mpeg',
		'qt':v+'quicktime',
		'mov':v+'quicktime',
		'mqv':v+'quicktime',
		'fvt':v+'vnd.fvt',
		'mxu':v+'vnd.mpegurl',
		'm4u':v+'vnd.mpegurl',
		'viv':v+'vnd.vivo',
		'vivo':v+'vnd.vivo',
		'fli':v+'fli',
		'flc':v+'flc',
		'cel':v+'flc',
		'asr':v+'x-ms-asf',
		'asf':v+'x-ms-asf',
		'asx':v+'x-ms-asx',
		'lsf':v+'x-la-asf',
		'lsx':v+'x-la-asf',
		'wm':v+'x-ms-wm',
		'wmp':v+'x-ms-wmp',
		'wmv':v+'x-ms-wmv',
		'wmx':v+'x-ms-wmx',
		'wvx':v+'x-ms-wvx',
		'avi':v+'x-msvideo',
		'avs':v+'avs-video',
		'mv':v+'x-sgi-movie',
		'movie':v+'x-sgi-movie',
		'ice':'x-conference/x-cooltalk',
		'f4v':v+'mp4',
		'f4p':v+'mp4',
		'flv':v+'flv',
		'swf':'application/x-shockwave-flash',
		'spl':'application/futuresplash',
		'dxr':'application/x-director',
		'dir':'application/x-director',
		'dcr':'application/x-director',
		'divx':v+'divx',
		'div':v+'divx',
		'dv':v+'x-dv',
		'dif':v+'x-dv',
		'dl':v+'dl',
		'gl':v+'gl',
		'ogv':v+'ogg',
		'ogg':'application/x-ogg',
		'ogx':'application/ogg',
		'axv':v+'annodex',
		'anx':'application/annodex',
		'afl':v+'animaflex',
		'fmf':v+'x-atomic3d-feature',
		'isu':v+'x-isvideo',
		'mjpg':v+'x-motion-jpeg',
		'qtc':v+'x-qtc',
		'rv':v+'vnd.rn-realvideo',
		'ra':'audio/x-pn-realaudio',
		'ram':'audio/x-pn-realaudio',
		'rm':'audio/x-pn-realaudio-plugin',
		'rpm':'audio/x-pn-realaudio-plugin',
		'rpj':'application/vnd.rn-realplayer-javascript',
		'scm':v+'x-scm',
		'vdo':v+'vdo',
		'vos':v+'vosaic',
		'xdr':v+'x-amt-demorun',
		'xsr':v+'x-amt-showrun',
		'sdv':v+'sd-video',
		'vob':v+'mpeg-system',
		'm4v':v+'x-m4v',
		'vlc':'application/x-vlc-plugin',
		'amc':'application/x-mpeg'
	};
})();

/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

UniplayerFlashJWPlayer = function(conf){
	/*
		KNOWN ISSUES
		
		- no javascript control for fullScreen due to flash security restrictions
	*/
	this.name = 'flashjw';
	this.title = 'Flash JW Player';
	this.needle = 'Flash';
	this.progid = 'ShockwaveFlash.ShockwaveFlash';
	this.classid = 'clsid:D27CDB6E-AE6D-11CF-96B8-444553540000';
	this.codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab';
	this.pluginspage = 'http://www.macromedia.com/go/getflashplayer';
	this.mime = 'application/x-shockwave-flash';
	this.supported = [
		//-- audio
		'audio/mpeg',
		//'audio/aac',
		//'audio/aacp',
		//-- video
		'video/flv',
		'application/x-shockwave-flash',
		'video/mp4'
	];
	this.maxVolume = 100;
	this.duration = 0;
	this.position = 0;
	// build		http://developer.longtailvideo.com/trac/wiki/FlashVars
	this.build = function(){
		if (conf && conf.flashvars && conf.flashvars.streamer == 'lighttpd' && this.player.current.mimetype != 'audio/mpeg') {
			this.streamerLighttpd = true;
		}
		// show native controls
		var height = this.player.options.height;
		if(this.player.options.showNativeControls){
			height+= 20;
		}
		// create object
		var swf = (conf && conf.swf) ? conf.swf : 'http://play.radiolla.com/uniplayer/components/jwplayer/player.swf';
		if(!this.player.options.id){
			this.player.options.id = 'uniplayer_' + this.name + '_' + Math.floor(Math.random()*100000000);	// jwplayer needs the ID to work correctly in IE
		}
		var obj = new this.player.UniplayerObject({
			id:	this.player.options.id,
			src: swf,
			width: this.player.options.width,
			height: height,
			type: 'application/x-shockwave-flash',
			classid: this.classid,
			codebase: this.codebase,
			pluginspage: this.pluginspage
		});
		obj.addParam('movie', swf, true);
		obj.addParam('quality', 'high');
		obj.addParam('wmode', 'opaque');
		obj.addParam('allowfullscreen', true);
		obj.addParam('allowscriptaccess', 'always');
		var flashvars = 'file='+escape(this.player.current.src).replace(/\%2523/g, '%25252523').replace(/\%253F/g, '%2525253F');
		flashvars+= '&id='+this.player.options.id;
		flashvars+= '&controlbar='+(this.player.options.showNativeControls?'bottom':'none');
		flashvars+= '&autostart='+(this.player.options.autoplay?'true':'false');
		flashvars+= '&volume='+this.player.options.volume*this.maxVolume;
		if(!this.player.options.showNativeControls){
			flashvars+= '&displayclick=fullscreen';
		}
		if(this.player.options.background){
			flashvars+= '&screencolor=' + this.player.options.background;
			obj.addParam('bgcolor', this.player.options.background);
		}
		if(conf && conf.flashvars){
			for(var i in conf.flashvars){
				if (i == 'streamer' && conf.flashvars[i] == 'lighttpd' && !this.streamerLighttpd) {
					continue;
				}
				flashvars+= '&' + i + '=' + conf.flashvars[i];
			}
		}
		obj.addParam('flashvars', flashvars);
		this.movie = obj.write(this.player.holders.movie);
		delete obj;
		// event time is only way to get jw flv player's position and duration
		var self = this;
		window.playerReady = function(obj){
			if(obj.id != self.player.options.id){return;}
			window[self.player.options.id + '_onPositionChange'] = function(obj){
				self.duration = obj.duration;
				self.position = self.duration ? obj.position/self.duration : 0;
			};
			self.player.current.movie.addModelListener('TIME', self.player.options.id + '_onPositionChange');
			delete window.playerReady;
		};
		this.player.current.width = this.player.options.width;
		this.player.current.height = height;
		return this.movie;
	};
	// controls		http://developer.longtailvideo.com/trac/wiki/FlashVars
	this.getVersion = function(){
		return this.player.current.movie.getConfig().version;
	};
	this.getState = function(){
		var state = this.player.current.movie.getConfig().state;
		var currentState = this.player.current.state;
		switch(state){
			case 'BUFFERING':
				currentState = this.player.states.loading;
				break;
			case 'PLAYING':
				currentState = this.player.states.playing;
				break;
			case 'PAUSED':
				currentState = this.player.states.paused;
				break;
			case 'IDLE':
			case 'COMPLETED':
				currentState = this.player.states.stopped;
				break;
			default:
				currentState = this.player.states.stopped;
				break;
		}
		return currentState;
	};
	this.reload = function(){
		if (this.streamerLighttpd && this.player.current.mimetype == 'audio/mpeg') {
			this.streamerLighttpd = false;
			this.player.current.movie = this.build();
		}
		if (!this.streamerLighttpd && this.player.current.mimetype != 'audio/mpeg') {
			this.streamerLighttpd = true;
			this.player.current.movie = this.build();
		}
		this.player.current.movie.sendEvent('LOAD', this.player.current.src.replace(/\%23/g, '%2523').replace(/\%3F/g, '%253F'));
	};
	this.play = function(){
		return this.player.current.movie.sendEvent('PLAY', true);
	};
	this.pause = function(){
		return this.player.current.movie.sendEvent('PLAY', false);
	};
	this.stop = function(){
		return this.player.current.movie.sendEvent('STOP');
	};
	this.fullScreen = function(){
		return this.player.pageScreen();
	};
	this.getMute = function(){
		return this.player.current.movie.getConfig().mute;
	};
	this.setMute = function(turn){
		return this.player.current.movie.sendEvent('MUTE', turn);
	};
	this.getVolume = function(){
		return this.player.current.movie.getConfig().volume/this.player.current.module.maxVolume;
	};
	this.setVolume = function(volume){
		return this.player.current.movie.sendEvent('VOLUME', volume*this.player.current.module.maxVolume);
	};
	this.getDuration = function(){
		return this.duration;
	};
	this.getPosition = function(){
		return this.position;
	};
	this.setPosition = function(position){
		return this.player.current.movie.sendEvent('SEEK', position*this.player.current.duration);
	};
};

/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

UniplayerWindowsMedia = function(){
	/*
		KNOWN ISSUES
		
		Windows:
			Firefox3
				-control (needs to install wmpfirefoxplugin.exe)
				-volume-param
			Safari3
				-downgrade to wmp6.4 without wmpfirefoxplugin
				-control (needs to install wmpfirefoxplugin.exe)
				-volume-param
				-volume-js (even if wmpfirefoxplugin installed)
			Opera9
				-volume
				-fullscreen
			IE5.01
				-control

		Flip4Mac:
			ALL
				-volume
				-fullscreen
				-mute
				-getPosition -	instead of Flip4Mac does not provide the Duration property,
				-setPosition	but property CurrentPosition is provided.
			Firefox3
				Flip4Mac controls trows an Exception but works
			Opera9
				-control

		Both:
			- background
			
	*/
	var mac = navigator.appVersion.indexOf('Macintosh') >= 0;
	this.name = mac ? 'flip4mac' : 'windowsmedia';
	this.title = mac ? 'Flip4Mac' : 'Windows Media Player';
	this.needle = ['(Windows Media|ActiveX Plug-in)'];// for google.chrome's activex plugin
	this.progid = 'wmplayer.ocx';
	this.classid = 'clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6';	// 'clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95'; for wmp6.4
	this.codebase = '';	// http://support.microsoft.com/kb/321684
	this.pluginspage = 'http://www.microsoft.com/windows/windowsmedia/player/default.aspx';
	this.mime = 'video/x-ms-wm';	// force using of WMP (VLC or x-mplayer2 may override WMP if other mimetype is used)
	this.supported = [
		'application/x-mplayer2',
		//-- audio
		'audio/mpeg',
		'audio/x-ms-wma',
		'audio/x-ms-wax',
		//-- video
		'video/x-msvideo',
		'video/x-ms-wm',
		'video/x-ms-wmv',
		'video/x-ms-wvx',
		'video/x-ms-asf',
		'video/x-ms-wmx',
		'video/x-ms-asf-plugin',
		'video/x-ms-wmp',
		'video/x-ms-asx'
	];
	this.maxVolume = 100;// -10000 for WMP 6.4;
	// build
	this.build = function(){
		// show native controls
		var height = this.player.options.height;
		if(this.player.options.showNativeControls){
			if(mac){
				height+= 16;
			}
			else{
				height+= 64;
			}
		}
		// create object
		var obj = new this.player.UniplayerObject({
			id:	this.player.options.id,
			src: this.player.current.src,
			width: this.player.options.width,
			height: height,
			type: this.mime,
			classid: this.classid,
			codebase: this.codebase,
			pluginspage: this.pluginspage
		});
		obj.addParam('URL', this.player.current.src, true);
		obj.addParam('AutoStart', this.player.options.autoplay ? 1 : 0);
		obj.addParam('volume', this.player.options.volume*this.maxVolume);
		obj.addParam('ShowControls', this.player.options.showNativeControls);
		obj.addParam('ShowStatusBar', this.player.options.showNativeControls);
		obj.addParam('uiMode', this.player.options.showNativeControls ? 'mini' : 'none');
		obj.addParam('version', 'VideoLAN.VLCPlugin.2');	// if plugin is overridden by VLC, this param is needed to access VLC controls
		this.movie = obj.write(this.player.holders.movie);
		delete obj;
		this.player.current.width = this.player.options.width;
		this.player.current.height = height;
		return this.movie;
	};
	// test
	this.test = function(){
		var result = false;
		try{
			result = (this.player.current.movie.controls || this.player.current.movie.FileName) ? true : false;
		}
		catch(e){}
		return result;
	};
	//controls		http://msdn.microsoft.com/en-us/library/bb248464(VS.85).aspx
	//	wmp6.4		http://msdn.microsoft.com/en-us/ms870192.aspx
	//flip4mac		http://forum.flip4mac.com/forum/messageview.aspx?catid=9&threadid=1271
	//				Flip4Mac WMV Supports the following methods and properties from the Windows Media 6.4 SDK
	//				Methods: "play","pause","Play","Pause","Stop","Next","Previous","Open"
	//				Properties: "CurrentPosition","FileName","PlayState" 
	this.getVersion = function(){
		return this.player.current.movie.versionInfo;		// flip4mac returns undefined
	};
	this.getState = function(){
		var state = 0;
		if(this.player.current.movie.controls){
			state = this.player.current.movie.playState;
		}
		else{
			state = this.player.current.movie.PlayState;
		}
		state = parseInt(state);
		var currentState = this.player.current.state;
		if(this.player.current.movie.controls){
			switch(state){
				case 4:
				case 5:
				case 6:
				case 7:
				case 9:
				case 11:
					currentState = this.player.states.loading;
					break;
				case 3:
					currentState = this.player.states.playing;
					break;
				case 2:
					currentState = this.player.states.paused;
					break;
				case 0:
				case 1:
				case 8:
				case 10:
					currentState = this.player.states.stopped;
					break;
			}
		}
		else{
			switch(state){
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					currentState = this.player.states.loading;
					break;
				case 2:
					currentState = this.player.states.playing;
					break;
				case 1:
					currentState = this.player.states.paused;
					break;
				case 0:
				case 8:
					currentState = this.player.states.stopped;
					break;
			}
		}
		return currentState;
	};
	this.reload = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.URL = this.player.current.src;
		}
		else{
			return this.player.current.movie.FileName = this.player.current.src;
		}
	};
	this.play = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.controls.play();
		}
		else{
			return this.player.current.movie.Play();
		}
	};
	this.pause = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.controls.pause();
		}
		else{
			return this.player.current.movie.Pause();
		}
	};
	this.stop = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.controls.stop();
		}
		else{
			return this.player.current.movie.Stop();
		}
	};
	this.fullScreen = function(){
		if(mac){
			return this.player.pageScreen();
		}
		else if(this.player.current.movie.controls){
			return this.player.current.movie.fullScreen = true;
		}
		else{
			return this.player.current.movie.displaySize = 3;
		}
	};
	this.getMute = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.settings.mute;
		}
		else{
			return this.player.current.movie.Mute;
		}
	};
	this.setMute = function(turn){
		if(this.player.current.movie.controls){
			return this.player.current.movie.settings.mute = turn;
		}
		else{
			return this.player.current.movie.Mute = turn;
		}
	};
	this.getVolume = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.settings.volume/this.player.current.module.maxVolume;
		}
		else{
			return isNaN(this.player.current.movie.Volume) ? this.player.current.volume : (this.player.current.movie.Volume+10000)/10000;
		}
	};
	this.setVolume = function(volume){
		if(this.player.current.movie.controls){
			return this.player.current.movie.settings.volume = volume*this.player.current.module.maxVolume;
		}
		else{
			return this.player.current.movie.Volume = volume*10000-10000;
		}
	};
	this.getDuration = function(){
		if(this.player.current.movie.controls){
			return this.player.current.movie.currentMedia.duration;
		}
		else{
			return isNaN(this.player.current.movie.Duration) ? 0 : this.player.current.movie.Duration;
		}
	};
	this.getPosition = function(){
		if(this.player.current.movie.controls){
			return this.player.current.duration ? this.player.current.movie.controls.currentPosition/this.player.current.duration : 0;
		}
		else{
			return (!this.player.current.duration || isNaN(this.player.current.movie.CurrentPosition) || this.player.current.movie.CurrentPosition < 0) ? 0 : this.player.current.movie.CurrentPosition/this.player.current.duration;
		}
	};
	this.setPosition = function(position){
		if(this.player.current.movie.controls){
			return this.player.current.movie.controls.currentPosition = position*this.player.current.duration;
		}
		else{
			return this.player.current.movie.currentPosition = position*this.player.current.duration;
		}
	};
};

/*
    Uniplayer - Universal Web Media Player
    Copyright (C) 2008 Artem Bandur <artico.bandurini@gmail.com>

    This program 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.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

UniplayerVLC = function(){
	/*
		KNOWN ISSUES
		
		- background
	*/
	this.name = 'vlc';
	this.title = 'VLC';
	this.needle = ['VLC', '(Plug-in|Plugin)'];
	this.progid = 'VideoLAN.VLCPlugin';
	this.classid = 'clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921';
	this.codebase = 'http://play.radiolla.com/uniplayer/install/VLC.cab';
				  // http://downloads.videolan.org/pub/videolan/vlc/0.8.6c/win32/axvlc.cab
				  // http://downloads.videolan.org/pub/videolan/vlc/0.9.2/win32/axvlc.cab
	this.pluginspage = 'http://www.videolan.org/';
	this.mime = 'application/x-vlc-plugin';
	this.supported = [
		//-- audio
		'audio/flac',
		'audio/mpeg',
		'audio/x-mpeg',
		'audio/mpeg4',
		'audio/wav',
		'audio/x-wav',
		'audio/3gpp',
		'audio/3gpp2',
		//-- video
		'application/x-vlc-plugin',
		'video/mpeg',
		'video/mpeg4',
		'video/x-mpeg',
		'video/x-msvideo',
		'video/x-ms-wmv',
		'application/ogg',
		'application/x-ogg',
		'application/mpeg4-muxcodetable',
		'video/mp4',
		'video/3gpp2',
		'video/x-ms-asf-plugin',
		'video/x-ms-asf',
		'application/mpeg4-iod',
		'video/mpeg-system',
		'video/x-mpeg-system',
		'video/divx',
		'video/x-google-vlc-plugin'
	];
	this.maxVolume = 100;	// can be even 200
	// build		http://www.videolan.org/doc/play-howto/en/ch04.html
	this.build = function(){
		// create object
		var obj = new this.player.UniplayerObject({
			id:	this.player.options.id,
			src: this.player.current.src,
			width: this.player.options.width,
			height: this.player.options.height,
			type: this.mime,
			classid: this.classid,
			codebase: this.codebase,
			pluginspage: this.pluginspage
		});
		obj.addParam('src', this.player.current.src, true);
		obj.addParam('version', 'VideoLAN.VLCPlugin.2');
		obj.addParam('autoplay', this.player.options.autoplay);
		obj.addParam('volume', this.player.options.volume*this.maxVolume);
		obj.addParam('showdisplay', true);
		this.movie = obj.write(this.player.holders.movie);
		delete obj;
		this.movie.style.width = this.player.options.width + 'px';
		this.movie.style.height = this.player.options.height + 'px';
		this.player.current.width = this.player.options.width;
		this.player.current.height = this.player.options.height;
		return this.movie;
	};
	// test
	this.test = function(){
		var result = false;
		try{
			result = (this.getVersion() && this.player.current.movie.input) ? true : false;
		}
		catch(e){}
		return result;
	};
	//controls		http://www.videolan.org/doc/play-howto/en/ch04.html
	this.getVersion = function(){
		return this.player.current.movie.VersionInfo;
	};
	this.getState = function(){
		var state = parseInt(this.player.current.movie.input.state);
		var currentState = this.player.current.state;
		switch(state){
			case 1:
			case 2:
				currentState = this.player.states.loading;
				break;
			case 3:
				currentState = this.player.states.playing;
				break;
			case 4:
				currentState = this.player.states.paused;
				break;
			case 6:
				currentState = this.player.states.failed;
				break;
			case 0:
			case 5:
				currentState = this.player.states.stopped;
				break;
		}
		return currentState;
	};
	this.reload = function(){
		this.stop();
		this.player.current.movie.playlist.clear();
		return this.player.current.movie.playlist.add(this.player.current.src);
	};
	this.play = function(){
		return this.player.current.movie.playlist.play();
	};
	this.pause = function(){
		return this.player.current.movie.playlist.togglePause();
	};
	this.stop = function(){
		return this.player.current.movie.playlist.stop();
	};
	this.fullScreen = function(){
		return this.player.current.movie.video.toggleFullscreen();
	};
	this.getMute = function(){
		return this.player.current.movie.audio.mute;
	};
	this.setMute = function(turn){
		return this.player.current.movie.audio.mute = turn;
	};
	this.getVolume = function(){
		return this.player.current.movie.audio.volume/this.player.current.module.maxVolume;
	};
	this.setVolume = function(volume){
		return this.player.current.movie.audio.volume = volume*this.player.current.module.maxVolume;
	};
	this.getDuration = function(){
		var duration = this.player.current.movie.input.length/1000;
		return isNaN(duration) ? 0 : duration;
	};
	this.getPosition = function(){
		return this.player.current.movie.input.position;
	};
	this.setPosition = function(position){
		return this.player.current.movie.input.position = position;
	};
};
