// Javascript 1.5 file
// title: Media Player Practice
// by: Christopher Walker, 2005
/*	description: An object class written in Javascript
*	to use both Windows Media Player and Quicktime
*	with some of the same methods
*/ 

/*
support:
========
this class is really targeted for Quicktime 7 and Windows
Media Player 9, but may work for slighter earlier versions.
The Quicktime player should work for browsers that allow
scripting of the Quicktime plug-in (Gecko,IE, and Safari 2.0)
The Windows Media player will only work with browsers that
support the ActiveX object (likely only IE for Windows, unless
the end-user tweaks Gecko).  Opera 8 doesn't appear to support
any scripting of external media players at this time.

other notes:
============
the class assumes you want to show the controller.  Autostart
will be turned off.

constructor:
============
	var instanceName = new Media([strMediaPlayer]);
	
	*if no argument is passed, the constructor will try to figure
	out which media player to choose.  If the UA is IE, then the
	constructor will pick "windowsmediaplayer", otherwise
	the constructor will "quicktime".  To determine if the the UA is
	IE or not, the constructor will see if the UA runs ActiveX components.
	If so, "windowsmediaplayer" will be chosen.
	
	possible string arguments:
	"windowsmediaplayer"
	"quicktime"
	
	example:
		myMedia = new Media("quicktime");

methods:
=======

	player()
		read-only string that indicates which media player 
		to use.  Currently accepted values which can be returned
		include	"windowsmediaplayer" and "quicktime".  This value
		is set up during the creation of the object (see constructor).
		
		example:
			alert(myMedia.player());
			// returns an alert box saying "quicktime", or
			other specifiec player
				
	height()
		read/write number indicating the pixel height of media
		
	width()
		read/write number indicating the pixel width of media
		
	nameAndId()
		read/write string indicating the name and id.  For cross
		browser scripting, these two values should be the same,
		and thus are brought together in this single method.
		
	autoStart()
		read/write boolean to start movie immediately upon load.
		If this property is set before the movie loads, the param can
		be passed to the embed/object tag.
		
		* note to self:
		in the code, this example shows how a method is built for both
		pre-load purposes and after load dyanmic changes
		
	uiMode()
		read/write string indicate how the media controller should
		display.  Current values include: "none" and "full".
		Windows Media Player allows for other options as well,
		but this method does not currently offer support.
		(currently only works on embed tags before load)
				
	url()
		read/write string indicating the full url of the movie to load
		into the Media object.
		
	play()
		method to get the movie to start playing from the current
		start time to the current end time.
		
	playOrLoad()
		method to play or load media as needed.
		
	stopAndRewind()
		method to get the movie to stop at the current time, then rewind
		to the beginning
		
	pause()
		method to pause the movie without changing current time position
		
	hidden()
		read/write boolean which sets the width and height to smallest
		possible (2px by 2px).  *note: a completely invisible
		embed seems impossible (to Netscape at least).
		(affects embed tags... not dynamic at this point)
		
	mute()
		read/write using boolean 'true' or 'false'
		method to mute on or off without changing the current volume setting
		a 'true' value indicates that no sounds is being emitted.
		
	isLooping()
		read/write boolean shows loop state 'true' or 'false'
		
	isPlaying()
		read only boolean tells whether the media is currently playing or not
		
	playSection(startTime, endTime)
		write only, integers in seconds from beginning.  Internally
		uses the doNotPlayBeyond() method (see decscription).
		
	loadIntoDiv(divname)
		method loads tags into div element specified by string divname and
		sets the __loaded__ property of the object as true, which
		is important.
		
	doNotPlayBeyond()
		read/write int of times from beginning.  This method has been
		implemented since windows media player doesn't seem to have
		a setable 'endtime' as in quicktime.  This method sets up a timer
		to see if the timePosition is still less the the doNotPlayBeyond
		time.  Use of this method should involve an understanding of the code
		that comprises the function.
		
	duration()
		read-only integer return total time of movie in seconds.
		*This method doesn't seem to work in WMP until the movie
		has been activated by the user.
		
	timePosition()
		read/write integer indicating the current time position of the movie,
		in seconds from beginning.
		
	createTags()
		returns string to create all the necessary XTHML tags (such as
	 	<object> and <embed> along with the parameters as specified
		in the other Media properties.  Use function innerHTML to put
		in website.  (I might make this an actual DOM object)
		
	stretchToFit()
		read/write boolean, specifies that movie will fit the
		specified height and width of the object/embed tag, while
		keeping aspect ratio.  Default set to false.
		
		
extra notes:
============
	to make hidden:
		The object or embed tag must appear withing the document,
		and it needs 2px by 2px real display, but it can be taken
		out of view of the viewport by setting container within
		the document body and giving it an absolute position of
		top:-20px and left:-20px, a method that will work in
		IE6 which does not have fixed position. In addition to the
		usual Media parameters, you should set o.hidden(true);
		o.uiMode("none"); the former makes height and width
		2 by 2 pixels (regardless of what is specified in the
		height and width parameters), and the later takes out
		and expanding of the width to compensate for the controller.
*/
/********************************************************* the constructor */
// constants
__playerControlHeightQuicktime__ = 16; // pixel unit
__playerControlHeightWindowsmediaplayer__ = 45;
// MODIFIED
function Media(sPlayer) {
	//alert(sPlayer); // debugger
	if (sPlayer==undefined) {
		if (window.ActiveXObject) {
			sPlayer = "windowsmediaplayer";
		}
		else {
			sPlayer = "quicktime";
		}
	}
	//alert("chosen media player: "+sPlayer); // debugger
	this.__player__ = sPlayer;
	this.__url__ = new String("not set yet");
	this.__width__ = new Number(0);
	this.__height__ = new Number(0);
	this.__nameAndId__ = new String("no name or id set yet");
	this.__autoStart__ = false; // default no autoStart
	//this.__nameOfInstance__ = "net set yet"; 
	// the above can be done with function closure
	this.__hidden__ = false; 
	this.__loaded__ = false;
	this.__uiMode__ = "full";
	this.__stretchToFit__ = false;
}



/**************************************************** methods properties */
Media.prototype.player = function() {
	return this.__player__;
}
Media.prototype.uiMode = function (sType) {
	var m = document.getElementById(this.__nameAndId__);
	if (this.__player__ == "quicktime") {
		if (sType==undefined) {
			return this.__uiMode__;
		}
		else {
			if (this.__loaded__) {
				m.SetControllerVisible((sType=="none")?0:1);
			} else {
				this.__uiMode__ = sType;
			}
		}
	}
	else if (this.__player__== "windowsmediaplayer") {
		if (sType==undefined) {
			return this.__uiMode__;
		}
		else {
			if (this.__loaded__) {
				m.uiMode = sType;
			} else {
				this.__uiMode__ = sType;
			}
		}
	}
}
Media.prototype.stretchToFit = function (bln) {
	var m = document.getElementById(this.__nameAndId__);
	if (this.__player__ == "quicktime") {
		if (bln==undefined) {
			return this.__stretchToFit__;
		}
		else {
			if (this.__loaded__) {
				//manual indicates can't do dynamically
			} else {
				this.__stretchToFit__ = bln;
			}
		}
	}
	else if (this.__player__== "windowsmediaplayer") {
		if (bln==undefined) {
			return this.__stretchToFit__;
		}
		else {
			if (this.__loaded__) {
				m.stretchToFit = bln;
			} else {
				this.__stretchToFit__ = bln;
			}
		}
	}
}

Media.prototype.url = function(sUrl) {
	// get
	if (sUrl == undefined) {
		return this.__url__;
	}
	// set
	else {
		this.__url__ = sUrl;
		return true;
	}
}
Media.prototype.hidden = function(bln) {
	// get
	if (bln == undefined) {
		return this.__hidden__;
	}
	// set
	else {
		this.__hidden__ = bln;
		return true;
	}
}
Media.prototype.play = function() {
		// make sure the timer for section is off
		clearInterval(this.__doNotPlayBeyondTimerId__);
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {
			m.Play();
		}
		else if (this.__player__ == "windowsmediaplayer") {
			m.controls.play();
		}
}
Media.prototype.pause = function () {
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {			
			m.Stop();
		}
		else if (this.__player__ == "windowsmediaplayer") {
			m.controls.pause();
		}
}
Media.prototype.mute = function (bln) {
	var m = document.getElementById(this.__nameAndId__);
	if (this.__player__ == "quicktime") {			
		if (bln==undefined) {
			if (m.GetMute()==0) {
				return false;
			}
			else {
				return true;
			}
		}
		else {
			if (bln==true) {
				m.SetMute(1);
			}
			else {
				m.SetMute(0);
			}
		}
	}
	else if (this.__player__ == "windowsmediaplayer") {
		if (bln==undefined) {
			return m.settings.mute;
		}
		else {
			m.settings.mute = bln;
		}
	}
}
Media.prototype.isLooping = function (bln) {
	var m = document.getElementById(this.__nameAndId__);
	if (this.__player__ == "quicktime") {			
		if (bln==undefined) {
			if (m.GetIsLooping()==0) {
				return false;
			}
			else {
				return true;
			}
		}
		else {
			if (bln==true) {
				m.SetIsLooping(1);
			}
			else {
				m.SetIsLooping(0);
			}
		}
	}
	else if (this.__player__ == "windowsmediaplayer") {
		if (bln==undefined) {
			return m.settings.getMode("loop");
		}
		else {
			m.settings.setMode("loop", bln);
		}
	}
}


Media.prototype.duration = function () {
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {			
			return (m.GetDuration() / m.GetTimeScale());
		}
		else if (this.__player__ == "windowsmediaplayer") {
			return m.currentMedia.duration;
		}
}
			
			
			
Media.prototype.timePosition = function(iTime) {
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {
			if (iTime == undefined) {
				return (m.GetTime() / m.GetTimeScale());
			}
			else {
				m.SetTime(iTime * m.GetTimeScale());
			}
		}
		else if (this.__player__ == "windowsmediaplayer") {
			if (iTime == undefined) {
				return m.controls.currentPosition;
			}
			else {
				m.controls.currentPosition = iTime;
			}
		}
}


Media.prototype.isPlaying = function() {
	var m = document.getElementById(this.__nameAndId__);
	if (this.__player__ == "quicktime") {
		if (m.GetRate() != 0) {
			return true;
		}
		else {
			return false;
		}
	}
	else if (this.__player__ == "windowsmediaplayer") {
		if (m.playState == 3) {
			return true;
		}
		else {
			return false;
		}
	}
}

Media.prototype.stopAndRewind = function () {
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {
			m.Stop();
			m.Rewind();
		}
		else if (this.__player__ == "windowsmediaplayer") {
			m.controls.stop();
		}
}


Media.prototype.width = function(nWidth) {
	// get
	if (nWidth == undefined) {
		return this.__width__;
	}
	// set
	else {
		this.__width__ = nWidth;
		return true;
	}
}
Media.prototype.height = function(nHeight) {
	// get
	if (nHeight == undefined) {
		return this.__height__;
	}
	// set
	else {
		this.__height__ = nHeight;
		return true;
	}
}
Media.prototype.autoStart = function(bln) {
	if (bln != undefined) {
		this.__autoStart__ = bln;
		// maybe add later if needed:
		// if (thisIsLoaded) set PLAYER OBJECT to autostart yes!
		// SEE BELOW
	} else {
		return this.__autoStart__;
	}
}
	
	
	
	/*if ((this.__nameAndId__) && (document.getElementById(this.__nameAndId__))){ 
		var m = document.getElementById(this.__nameAndId__);
		if (this.__player__ == "quicktime") {			
			if (bln==undefined) {
				if (m.GetAutoPlay()==0) {
					return false;
				}
				else {
					return true;
				}
			}
			else {
				if (bln==true) {
					m.SetAutoPlay(1);
				}
				else {
					m.SetAutoPlay(0);
				}
			}
		}
		else if (this.__player__ == "windowsmediaplayer") {
			if (bln==undefined) {
				return m.settings.autoStart;
			}
			else {
				m.settings.autoStart = bln;
			}
		}
	}
	else {
		return this.__autoStart__;
	}*/

Media.prototype.nameAndId = function(sNameAndId) {
	// get
	if (sNameAndId == undefined) {
		return this.__nameAndId__;
	}
	// set
	else {
		this.__nameAndId__ = sNameAndId;
		return true;
	}
}
Media.prototype.loadIntoDiv = function(sDivId) {
	oDiv = document.getElementById(sDivId);
	oDiv.innerHTML = this.createTags();
	this.__loaded__ = true;
}

Media.prototype.createTags = function() {
	var tags = new String("");
	// redo this so that __playerControlHeight__ is variable as property of Media
	var playerControlHeight=(this.__uiMode__=="none")?0:(this.__player__=="quicktime")?__playerControlHeightQuicktime__:__playerControlHeightWindowsmediaplayer__;
	var bController = (this.__uiMode__=="none")?"False":"True";
	var height = (this.__hidden__)?2:this.__height__;
	var width  = (this.__hidden__)?2:this.__width__;
	// above: WMP handles this just by setting height and width to zero
	// quicktime?
	if (this.__player__ == "quicktime") {
		tags  ="<embed \n";
		tags +="\ttype=\"image/x-quicktime\"\n";
		// i had taken out the bottom 2 earlier, why?
		
		tags +="\twidth=\""+width+"\"\n";
		tags +="\theight=\""+(height+playerControlHeight)+"\"\n";
		
		tags +="\tsrc=\""+this.__url__+"\"\n";
		tags +="\tname=\""+this.__nameAndId__+"\"\n";
		tags +="\tid=\""+this.__nameAndId__+"\"\n";
		tags +="\tautoplay=\""+this.__autoStart__+"\"\n";
		tags +="\tscale=\""+((this.__stretchToFit__)?"Aspect":"1")+"\"\n";
		tags +="\tcontroller=\""+bController+"\"\n";
		tags +="\tbgcolor=\"black\"\n";
		tags +="\tAllowEmbedTagOverrides=\"True\"\n";
		tags +="\tenablejavascript=\"True\">\n";
		tags +="</embed>\n";
	}
	
	/* OLD VERSION
		if (this.__player__ == "quicktime") {
		tags  ="<embed \n";
		tags +="\tsrc=\"/javascript/UNeedQT4.qtif\"\n";
		tags +="\ttype=\"image/x-quicktime\"\n";
		// i had taken out the bottom 2 earlier, why?
		
		tags +="\twidth=\""+width+"\"\n";
		tags +="\theight=\""+(height+playerControlHeight)+"\"\n";
		
		tags +="\tqtsrc=\""+this.__url__+"\"\n";
		tags +="\tname=\""+this.__nameAndId__+"\"\n";
		tags +="\tid=\""+this.__nameAndId__+"\"\n";
		tags +="\tautoplay=\""+this.__autoStart__+"\"\n";
		tags +="\tscale=\""+((this.__stretchToFit__)?"Aspect":"1")+"\"\n";
		tags +="\tcontroller=\""+bController+"\"\n";
		tags +="\tbgcolor=\"black\"\n";
		tags +="\tAllowEmbedTagOverrides=\"True\"\n";
		tags +="\tenablejavascript=\"True\">\n";
		tags +="</embed>\n";
	}
	*/
	// or windowsmediaplayer?
	else if (this.__player__ == "windowsmediaplayer") {
		
		tags  ="<object \n";
		tags +="\tname=\""+this.__nameAndId__+"\"\n";
		tags +="\tid=\""+this.__nameAndId__+"\"\n";
		tags +="\twidth=\""+width+"\"\n";
		tags +="\theight=\""+(height+playerControlHeight)+"\"\n";
		tags +="\tclassid=\"CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6\">\n";
		tags +="\t<param name=\"autoStart\" value=\""+
			this.__autoStart__+"\"/>\n";
		tags +="\t<param name=\"stretchToFit\" value=\""+this.__stretchToFit__+"\"/>\n";
		tags +="\t<param name=\"uiMode\" value=\""+this.__uiMode__+"\"/>\n";
		tags +="\t<param name=\"URL\" value=\""+this.__url__+"\"/>\n";
  		tags +="</object>";
	}
	// or player not defined
	else {
		tags = "player not defined";
	}
	return tags;
}
// DELETE ME
/*Media.prototype.doNotPlayBeyondDELME = function(iTime) {
	this.__doNotPlayBeyond__ = iTime; // global variable
	
	var instanceName = this.__nameOfInstance__;
	code = "if ("+instanceName+".__doNotPlayBeyond__ < "+
		instanceName+".timePosition())"+
		"{"+instanceName+".pause(); clearInterval("+
		instanceName+".__doNotPlayBeyondTimerId__);}; ";
	
	
	if (this.__player__ == "windowsmediaplayer" ||
	    this.__player__ == "quicktime") {
		// this.checkIfPlayingBeyond();
		this.__doNotPlayBeyondTimerId__ = setInterval(code,1) // global
	}
}*/



// the following belongs together as a group
// must add closure to the function since otherwise
// the object is not evaluated
function __setupIntervalTimerForEnd__(o) {
	return function() {
		// document.getElementById("debug").innerHTML = o.timePosition();
		if (o.timePosition() >= o.__doNotPlayBeyond__) {
			// o.pause();
			o.stopAndRewind();
			clearInterval(o.__doNotPlayBeyondTimerId__);
		}
	}
}
Media.prototype.doNotPlayBeyond = function(iTime) {
	this.__doNotPlayBeyond__ = iTime;
		this.__doNotPlayBeyondTimerId__ =
		setInterval(__setupIntervalTimerForEnd__(this),1);
}



Media.prototype.playSection = function(iStartTime, iEndTime) {
	this.timePosition(iStartTime);
	this.play();
	this.doNotPlayBeyond(iEndTime);

}
