/* version: Update August 12 (octobar fix), 2009. */

var octopv_globalPlayObj = null;
var octopv_octobarPath = "http://www.octoshape.com/javascripts/octobar.swf";

/* octopv_embeddedPlayObject is a global object set only once: when embeddedplay is called for the first time. 
    It knows how to play embedded in the current user setup. 
    It can be used by all embeded players on the page. */
var octopv_embeddedPlayObject = null;

/* Octopv_embeddedPlayers holds any actual embedded players started by the octoPlayEmbedded function.
	There is one object for each playerDiv. 
	playerDiv (string) -> object with methods: 
		- playerStop()
		- playerPlay() 
		- playerPause() 
		- playerVolume(number) from 0 to 100
		- playerSeek(number) from 0 to 1000
	Player objects are added in the embeddedPlay function.
*/
var octopv_embeddedPlayers = new Object;


/*doc <!--
<function id="octoNeedsNewFxWmpPlugin" group="dutility functions">
	<description>
		This is a small utility function to determine if the user could 
		benefit from getting the new Firefox Windows Media Player (WMP) plug-in. 
		It is recommended to ask the user to get this plug-in if you are 
		using the Octoshape embbedded play API to play an on demand stream.
		<BR /><BR />
		Windows XP and earlier has a pre-installed older Firefox WMP plug-in, but there are a few 
		issues with this plug-in so it might improve the user experience to ask the user to get the new plug-in
		if they are using the old one. Known issues with the old plug-in:
		<ul>
			<li>If an Octoshape on demand stream is played, the user can not seek in the file.
				(This is because the old WMP plug-in is not scriptable).</li>
			<li>Some users have experienced video resizing errors.
				(Notably with the combination of Firefox 2 and WMP 11).</li> 
		</ul>
		The plug-in requires Windows XP or Windows Vista. 
	</description>
	<returns>
		Returns true if all of the following conditions are met: 
		The browser is Firefox, the OS is either Windows XP or Vista, and 
		the user does not have the new Firefox WMP plug-in.
	</returns>
	<comment>
		Read about the WMP plug-in at: 
		<a href="http://kb.mozillazine.org/Windows_Media_Player">MozillaZine Knowledge Base on WMP plug-ins</a>.
		The plug-in can be downloaded from Microsoft at: 
		<pre>http://port25.technet.com/pages/windows-media-player-firefox-plugin-download.aspx</pre>
	</comment>
</function> 
 --> **/
function octoNeedsNewFxWmpPlugin(){
	if(!octopv_isFirefox()) return false;
	if(!(octopv_isVista()||octopv_isXP())) return false;
	return !octopv_has_mime("application/x-ms-wmp");
}


/* **************************** PLAY FUNCTIONS *******************************/

/*doc <!--
<function id="octoGetEmbeddedPlayer" group="aget embedded play object"> 
	<description>
		This creates a JavaScript object that can be used to insert a Windows Media Player playing an 
		Octoshape stream on a web page. 
		The player will not be inserted until start is called on the reply object.
		<BR /><BR />
		Do not call this function from the head section of an html document.
	</description>			
	<param id="playerDiv" 		description="The id of the html section you placed on the page for the media player" />
	<param id="player_width" 	description="The width in pixels you want the embedded media player to have" />
	<param id="player_height">
		The height in pixels you want the viewing area of the embedded media player to have. 
		The actual player (including the controls below) is an additional 46 pixels high.
	</param>
	<param id="controls" optional="true" >
		<ol class="nospace">
			<li value="0"> The default value. Shows common live stream controls beneath the video image (play/pause, stop, volume etc.).</li>
			<li value="1"> Shows on demand controls (24 pixels high) beneath the video the video image.	
				NB: If 0 is set for an on demand stream, the seek bar below the player will not function correctly.
				</li>
			<li value="2"> Shows no controls at all.</li>
		</ol>
	</param>
	<returns>
		Returns a JavaScript object. See API for a list of methods.
	</returns>
</function> 
 --> **/
 /*doc <!--
<function id="obj.setMessages" group="bprimary object methods"> 
	<description>
		This function changes the messages shown to the user.
		<BR /><BR />
	</description>
	<param id="messageStartingUp" >
		Message user sees while the Octoshape plug-in is starting up (and being installed). 
		Should be a single line of text.
	</param>
	<param id="messageMissing" optional="true" >
		Message user sees if the Octoshape plug-in is not installed and s/he needs to perform a manual install.
	</param>
	<param id="messageError" optional="true"  >
		Message user sees is there was some error with an existing Octoshape plug-in installation and the user needs to re-install.
	</param>
</function> 
 --> **/

 /*doc <!--
<function id="obj.start" group="bprimary object methods"> 
	<description>
		If the Octoshape plug-in is not running when this function is called, 
		the plug-in will launch (this might take a few seconds), and then play the stream.
		<BR /><BR />
		If we are on the Mac and there is no Flip4Mac media browser plug-in we call octoPlayExternal.
		<BR /><BR />
		When playing an on demand stream it is recommended to ensure that the user is not using the old 
		Firefox Windows Media Player plug-in. See comments to function %apiref "octoNeedsNewFxWmpPlugin"% 
		for details. 
		<BR /><BR />
	</description>			
	<param id="octolink" description="The unique OctoLink you got from Octoshape" />
	<param id="autoinstall" optional="true" >
		If true this call will attempt to install the Octoshape Plug-in if it is not already installed. 
		To use this feature you need to include the auto install JavaScript files.
	</param>
</function> 
 --> **/
/*doc <!--
<function id="obj.playerStop" group="cplay object methods">
	<description>Stooping the stream. A subsequent call to playerPlay will start 
	the stream from the beginning.</description>
</function> 
 --> **/
/*doc <!--
<function id="obj.playerPlay" group="cplay object methods">
	<description>
		This can be called after a call to playerStop or playerPause.
	</description>
</function> 
 --> **/
/*doc <!--
<function id="obj.playerPause" group="cplay object methods">
	<description>
		This will pause the stream. It can be resumed by a call to playerPlay.
	</description>
</function> 
 --> **/

/*doc <!--
<function id="obj.playerVolume" group="cplay object methods">
	<description>
		Function to control the media player volume. 
	</description>
	<param id="newVolume" description="A number from 0 to 100, where 0 is no sound at all and 100 is full volume."/>
</function> 
 --> **/
function octoGetEmbeddedPlayer(playerDIV_ID, arg_player_width, arg_player_height, arg_controls){
	octopv_debug('we were asked to set up an embedded player into div: '+playerDIV_ID, arguments.callee);

	if(octopv_isIE()&&(typeof (octopv_embeddedPlayers[playerDIV_ID]) != 'undefined')){
		octopv_embeddedPlayers[playerDIV_ID].playerStop();
	}
	
	octopv_setEmbeddedPlayObject();
	var controls = (typeof(arg_controls) != "number")? 0: arg_controls; 
	var embedobj = octopv_embeddedPlayers[playerDIV_ID];

	if(typeof embedobj != 'undefined'){
		// We already have an embedobj for this div.
		octopv_embedobj_set(embedobj, arg_player_width,arg_player_height, controls);
	}else{
		embedobj = new octopv_embedobj(playerDIV_ID,arg_player_width, arg_player_height, controls);
		octopv_embeddedPlayers[playerDIV_ID] = embedobj;
		octopv_debug('Adding "'+playerDIV_ID+'" player div arr: '+getPropertiesString(octopv_embeddedPlayers), arguments.callee);
	}
	
	

	embedobj.pvPluginAlertErrorSpecial = function(result, description){
		alert("An un-expected error occured while trying to start up the Octoshape plug-in. \n"+
		"Please try to shut down the plug-in and then press play again. \n" + 
		"To shut down: right click the system tray icon and choose exit. \n" + 
		"\n\n\nFunction getStatus response was: " + result + 
		"\nStartup link Exception:" + description);
	};
	
	embedobj.pling="";
	embedobj.plingRunning=false;
	embedobj.showStartupMessage = function(){
		if(embedobj.plingRunning){
			embedobj.pling = embedobj.pling+".";
			if(	embedobj.pling.length > 15){
				embedobj.pling=".....";
			}
			embedobj.displayMessageHTML(embedobj.pv_messageStartup+"<BR />"+embedobj.pling,2);
			window.setTimeout("window.octopv_embeddedPlayers['"+playerDIV_ID+"'].showStartupMessage();", 1000);
		}
	}
	
	embedobj.start = function(octolink, tryAutoInstall){
		embedobj.plingRunning=false;
		if(octopv_isIE()){
			embedobj.playerStop();
		}
		octoGetPlayLink(octolink, function(statusInt, playlink){
			octopv_debug('Reply from getLink('+statusInt+'): '+playlink, "embedobj.start");
			embedobj.plingRunning=false;
			switch(statusInt){
				case 0: embedobj.play(playlink); break;
				case -1: embedobj.displayMessageHTML(embedobj.pv_messageMissing, 1); break;
				default:
					// TODO more detailed messages for the autoinstall cases ... 
					embedobj.displayMessageHTML(embedobj.pv_messageError+"(err:"+statusInt+")",3);
				}
		}, tryAutoInstall, function(messageString){
			octopv_debug('Startup message: '+messageString, "embedobj.start");
			if(!embedobj.plingRunning){
				embedobj.plingRunning=true;
				embedobj.pling="";
				embedobj.showStartupMessage();
			};
		});
	};
	
	var variantStr = (typeof octoshapeVariant == 'string')?"?variant="+octoshapeVariant:""; 
	var get_plug_in= '<a STYLE="color:white;" href="http://'+octopv_baseWebPath+'/plugin/get.asp'+variantStr+'">get plug-in</a>';

	embedobj.pv_messageError = "An error occurred while trying to play an Octoshape stream.<BR />"+
								"Please re-install the plug-in: "+get_plug_in + "<BR />";
	embedobj.pv_messageMissing = 'Please get the Octoshape Plug-In to play: '+get_plug_in;
	embedobj.pv_messageStartup = 'Starting up ..';
	
	function getVar(newVar, oldVar){
		return newVar==null||(typeof (newVar))== 'undefined'? oldVar:newVar;
	}
	embedobj.setMessages = function(startupMessage, missingMessage, errorMessage){
		embedobj.pv_messageStartup = getVar(startupMessage,embedobj.pv_messageStartup);
		embedobj.pv_messageMissing = getVar(missingMessage,embedobj.pv_messageMissing);
		embedobj.pv_messageError = getVar(errorMessage,embedobj.pv_messageError);
	};
	return embedobj;
}


function octopv_setEmbeddedPlayObject(){
	if(octopv_embeddedPlayObject == null){
		var ob = new octopv_embedplayobj_basics();
		if(octopv_isOSX()){
			octopv_embedobj_setMac(ob);
		}else if(octopv_isFirefox() && octopv_has_mime("application/x-ms-wmp")){
	 		octopv_embedobj_setFxWithPlugin(ob);
		 	octopv_setWmpScripting(ob);
		}else if(octopv_hasWmp7()){ 
			octopv_embedobj_setIeWmp7(ob);
			octopv_setWmpScripting(ob);
		}else{
			if(octopv_isIE()){
				octopv_embedobj_setIeWmp64(ob);
			}else{
				octopv_embedobj_setEmbedTag(ob);
			}
		}
		octopv_embeddedPlayObject = ob;
	}
}

/* **************************************************************************************/
/* ********************************* PRIVATE FUNCTIONS *******************************/

/* 
 @function: octopvGetPlayerID
 @param playerDiv: string id of the media player div
 @returns string id to use in object and embed tags to uniquely identify the media player
 */
function octopvGetPlayerID(playerDiv){
	return "octoPlayerObjectID" + playerDiv;
}

/* 
 @function: octopvGetOctobarID
 @param playerDiv: string id of the media player div
 @returns string id to use in object and embed tags to uniquely identify the octobar
 */
function octopvGetOctobarID(playerDiv){
	return "octobarObjectID" + playerDiv;
}


/* *************************************************************************************/
/* ****************************** EMBEDDED PLAY FUNCTIONS *******************************/

function octopv_embedobj_set(embedObject, widthArg,heightArg, controlsArg, cheatArg){
	embedObject.width 		= widthArg;
	embedObject.height 		= octopv_convertToNumber(heightArg,0);
	embedObject.controls 	= (typeof(controlsArg) != "number")? 0: controlsArg; 
	embedObject.cheat 		= (typeof (cheatArg) != "number")?0:cheatArg;
	octopv_debug(embedObject.embedID+' Setting new values. controls: '+embedObject.controls, arguments.callee);
}


/** 
 */
function octopv_embedplayobj_basics(){

	this.convertOctolink=function(octolink){
		return octolink;
	};

	/* This function should call begin on the octobar object with the 
		lenght of the playing media clip (in seconds). 
		The will initialize the octobar to move.
	*/
	this.octobarReady = function(callbackObject, playerDiv, playerObject){
		octopv_debug('No octobar duration callback implemented. Calling octobarBegin with -1', arguments.callee);
		return false;
	};
	
	this.octobarHTML = function(id, src,width,height){
		octopv_debug('No octobarHTML function implemented. ', arguments.callee);
		return '';
	};

	this.playerHTML = function(id, src, width, height, showControls){
		octopv_debug('No playerHTML function implemented. ', arguments.callee);
		return '';
	};


	this.stop = function(player){
		octopv_debug('stopping player', arguments.callee);
		return false;
	};
	
	this.start = function(player){
		octopv_debug('starting player', arguments.callee);
		return false;
	};
	
	this.setNewUrl = function(player, url){
		octopv_debug('setting new url', arguments.callee);
		return false;
	};
	
	this.volume = function(player, numberBetween1And100){
		octopv_debug('setting volume', arguments.callee);
		return false;
	};
	
	this.playerPause = function(player){
		octopv_debug('setting pause', arguments.callee);
		return false;
	};
}
 

/* 
 @constructor: octopv_embedobj
 @param playerDivArg: string id of the media player div
 @param widthArg: width of the media content
 @param heightArg: height of the media content
 @param controls: (number) 0:normal controls 1:ondemand controls 2:no controls.
 @param cheat [optional]: (number) 
 		0 or undefined: normal play. 
 		1: start up octoshape and play the 'octolink' directly in wmp. 
 		2: do not start up octoshape but just play the 'octolink' directly.
 @public functions added: 
	- play(src)
 	- startup()			shows startup image in player.
 	- playerSeek(number)
 	- playerPlay()
 	- playerStop()
 	- playerPause()
 	- playerVolume(numberBetween1And100)
 	- octobarReady()				dummy (may be overwriten later)
 	- string convertOctolink(link)	dummy (may be overwriten later)
*/
function octopv_embedobj(playerDivArg,widthArg,heightArg, controlsArg, cheatArg){
	this.playerDiv 	= playerDivArg;
	this.embedID 	= Math.random();
	octopv_embedobj_set(this, widthArg,heightArg, controlsArg, cheatArg);

	var scriptingReady 	= false; // ensures that scripting functions are not called before play has been called
	var hasInitDiv 		= false; 
	var rewindSeek 		= false;
	var hasSeekSrc 		= false;
	
	// this must be called from body section.
	this.initPlayerDiv = function(){
		if(!hasInitDiv){
			octopv_debug(this.embedID+' inits player div ', arguments.callee);
			hasInitDiv = true;
			var wmpId = 'octopv_player_'+this.playerDiv;
			var barId = 'octopv_bar_'+this.playerDiv;
			document.getElementById(this.playerDiv).innerHTML='<div id="'+wmpId+'">begin</div><div id="'+barId+'"></div>'; 
			this.wmpDiv = document.getElementById(wmpId); 
			this.barDiv = document.getElementById(barId); 
			octopv_debug(this.embedID+' end init playerdiv: '+this.wmpDiv, arguments.callee);
		}
	};	
	
	this.displayMessageHTML = function(text, numLines){
		var fontSize = 18;	
		if(widthArg<650){
			fontSize = 16;
		}else if(widthArg<450){
			fontSize = 14;
		}else if(widthArg<350){
			fontSize = 12;
		}else if(widthArg<200){
			fontSize = 9;
		}
		
		var lineHeight = fontSize*1.2;
		var textH = lineHeight*numLines;
		var message = ''+
			'<div STYLE="background-color:black; width:100%; height:100%;">'+
				'<div STYLE="color:white; background-color:black; width:'+widthArg+'px; height:'+heightArg+'px;">'+
					'<div STYLE="float:left; height:50%; margin-bottom:-'+(textH/2)+'px; width:'+widthArg+'px; "></div>'+
					'<div STYLE="text-align:center; clear:both; height:'+textH+'px; position:relative; '+
						'line-height:'+lineHeight+'px; font-size:'+fontSize+'px; ">'+
							text+
					'<div>'+
				'<div>'+
			'</div>';
		document.getElementById(this.playerDiv).innerHTML = message;
		hasInitDiv=false;
	}
	
	this.play = function(src){
		octopv_debug(this.embedID+' playing: '+src, arguments.callee);
		this.initPlayerDiv();
		this.basicSrc = src;
		var id = octopvGetPlayerID(this.playerDiv);
		this.wmpDiv.innerHTML = octopv_embeddedPlayObject.playerHTML(id, this.basicSrc, this.width, this.height, this.controls==0);
		var idBar = octopvGetOctobarID(this.playerDiv);
		if(this.controls==1){
			var srcBar = octopv_octobarPath + "?embedID="+this.playerDiv;
			this.barDiv.innerHTML = octopv_embeddedPlayObject.octobarHTML(idBar, srcBar, this.width, 24);
		}
		
		this.playerObject = document[id]; 
		if(this.controls==1){
			this.octobarObject = document[idBar]; 
		}
		scriptingReady = true;
		octopv_debug(this.embedID+' playerObject: '+this.playerObject, arguments.callee);
	};

	this.close=function(){
		this.initPlayerDiv();
		this.wmpDiv.innerHTML = "";
	}
	
	
	this.playerStop = function(){
		if(scriptingReady){
			if (hasSeekSrc){
				octopv_debug(this.embedID+' setting rewind seek', arguments.callee);
				rewindSeek = true;
			}
			if(!octopv_embeddedPlayObject.stop(this.playerObject)){
				this.wmpDiv.innerHTML='<div STYLE="height:'+this.height+'px;"></div>';
			};
		}
	};
	
	this.playerPlay = function(){
		if(scriptingReady){
			if(rewindSeek){
				octopv_embeddedPlayObject.setNewUrl(this.playerObject,this.basicSrc);
				rewindSeek = false;
				hasSeekSrc = false;
			}else{
				if(!octopv_embeddedPlayObject.start(this.playerObject)){
					this.play(this.basicSrc);
				};
			}
		}
	};
	
	this.playerSeek = function(number){
		if(scriptingReady){
			octopv_debug(this.embedID+' Seeking to '+number, arguments.callee);
			//octopv_debug('Stopping media player object. ', arguments.callee);
			//this.playerClose(this.playerObject);
			var newUrl = '';
			if(this.basicSrc.indexOf('?') >= 0){
				newUrl = this.basicSrc + '&beginat='+number+'pm';
			}else{
				newUrl = this.basicSrc + '?beginat='+number+'pm';
			}
			hasSeekSrc = (number > 0);
			octopv_debug(this.embedID+' Setting url to '+newUrl, arguments.callee);
			if(!octopv_embeddedPlayObject.setNewUrl(this.playerObject,newUrl)){
				var id = octopvGetPlayerID(this.playerDiv);
				this.wmpDiv.innerHTML=octopv_embeddedPlayObject.playerHTML(id, newUrl, this.width, this.height, this.controls==0);
				this.playerObject = document[id];
				octopv_debug(this.embedID+' inserted new player', arguments.callee);
			}
		}else{
			octopv_debug('not seeking since script is not ready ...', "playerSeek");
		}
	};
	
	this.playerVolume = function(numberBetween1And100){
		if(scriptingReady){
			octopv_embeddedPlayObject.volume(this.playerObject,numberBetween1And100);
		}
	};
	
	this.playerPause = function(player){
		if(scriptingReady){
			octopv_embeddedPlayObject.pause(this.playerObject);
		}
	};

	// this is called from flash octobar.
	this.octobarReady = function(){
		if(!octopv_embeddedPlayObject.octobarReady(this,this.playerDiv, this.playerObject)){
			this.octobarObject.octobarBegin("-1");
		}
	};
	
	
	/***************** event handler callbacks ******************/
	
	var hasSetDuration = false;
	this.eventCallback_duration = function(duration){
		octopv_debug("wmp event playing. we call octobar.begin("+duration+")", arguments.callee);
		try{
			var durationStr = ''+duration+'';
			this.octobarObject.octobarBegin(durationStr);
			hasSetDuration = true;
		}catch(exception){
			octopv_debug("octobar set begin exeption: "+exception,  arguments.callee);
		}
	};
	
	
	this.eventCallback_mustGetDuration = function(){
		return !hasSetDuration;
	};
	
	this.eventCallback_playing = function(){
		octopv_debug("wmp event playing. we call octobar.showPlaying() ", arguments.callee);
		this.octobarObject.octobarShowPlaying();
	};
	
	this.eventCallback_buffering = function(){
		octopv_debug("wmp event buffering. we call octobar.showBuffering().", arguments.callee);
		this.octobarObject.octobarShowBuffering();
	};
	
	this.eventCallback_ended = function(){
		try{
			octopv_debug("wmp event ended. We call octobar.stop()",  arguments.callee);
			this.octobarObject.octobarStop();
			rewindSeek = true;
		}catch(exception){
				octopv_debug("octobar stop exeption: "+exception,  arguments.callee);
		}
	};
	
	
}


/* 
 @function: octopv_embedobj_setMac 
 @param embedobj: a octopv_embedobj_basics object
 @Adds methods to param obj: 
 	- octobarHTML(id, src,width,height)
 	- playerHTML(id, src, width, height, showControls)
	- stop(player): This has odd behavier on live streams.
			Flip4mac (and quicktime) actually performs progressive download, that is, 
			the played part of the stream are saved so the user can seek in it. 
			So stop will return to the first viewed part of the stream. 
	- pause(player)
	- start(player)
	- volume(player,number): dummy function doing nothing since flip4mac does not have scriptable volume control.
	- setNewUrl(player,newUrl)	
*/
function octopv_embedobj_setMac(embedobj){
	octopv_debug('Creating embedobj: '+embedobj.embedID, arguments.callee);

	embedobj.convertOctolink=function(octolink){
		// we append the name of the player plugin to the octolink we give to the octoshape browser plugin.
		// this ensures that we get a working link back.
		octopv_debug('Mac converting octolink: '+octolink, arguments.callee);
		if(navigator && navigator.mimeTypes && navigator.mimeTypes.length){
			var mimeID = "video/x-ms-asf";
			var mime =  navigator.mimeTypes[mimeID];
			if(mime && mime.enabledPlugin){
				var playerName = mime.enabledPlugin.name;
				octopv_debug('setting playerplugin='+playerName, arguments.callee);
				return octolink+";playerplugin="+playerName;
			}
		}
		octopv_debug('Mac has converted octolink to: '+octolink, arguments.callee);
		return octolink;
	};

	embedobj.playerHTML = function(id, src, width, height, showControls){
		var html  = '';
		var embedControls=0;

		if(showControls || octopv_isFirefox()){
			// flip4mac in firefox will make space for the controls even if they are not shown!
			embedControls = 16; 
		}
		
		html += '<embed ';
       	html += ' 	src="'+src+'" ';
		html += '	name="'+id+'" ';
		html += '	SCALE="ASPECT" ';
		html += '	ENABLEJAVASCRIPT="TRUE" ';
		html += '	BGCOLOR="GRAY" ';
		html += '	AutoStart="TRUE" ';
       	html += '	width="' + width + '" ';
       	html += '	height="'+(height + embedControls)+'" ';
		html += ' 	TYPE="application/x-mplayer2" ';
		html += ' 	pluginspage="http://www.flip4mac.com/wmv_download." ';
		if(showControls){
			html += '	ShowControls="true" ';
			html += '	showStatusBar="true" ';
		}else{
			html += '	ShowControls="false" ';
			html += '	showStatusBar="false" ';
		}
       	html += ' />';
		return html;
	};




	embedobj.octobarHTML = function(id, src,width,height){
		var html  = '';
		var octobarTopMargin=0;

		if(octopv_isFirefox()){
			// flip4mac in firefox will make space for the controls even if they are not shown!
			octobarTopMargin = -38; 
		}else{
			octobarTopMargin = -5; 
		}
		html += '	<embed src="'+src+'" ';
		html += '		STYLE="margin-top:'+octobarTopMargin+'px;"'; 
		html += '		loop="false"';
		html += '		menu="false"';
		html += '		quality="high"';
		html += '		salign="lt"';
		html += '		bgcolor="#ffffff"';
		html += '		width="'+width+'"';
		html += '		name="'+id+'"';
		html += '		height="'+height+'"';
		html += '		align="middle"';
		html += '		allowScriptAccess="always"';
		html += '		allowFullScreen="true"';
		html += '		type="application/x-shockwave-flash"';
		html += '		pluginspage="http://www.macromedia.com/go/getflashplayer" />';
		return html;
	};
	
	
	embedobj.stop = function(player){
		try{
			player.Stop();
			return true;
		}catch(exception){
			octopv_debug('Could not stop: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.start = function(player){
		try{
			octopv_debug('should play mac script.', arguments.callee);
			player.Play();
			return true;
		}catch(exception){
			octopv_debug('Could not play: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.pause = function(player){
		try{
			octopv_debug('pausing from mac script ', arguments.callee);
			player.Pause();
			return true;
		}catch(exception){
			octopv_debug('Could not pause: '+exception, arguments.callee);
			return false;
		}
	}
	
	
	// We have no octobarReady function since we can not retrieve the media duration from flip4mac.
	/** There is no documentation for flip4mac script support.
	According to: http://forum.flip4mac.com/forum/messageview.aspx?catid=9&threadid=1271
		Flip4Mac supports Play, Pause, Stop, Next, Previous, Open as well as CurrentPosition, FileName, PlayState. 
	from http://msdn.microsoft.com/en-us/ms870192.aspx 
		But open and filename does not work!.
	
	*/
		
	
}



/* 
 @function: octopv_embedobj_setFxWithPlugin
	For Firefox browser with the wmp plugin installed
 @param embedobj
 @Adds public methods to embedobj:
 	- void playerHTML(id, src, width, height, showControls) 
 	- void octobarHTML(id, src,width,height) 
*/
function octopv_embedobj_setFxWithPlugin(embedobj){
	octopv_debug('Creating embedobj ', arguments.callee);
	
	embedobj.playerHTML = function(id, src, width, height, showControls){
		var paramUiMode = '';
		var controls = 0;
		if(showControls){
			paramUiMode += '	<PARAM name="uimode" value="mini" >';
			controls += 45; 
		}else{
			paramUiMode += '	<PARAM name="uimode" value="none" >';
		}
		octopv_debug('inserting. h:'+height+" cntrls: "+controls+" ", arguments.callee);
		var html  = '';
		html += '	<OBJECT ID="'+id+'" ';
		html += '	height="'+(height + controls)+'" width="'+width+'" ';
        html += ' 	type="application/x-ms-wmp"'; 
		html += '   STANDBY="Loading Octoshape plugin and client" >';
		html += '		<param name="Loop" value="0">';
		html += '       <param name="Repeat" value="false">';
		html += '	    <param name="rate" value="True">';
		html += '	    <param name="defaultFrame" value="">';
		html += '	    <param name="playCount" value="False">';
		html += '	    <param name="mute" value="False">';
		html += '	    <param name="enableErrorDialogs" value="False">';	
		html += '       <param name="autostart" value="true">';
		html += '       <param name="PlayCount" value="1">';
		html += '       <param name="AutoRewind" value="false">';
		html += '	    <param name="URL" value="'+src+'">';
		html += '	    <param name="src" value="'+src+'">';
		
		// StretchToFit will scale up the video if the player is larger than the content, 
		// 	but the aspect ratio will be preserved. 
		// There is no ShrinkToFit like for IE, the behavior is just always to shrink to fit. 
		html += '   	<param name="stretchToFit" value="1" />';	
		html += paramUiMode;
		html += '</OBJECT>';
		return html;
	};

	embedobj.octobarHTML = function(id, src,width,height){
		var html  = '';
			html += '	<embed src="'+src+'"';
			html += '		STYLE="margin-top:-4px;"'; // for some reason fx inserts a spacing between the objects.
			html += '		loop="false"';
			html += '		menu="false"';
			html += '		quality="high"';
			html += '		salign="lt"';
			html += '		bgcolor="#ffffff"';
			html += '		width="'+width+'"';
			html += '		height="'+height+'"';
			html += '		name="'+id+'"';
			html += '		align="middle"';
			html += '		allowScriptAccess="always"';
			html += '		allowFullScreen="false"';
			html += '		type="application/x-shockwave-flash"';
			html += '		pluginspage="http://www.macromedia.com/go/getflashplayer" />';
			return html;
	};
}

/* 
 @function: octopv_embedobj_setIeWmp7
	 For Internet Explorer at least with wmp 7.
 @param embedobj
 @Adds public methods to embedobj:
 	- void playerHTML(id, src, width, height, showControls) 
 	- void octobarHTML(id, src,width,height) 
*/
function octopv_embedobj_setIeWmp7(embedobj){
	octopv_debug('Creating embedobj ', arguments.callee);
	
	embedobj.playerHTML = function(id, src, width, height, showControls){
		var html  = '';
		var paramUiMode = '';
		var controls = 0;
		
		if(showControls){
			paramUiMode += '	<PARAM name="uimode" value="mini" >';
			controls += 45; 
		}else{
			paramUiMode += '	<PARAM name="uimode" value="none" >';
		}
		
		octopv_debug('inserting. h:'+height+" cntrls: "+controls+" ", arguments.callee);
		html += '<OBJECT ID="'+id+'" ';
		html += 'height="'+(height + controls)+'" width="'+width+'" ';
		html += 'classid="CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6" ';
		html += 'STANDBY="Loading Octoshape plugin and client" ';
		html += 'pluginspage="http://microsoft.com/Windows/MediaPlayer/" ';
		html += 'codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,7,1112" '; // checks if wmp is installed, if not it is installed automaticly 
		html += 'type="application/x-oleobject">';
		html += '	<param name="rate" value="True" />';
		html += '	<param name="enableErrorDialogs" value="False" />';	
		html += '   <param name="autostart" value="True" />';
		html += '	<param name="URL" value="'+src+'" />';
		
		// StretchToFit will scale up the video if the player is larger than the content, 
		// 	but the aspect ratio will be preserved.
		// The matching shrinkToFit has default value true so it is not necessary to add it.
		html += '   <param name="StretchToFit" value="True" />';

		
		html += paramUiMode;
		html += '</OBJECT>';
		return html;
	};
	
	embedobj.octobarHTML = function(id, src,width,height){
		var html='';
		html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
		html += 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ';
		html += 'width="'+width+'" height="'+height+'" id="'+id+'" align="middle">';
		html += '	<param name="allowScriptAccess" value="always" />';
		html += '	<param name="allowFullScreen" value="false" />';
		html += '	<param name="movie" value="'+src+'" />';
		html += '	<param name="loop" value="false" />';
		html += '	<param name="menu" value="false" />';
		html += '	<param name="quality" value="high" />';
		html += '	<param name="salign" value="lt" />';
		html += '	<param name="bgcolor" value="#ffffff" />';
		html += '</object>';
		return html;
	};
	
	
}


/* 
 @function: octopv_embedobj_setIeWmp64
 		For Internet Explorer with WMP version 6.4 or lower
 @param embedobj
 @Adds public methods to param embedobj:
 	- void playerHTML(id, src, width, height, showControls) 
 	- void octobarHTML(id, src,width,height) 
	- playerStop2()
	- playerPause()
	- playerPlay2()
	- playerVolume(number)
	- playerSetNewUrl(newUrl)	
 @issues:
 	1) Video content scalling: (StretchToFit parameter)
	  	- scales up and down 	
	  	- but does not keep aspect ratio
*/
function octopv_embedobj_setIeWmp64(embedobj){
	octopv_debug('Creating embedobj: ', arguments.callee);
	
	embedobj.playerHTML = function(id, src, width, height, showControls){
		var html  = '';
		var objectParamsUiMode = '';
		var objectControls = 0;

		objectParamsUiMode += '<PARAM name="showtracker" value="false" >';
		objectParamsUiMode += '<PARAM name="showdisplay" value="false" >';
		
		if(showControls){
			objectParamsUiMode += '<PARAM name="showcontrols" value="true" >';
			objectControls += 26; 
			objectParamsUiMode += '<PARAM name="showstatusbar" value="true" >';
			objectControls += 24; 
		}else{
			objectParamsUiMode += '<PARAM name="showcontrols" value="false" >';
			objectParamsUiMode += '<PARAM name="showstatusbar" value="false" >';
		}
		
		html += '<OBJECT ID="'+id+'" ';
		html += 'height="'+(height + objectControls)+'" width="'+width+'"';
		html += 'classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"';
		html += 'STANDBY="Loading Octoshape plugin and client"';
		html += 'pluginspage="http://microsoft.com/Windows/MediaPlayer/" ';
		html += 'codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,7,1112"'; // checks if wmp is installed, if not it is installed automaticly 
		html += 'type="application/x-oleobject">';
		html += '	<param name="rate" value="True" />';
		html += '	<param name="enableErrorDialogs" value="False" />';	
		html += '   <param name="autostart" value="true" />';
		html += '   <param name="PlayCount" value="1" />';
		html += '   <param name="AutoRewind" value="false" />';
		html += '	<param name="URL" value="'+src+'" />';
		html += '	<param name="src" value="'+src+'" />';
		html += objectParamsUiMode;
		html += '   <param name="stretchToFit" value="true" />';
		html += '</OBJECT>';
		return html;
	};

	embedobj.octobarHTML = function(id, src,width,height){
		var html = '';
		html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
		html += 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ';
		html += 'width="'+width+'" height="'+height+'" id="'+id+'" align="middle">';
		html += '	<param name="allowScriptAccess" value="always" />';
		html += '	<param name="allowFullScreen" value="false" />';
		html += '	<param name="movie" value="'+src+'" />';
		html += '	<param name="loop" value="false" />';
		html += '	<param name="menu" value="false" />';
		html += '	<param name="quality" value="high" />';
		html += '	<param name="salign" value="lt" />';
		html += '	<param name="bgcolor" value="#ffffff" />';
		html += '</object>';
		return html;
	}


	embedobj.stop = function(player){
		try{
			player.stop();
			return true;
		}catch(exception){
			octopv_debug('Could not stop: '+exception, arguments.callee);
			return false;
		}
	};
	
	embedobj.start = function(player){
		try{
			player.play();
			return true;
		}catch(exception){
			octopv_debug('Could not play: '+exception, arguments.callee);
			return false;
		}
	};
	
	embedobj.pause = function(player){
		try{
			player.pause();
			return true;
		}catch(exception){
			octopv_debug('Could not pause: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.volume = function(player,number){
		try{
			// volume min is -10.000, max is 0, and mmedium is -600.
			// mapping below is heuristic
			var num = octopv_convertToNumber(number,0);
			if(num!=0){
				num = Math.log(num) * (100/Math.log(100));
				num = Math.sqrt(num) * 10;
				num = ((num)-100)*100;
			}
			player.Volume=num;
			octopv_debug('volume is after : '+player.Volume, arguments.callee);
			return true;
		}catch(exception){
			octopv_debug('Could not volume: '+exception, arguments.callee);
			return false;
		}
	};
	
	embedobj.setNewUrl = function(player, newUrl){
		try{
			octopv_debug('Setting url to '+newUrl, arguments.callee);
			player.Open(newUrl);
			return true;
		}catch(exception){
			octopv_debug('Could not seek: '+exception, arguments.callee);
			return false;
		}
	};
}


/* 
 @function: octopv_embedobj_setEmbedTag
 	Uses an <embed> tag
 	Used for Firefox without wmp plugin and for unknown browsers.
	Adds simple scripting by removing and inserting the player on the page.
 @param embedobj
 @Adds public methods to param embedobj:
 	- void playerHTML(id, src, width, height, showControls) 
	- startup()	: shows html img tag this startup image.
	- playerStop2(): removes the player.
	- playerPause(): dummy.
	- playerPlay2(): inserts a new player on the page
	- playerVolume(number): dummy.
	- playerSetNewUrl(newUrl): inserts a new player on the page
 @issues:
 	1) Video content scalling: 
	  	There are no usefull parameters.  Stretchtofit parameter does not work, 
	  	and autosize wil resize the PLAYER to fit the content (unless height and width are specified)).
	  	- only scales down 
	  	- keeps aspect ratio
	
 	2) Firefox + wmp 11: video content scalling (embed tag):
		Windows media player 11 has stretch and resize error with firefox embed plugin. 
 
 	3) None of the controls can be removed. 
	
*/
function octopv_embedobj_setEmbedTag(embedobj){
	octopv_debug('Creating embedobj: ', arguments.callee);
	
	embedobj.playerHTML = function(id, src, width, height, showControls){
		var html  = '';
		var embedControls = 51;	

		html += '<embed ';
		html += ' 	type="application/x-mplayer2" ';
		html += ' 	pluginspage="http://microsoft.com/Windows/MediaPlayer/" ';
		html += ' 	filename="'+src+'" ';
       	html += ' 	src="'+src+'" ';
		html += '	name="'+id+'" ';
       	html += '	width="' + width + '" ';
       	html += '	height="'+(height + embedControls)+'" />';
		return html;
	};

}

/* 
 @function: octopv_setWmpScripting
 @param embedobj
 @Adds public methods to param embedobj:
	- stop(player)
	- pause(player)
	- start(player)
	- volume(player,number)
	- setNewUrl(player,newUrl)
	- octobarReady()
*/
function octopv_setWmpScripting(embedobj){
	octopv_debug('Adding scripting functions embedobj. octobar: '+(embedobj.controls==1)+" controls: "+embedobj.controls, arguments.callee);
	
	embedobj.octobarReady = function(callbackObject, playerDiv, playerObject){
		octopv_debug('Function called ... ', "embedobj.octobarReady");
		callbackObject.playStateHandler = function(newState){
			octopv_debug('Callback function called ... ', "embedobj.octobarReady");
			switch(newState){
			case 3:	// playing state
				if(this.eventCallback_mustGetDuration()){
					var duration = this.playerObject.currentMedia.duration;
					this.eventCallback_duration(duration);
				}else{
					this.eventCallback_playing();
				}
				return true;
			case 8:	 // media ended state. 
				this.eventCallback_ended();
				return false;
			case 6: // buffering state
				this.eventCallback_buffering();
				return false;
			case 1:
				octopv_debug("wmp event stopped. ",  arguments.callee);
				return false;
			case 9:  
				octopv_debug("wmp event transitioning.", arguments.callee);
				return false;
			case 10:  
				octopv_debug("wmp event ready to play.", arguments.callee);
				return false;
			default:
				octopv_debug("wmp event "+newState, arguments.callee);
				return false;
			}
		};

		callbackObject.playStateHandlerNoArg = function(){
			var state = this.playerObject.playState;
			if((typeof(this.previousPlayState) == 'undefined' )|| (this.previousPlayState != state)){
				this.previousPlayState = state;
				this.playStateHandler(state);
			}
		};
		
		function setEventListener(eventName, handlerName, thisplayerDiv, thisplayerObject){
			octopv_debug("testing this.playerDiv: "+thisplayerDiv+" .", arguments.callee);
			var event = '';
			event += 	'var player = octopv_embeddedPlayers["'+thisplayerDiv+'"];';
			event += 	'if(typeof player != "undefined"){';
			event += 	'try{';
			event += 		'player.'+handlerName+'(NewState);';
			event += 	'}catch(ex){ ';
			event += 		'octopv_debug("Error calling '+handlerName+' with "+NewState+". Ex:"+ex, alert);';
			event += 	'}';
			event += 	'}else{';
			event += 		'octopv_debug("Could not find player in '+eventName+' event handler. state:"+NewState, alert);';
			event += 	'}';
			try{
				if(octopv_isFirefox3()){
					/**
					 The windows media player plugin object oriented event handlers does not work in Firefox 3.
					 For unknown reasons. No web documentation exists on this (acording to miscrosofts docu it should work).
					 TODO:
					 1) test with to players in one page!
					 2) new update in br-we-int pages.
					*/
					//we only add this once since it loops through all active players 
					if(typeof(window['octopv_hasSetFx3EventHandler']) == 'undefined'){
						window['octopv_hasSetFx3EventHandler'] = true;
						octopv_debug("Firefox 3 adding simple onState change for: "+thisplayerDiv+" .", arguments.callee);
						var scriptText = 'function OnDSPlayStateChangeEvt(NewState){';
						scriptText += '		for (var i in octopv_embeddedPlayers){';
						scriptText += '			try{';
						scriptText += '				octopv_embeddedPlayers[i].playStateHandlerNoArg();';
						scriptText += '			}catch(ex){';
						scriptText += '				octopv_debug("ERROR: "+ex+" Full embedded players array ("+getPropertiesString(octopv_embeddedPlayers)+")", arguments.callee);'; 
						scriptText += '			}';
						scriptText += '		}';
						scriptText += '}';
						var script = document.createElement('script');
						script.type = 'text/javascript';
						script.text = scriptText;
						document.getElementById(thisplayerDiv).appendChild(script);
					}
				}else if(octopv_isFirefox()){
					octopv_debug("Adding wmp event "+eventName+" listener firefox.", arguments.callee);
					var script = document.createElement('script');
					script.type = 'text/javascript';
					script.setAttribute('for', octopvGetPlayerID(thisplayerDiv));
					script.setAttribute('event', eventName+'(NewState)');
					script.text = event;
					document.getElementById(thisplayerDiv).appendChild(script);
				}else{
					// Internet Explorer can not use setAttribute for event handlers.
					// Dynamically adding a script inside another
					// attachEvent works for IE5+
					// attachEvent only works for IE
					/* About the second argument to attachEvent:
					  	It will be referenced not copied (the 'this' variable refers to the window element).
					  	There is appearently no way of getting a reference to the element that caused the event. 
					*/
					octopv_debug("Attaching wmp event "+eventName+" listener ie.", arguments.callee);
					var func = new Function("NewState", event);
					thisplayerObject.attachEvent(eventName, func);
				}
			}catch(ex){
				octopv_debug('Error adding '+eventName+' event listener: '+ex, arguments.callee);
			}
		};

		octopv_debug("Adding wmp event listeners.", arguments.callee);
		if(!callbackObject.playStateHandler(playerObject.playState)){
			setEventListener('PlayStateChange', 'playStateHandler', playerDiv,playerObject);
		};
		
		return true;
	}
	
	embedobj.stop = function(player){
		try{
			player.controls.stop();
			return true;
		}catch(exception){
			octopv_debug('Could not stop: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.start = function(player){
		try{
			player.controls.play();
			return true;
		}catch(exception){
			octopv_debug('Could not play: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.pause = function(player){
		try{
			player.controls.pause();
			return true;
		}catch(exception){
			octopv_debug('Could not pause: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.volume = function(player,number){
		try{
			octopv_debug('volume is before : '+player.settings.volume, arguments.callee);
			player.settings.volume=number;
			octopv_debug('volume is after : '+player.settings.volume, arguments.callee);
			return true;
		}catch(exception){
			octopv_debug('Could not volume: '+exception, arguments.callee);
			return false;
		}
	}
	
	embedobj.setNewUrl = function(player, newUrl){
		try{
			octopv_debug('Setting url to '+newUrl, arguments.callee);
			player.URL=newUrl;
			return true;
		}catch(exception){
			octopv_debug('Could not seek: '+exception, arguments.callee);
			return false;
		}
	}
}


/* **************************************************************************************/
/* ********************************* Interface Octobar uses *******************************/


function octoEmbeddedOctobarReady(playerDivId){
	var player = octopv_octobarHelp(playerDivId);
	if(player != null) player.octobarReady();
}

function octoEmbeddedPlayerPlay(playerDivId){
	var player = octopv_octobarHelp(playerDivId);
	if(player != null) player.playerPlay();
}

function octoEmbeddedPlayerPause(playerDivId){
	var player = octopv_octobarHelp(playerDivId);
	if(player != null) player.playerPause();
}

function octoEmbeddedPlayerStop(playerDivId){
	var player = octopv_octobarHelp(playerDivId);
	if(player != null) player.playerStop();
}

function octoEmbeddedPlayerSeek(playerDivId, number){
	var player = octopv_octobarHelp(playerDivId);
	if(player != null) player.playerSeek(number);
}

function octopv_octobarHelp(playerDivId){
	var player = octopv_embeddedPlayers[playerDivId];
	if(typeof player != 'undefined' ){
		return player;
	}else{
		octopv_debug('player '+playerDivId+' not in embedded players array ('+getPropertiesString(octopv_embeddedPlayers)+') ', arguments.callee);
		return null;
	}
}


/* **************************************************************************************/
/* ********************************* UTILITY FUNCTIONS *******************************/


function octopv_hasWmp7(){
	var wmp7;
	try{
		if(window.ActiveXObject){
    		wmp7 = new ActiveXObject("WMPlayer.OCX.7");
		} else if (window.GeckoActiveXObject) {
	    	 wmp7 = new GeckoActiveXObject("WMPlayer.OCX.7");
		}
	}catch(ex){
		octopv_debug("Could not instantiate (gecko) activex object: "+ex, arguments.callee);
		return false;
	}
	if (wmp7) return true; 
	return false;
}


/** 
 Converts an octolink where it is not known if it has a OCTOSHAPE[group]: prefix or not, to a standard form.
 If withPrefix is true, the returned link is on the form OCTOSHAPE[group]:link
 otherwise it is only the octolink. 
*/
function octopv_uniformOctolink(link, withPrefix){
	var low = link.toLowerCase();
	var group = octopv_group;
	var octoid = link;
	if(low.indexOf("octoshape") == 0){
		var endGroup = low.indexOf(':',0);
		group = low.substring(8,end).toUpperCase();
		octoid = link.substring(endGroup+1);
	}
	return withPrefix?"OCTOSHAPE"+this.group+":"+this.octoid:this.octoid;
}







