/**** $Id: mediaplayer.js,v 1.8 2008/09/11 13:28:36 tdinatale Exp $****/

/**
 * mediaPlayer.js
 *
 * Javascript library file for Embedded Windows Media Player
 * 
 * Usage: 
 *  Create a DIV tag that will house the media player window:
 *    <div id="media_div" style="width: 400px; height: 300px;">
 *       JavaScript must be enabled to view this content.
 *    </div>
 *
 *  Setup the mediaplayer object:
 *    var player = new MediaPlayer('media_div', 400, 300);
 *
 *  To setup a play/pause/stop button that automatically updates
 *  based on the playstate:
 *
 *    <a href="#" onclick="player.playOrPause(); return false;">
 *      <img id="play_pause" src="play.gif" border="0" />
 *    </a>
 *
 *    player.setPlayPauseImages('play_pause', 'play.gif', 'pause.gif', 'stop.gif');
 *
 *  To setup a mute/unmute button that automatically updates
 *  based on the mute state:
 *
 *    <a href="#" onclick="player.mute(); return false;">
 *      <img id="mute_img" src="mute_off.gif" border="0" />
 *    </a>
 *
 *    player.setMuteImages('mute_img', 'mute_off.gif', 'mute_on.gif');
 *
 *  To setup a volume images map that updates when the user clicks:
 *
 *    <img id="volume_map" src="vol3.gif" border="0" usemap="#volmap" />
 *
 *    player.setVolumeImages('volume_map', 'vol0.gif', 'vol1.gif', 'vol2.gif', 'vol3.gif', ...);
 *    In the Image map:
 *       player.setVolume(3, 10); // current, max
 *
 *  to play a single media item:
 *    player.setMedia('video/x-msvideo', 'video.wmv');
 *    player.play();
 *    player.pause();
 *    player.stop();
 *
 *  to play a playlist:
 *    player.addToPlaylist('tag1', 'video/x-msvideo', 'video.wmv', 'Title 1');
 *    player.addToPlaylist('tag2', 'video/x-pn-realvideo', 'video.rm', 'Title 2');
 *    player.addToPlaylist('tag3', 'video/x-flv', 'video.flv', 'Title 3');
 *    player.play();
 *    player.skipForward();
 *    player.skipBackward();
 */

/**** CLASS HELPER FUNCTIONS ****/
/* Two functions below copied from: http://www.crockford.com/javascript/inheritance.html */
Function.prototype.method = function (name, func)
{
	this.prototype[name] = func;
	return this;
};

Function.method('inherits', function (parent)
{
	var d = 0, p = (this.prototype = new parent());
	this.method('uber', function uber(name) 
	{
		var f, r, t = d, v = parent.prototype;
		if (t)
		{
			while (t)
			{
				v = v.constructor.prototype;
				t -= 1;
			}
			f = v[name];
		}
		else
		{
			f = p[name];
			if (f == this[name])
			{
				f = v[name];
			}
		}
		d += 1;
		r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
		d -= 1;
		return r;
	});
	return this;
});
/**** END CLASS HELPER FUNCTIONS ****/

/**** MEDIA OBJECT BASE CLASS ****/
function MediaObject(sDivId, iWidth, iHeight)
{
	this.construct(sDivId, iWidth, iHeight);
}

MediaObject.method('construct', function(sDivId, iWidth, iHeight)
{
	this.div_id = sDivId;
	this.div    = (document.getElementById ? document.getElementById(sDivId) : document.sDivId);

	this.width  = iWidth;
	this.height = iHeight;
});

MediaObject.method('showPlayer', function() {});
MediaObject.method('hidePlayer', function() {});
MediaObject.method('setContent', function(sContentUrl) {});
MediaObject.method('play', function () {});
MediaObject.method('pause', function () {});
MediaObject.method('stop', function () {});
MediaObject.method('isPlaying', function () { return false; });
MediaObject.method('mute', function (bMute) {});
MediaObject.method('setVolume', function (iPercentVolume) {});
MediaObject.method('secondsToString', function (iSeconds)
{
	var sOutput = "";
	var iHours = 0;
	while (iSeconds > 60 * 60)
	{
		iHours++;
		iSeconds = iSeconds - 60 * 60;
	}
	if (iHours > 0)
	{
		sOutput = iHours + ":";
	}

	var iMinutes = 0;
	while (iSeconds > 60)
	{
		iMinutes++;
		iSeconds = iSeconds - 60;
	}

	if (iHours > 0 && iMinutes < 10)
	{
		iMinutes = "0" + iMinutes;
	}

	sOutput = sOutput + iMinutes + ":";

	if (iSeconds < 10)
	{
		iSeconds = "0" + iSeconds;
	}

	return sOutput + iSeconds;
});

MediaObject.method('getDurationString', function () 
{
	return this.secondsToString(this.getDuration());
});

MediaObject.method('getDuration', function () { return 0; });
MediaObject.method('getPositionString', function ()
{
	return this.secondsToString(this.getPosition());
});

MediaObject.method('getPosition', function () { return 0; });
MediaObject.method('fullScreen', function() {});
MediaObject.method('displayFullScreenWarning', function() 
{
	var cookies = document.cookie.split(";");
	for (var i = 0; i < cookies.length; i++)
	{
		var chunk = cookies[i].split("=");
		if (chunk[0] == "__mp_fs_cookie" && chunk[1] == "seen")
		{
			return false;
		}
	}

	var new_cookie = '__mp_fs_cookie=seen;';
	document.cookie = new_cookie + document.cookie;

	return true;
});

MediaObject.method('getStatusString', function() { return ''; });
MediaObject.method('registerMediaEndCallback', function(fCallback) {});
MediaObject.method('featureSupported', function(sFeature) { return false; });
/**** END MEDIA OBJECT BASE CLASS ****/

/**** WINDOWS MEDIA PLAYER OBJECT CLASS ****/
function WMPObject(sDivId, iWidth, iHeight, iSource)
{
	// Test for IE vs. Netscape/Firefox
	if (!window.ActiveXObject || !new window.ActiveXObject("WMPlayer.OCX.7"))
	{
		// non windows
		return new WMPObject_netscape(sDivId, iWidth, iHeight, iSource);
	}
	this.constructor(sDivId, iWidth, iHeight, iSource);
}

WMPObject.inherits(MediaObject);
WMPObject.method('showPlayer', function() 
{
	this.div.innerHTML = '<object name="__media_player" id="__media_player" width="' + this.width + '"' +
			     ' height="' + this.height + '" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"' +
			     ' type="application/x-oleobject"><param name="autoStart" value="True" />' +
			     ' <param name="uiMode" value="none" />' + 
			     '</object>';
	this.player = document.getElementById('__media_player');

	if (this.player)
	{
		return true;
	}
	return false;
});

WMPObject.method('hidePlayer', function()
{
	this.div.innerHTML = '';
});

WMPObject.method('setContent', function(sContentUrl) 
{
	if (this.player)
	{
		this.player.URL = sContentUrl;
		return true;
	}
	return false;	
});

WMPObject.method('play', function () 
{
	if (this.player && this.player.Controls)
	{
		this.player.Controls.play();
		return true;
	}
	return false;
});

WMPObject.method('pause', function () 
{
	if (this.player && this.player.Controls)
	{
		this.player.Controls.pause();
		return true;
	}
	return false;
});

WMPObject.method('stop', function () 
{
	if (this.player && this.player.Controls)
	{
		this.player.Controls.stop();
		return true;
	}
	return false;
});

WMPObject.method('isPlaying', function()
{
	if (!this.player)
	{
		return false;
	}
	
	switch (this.player.playState)
	{
		case 3: // playing
		case 4: // ff
		case 5: // fr
		case 6: // buffering
		case 7: // waiting
		case 9: // loading next media
		case 11: // reconnecting
			return true;
	}
	return false;
});

WMPObject.method('mute', function (bMute) 
{
	if (this.mute.arguments.length == 0)
	{
		if (this.player && this.player.Settings)
		{
			return this.player.Settings.Mute;
		}
	}

	if (this.player && this.player.Settings)
	{
		var bMuteCurrent = this.player.Settings.Mute;
		this.player.Settings.Mute = bMute;
		return bMuteCurrent;
	}
	return false;
});

WMPObject.method('setVolume', function (iPercentVolume) 
{
	if (this.player && this.player.Settings)
	{
		this.player.Settings.volume = iPercentVolume;
		return true;
	}
	return false;
});

WMPObject.method('getDuration', function () 
{ 
	if (this.player && this.player.currentMedia)
	{
		return Math.round(this.player.currentMedia.duration);
	}
	return 0;
});

WMPObject.method('getPosition', function () 
{ 
	if (this.player && this.player.Controls)
	{
		return Math.round(this.player.Controls.currentPosition);
	}
	return 0;
});

WMPObject.method('fullScreen', function() 
{
	switch (this.player.playState)
	{
		case 6: // buffering
		case 7: // waiting
		case 9: // loading next media
			alert("Video must be playing to use full screen mode.");
			return false;
	}
	if (this.player)
	{
		var handler = window.onerror;
		window.onerror = function() 
		{
			alert("Could not play in full screen.");
			return true;
		};

		if (this.displayFullScreenWarning())
		{
			alert("Press the ESC key to return from full screen mode");
		}
		this.player.fullScreen = true;

		window.onerror = handler;
	}
});

WMPObject.method('getStatusString', function() 
{ 
	if (this.player)
	{	
		switch(this.player.playState)
		{
			case 0: return "";
			case 1: 
			case 8: return "Stopped";
			case 2: return "Paused";
			case 10: return "Ready";
			case 3: return "Playing..";
			case 4: return "Fast Forward..";
			case 5: return "Fast Reverse..";
			case 6: return "Buffering..";
			case 7: return "Waiting..";
			case 9: return "Loading Next Media..";
			case 11: return "Reconnecting..";
		}
	}
	return "";
});

WMPObject.method('registerMediaEndCallback', function(fCallback) 
{
	if (this.player)
	{
		window.__wmp_ie_ps_callback = fCallback;
		this.player.attachEvent('PlayStateChange', function(newState) 
		{ 
			if (newState == 8)
			{
				window.__wmp_ie_ps_callback();
			}
			return true;
		});
		return true;
	}
	return false;
});

WMPObject.method('featureSupported', function(sFeature) 
{ 
	return true;
});
/**** END WINDOWS MEDIA PLAYER OBJECT CLASS ****/

/**** WINDOWS MEDIA PLAYER OBJECT (NS) CLASS ****/
function WMPObject_netscape(sDivId, iWidth, iHeight, iSource)
{
	this.constructor(sDivId, iWidth, iHeight, iSource);

	this.playing = true;
	this.source  = iSource;
}

WMPObject_netscape.inherits(MediaObject);
WMPObject_netscape.method('_embed_player', function()
{
	document.getElementById('controls_div').style.display = 'none';
	this.div.innerHTML = '<object type="application/x-ms-wmp"' +
			     ' data="' + this.source + '" id="__media_player" classid="CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6"' +
			     ' codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"' +
			     ' name="__media_player" width="' + this.width + '" height="' + this.height + '">' +
			     ' <param name="URL" value="' + this.source + '" />' +
			     ' <param name="uiMode" value="none" />' +

			     '<embed type="application/x-mplayer2"' +
			     ' pluginspage = "http://www.microsoft.com/Windows/MediaPlayer/"' +
			     ' src="' + this.source + '" align="middle"' +
			     ' width="' + this.width + '"' +
			     ' height="' + this.height + '"' +
			     ' showstatusbar="true"' +
			     ' showcontrols="true">' +
			     '</embed>' +
			     '</object>';
	this.player = document.getElementById('__media_player');
});

WMPObject_netscape.method('showPlayer', function() 
{
	this._embed_player();

	if (this.player)
	{
		return true;
	}
	return false;
});

WMPObject_netscape.method('hidePlayer', function()
{
	this.div.innerHTML = '';
});

WMPObject_netscape.method('setContent', function(sContentUrl) 
{
	this.source = sContentUrl;
	this.player.URL = sContentUrl;

	if (this.playing)
	{
		if (!this.player)
		{
			return false;
		}
	}
	return true;	
});

WMPObject_netscape.method('play', function () 
{
	if (this.player)
	{
		this.player.controls.play();
		return true;
	}
	return false;
});

WMPObject_netscape.method('pause', function () 
{
	if (this.player)
	{
		this.player.controls.pause();
		return true;
	}
	return false;
});

WMPObject_netscape.method('stop', function () 
{
	if (this.player)
	{
		this.player.controls.stop();
		return true;
	}
	return false;
});

WMPObject_netscape.method('isPlaying', function()
{
	if (!this.player)
	{
		return false;
	}
	
	switch (this.player.playState)
	{
		case 3: // playing
		case 4: // ff
		case 5: // fr
		case 6: // buffering
		case 7: // waiting
		case 9: // loading next media
		case 11: // reconnecting
			return true;
	}
	return false;
});

WMPObject_netscape.method('mute', function (bMute) 
{
	if (this.mute.arguments.length == 0)
	{
		if (this.player && this.player.settings)
		{
			return this.player.settings.mute;
		}
	}

	if (this.player && this.player.settings)
	{
		var bMuteCurrent = this.player.settings.mute;
		this.player.settings.mute = bMute;
		return bMuteCurrent;
	}
	return false;
});

WMPObject_netscape.method('setVolume', function (iPercentVolume) 
{
	if (this.player && this.player.settings)
	{
		this.player.settings.volume = iPercentVolume;
		return true;
	}
	return false;
});

WMPObject_netscape.method('getDuration', function () 
{ 
	if (this.player && this.player.currentMedia)
	{
		return Math.round(this.player.currentMedia.duration);
	}
	return 0;
});

WMPObject_netscape.method('getPosition', function () 
{ 
	if (this.player && this.player.controls)
	{
		return Math.round(this.player.controls.currentPosition);
	}
	return 0;
});

WMPObject_netscape.method('fullScreen', function() 
{
	switch (this.player.playState)
	{
		case 6: // buffering
		case 7: // waiting
		case 9: // loading next media
			alert("Video must be playing to use full screen mode.");
			return false;
	}
	if (this.player)
	{
		var handler = window.onerror;
		window.onerror = function() 
		{
			alert("Could not play in full screen.");
			return true;
		};

		if (this.displayFullScreenWarning())
		{
			alert("Press the ESC key to return from full screen mode");
		}
		this.player.fullScreen = true;

		window.onerror = handler;
	}
});

WMPObject_netscape.method('getStatusString', function() 
{ 
	if (this.player)
	{	
		switch(this.player.playState)
		{
			case 0: return "";
			case 1: 
			case 8: return "Stopped";
			case 2: return "Paused";
			case 10: return "Ready";
			case 3: return "Playing..";
			case 4: return "Fast Forward..";
			case 5: return "Fast Reverse..";
			case 6: return "Buffering..";
			case 7: return "Waiting..";
			case 9: return "Loading Next Media..";
			case 11: return "Reconnecting..";
		}
	}
	return "";
});

WMPObject_netscape.method('registerMediaEndCallback', function(fCallback) 
{
	return false;
});

WMPObject_netscape.method('featureSupported', function(sFeature) 
{ 
	return true;
});
/**** END WINDOWS MEDIA PLAYER OBJECT (NS) CLASS ****/

/**** REAL MEDIA PLAYER OBJECT CLASS ****/
function RealObject(sDivId, iWidth, iHeight)
{
	this.constructor(sDivId, iWidth, iHeight);
}

RealObject.inherits(MediaObject);
RealObject.method('showPlayer', function() 
{
	// Test for IE vs. Netscape/Firefox
	try
	{
		new window.ActiveXObject("rmocx.RealPlayer G2 Control.1");
		this.div.innerHTML = '<object name="__real_player" id="__real_player" width="' + this.width + '"' +
		                     ' height="' + this.height + '" classid="CLSID:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"' +
		                     ' type="application/x-oleobject"><param name="CONTROLS" value="ImageWindow" />' +
		                     '<param name="CONSOLE" value="__rp_console" />' +
		                     '</object>';
		this.player = document.getElementById('__real_player');
	}
	catch(exception)
	{
		this.div.innerHTML = '<embed src="" name="__real_player" id="__real_player" width="' + this.width + '"' +
		                     ' controls="imagewindow" console="__rp_console" height="' + this.height +
		                     '" type="audio/x-pn-realaudio-plugin">' +
		                     '</embed>';
		this.player = document.getElementById('__real_player');

		// Just because this.player exists, does not necessarily mean that the user
		// has the necessary plugin installed.  We will check to see if a RealPlayer
		// function exists.
		if (!this.player.GetPlayState)
		{
			this.player = false;
		}
	}

	if (this.player)
	{
		return true;
	}
	else
	{
		this.div.innerHTML = '<p class="real_media_message">RealPlayer is needed to view this video. Please visit <a href="http://www.real.com/" target="_blank" class="real_media_href">real.com</a> to download the free player.</p>';
	}
	return false;
});

RealObject.method('hidePlayer', function()
{
	this.div.innerHTML = '';
});

RealObject.method('setContent', function(sContentUrl) 
{
	if (this.player)
	{
		this.player.SetSource(sContentUrl);
		return true;
	}
	return false;	
});

RealObject.method('play', function () 
{
	if (this.player)
	{
		this.player.DoPlay();
		return true;
	}
	return false;
});

RealObject.method('pause', function () 
{
	if (this.player)
	{
		this.player.DoPause();
		return true;
	}
	return false;
});

RealObject.method('stop', function () 
{
	if (this.player)
	{
		this.player.DoStop();
		return true;
	}
	return false;
});

RealObject.method('isPlaying', function()
{
	if (!this.player)
	{
		return false;
	}
	
	switch (this.player.GetPlayState())
	{
		case 1: // contacting
		case 2: // buffering
		case 3: // playing
		case 5: // seeking
			return true;
	}
	return false;
});

RealObject.method('mute', function (bMute) 
{
	if (this.mute.arguments.length == 0)
	{
		if (this.player)
		{
			return this.player.GetMute();
		}
	}

	if (this.player)
	{
		var bMuteCurrent = this.player.GetMute();
		this.player.SetMute(bMute);
		return bMuteCurrent;
	}
	return false;
});

RealObject.method('setVolume', function (iPercentVolume) 
{
	if (this.player)
	{
		this.player.SetVolume(iPercentVolume);
		return true;
	}
	return false;
});

RealObject.method('getDuration', function () 
{ 
	if (this.player && this.isPlaying())
	{
		return Math.round(this.player.GetLength() / 1000);
	}
	return 0;
});

RealObject.method('getPosition', function () 
{ 
	if (this.player && this.isPlaying())
	{
		return Math.round(this.player.GetPosition() / 1000);
	}
	return 0;
});

RealObject.method('fullScreen', function() 
{
	if (this.player && this.isPlaying())
	{
		var handler = window.onerror;
		window.onerror = function() 
		{
			alert("Could not play in full screen.");
			return true;
		};

		if (this.displayFullScreenWarning())
		{
			alert("Press the ESC key to return from full screen mode");
		}
		this.player.SetFullScreen();

		window.onerror = handler;
	}
	else
	{
		alert("Video must be playing to use full screen mode.");
	}
});

RealObject.method('getStatusString', function() 
{ 
	if (this.player)
	{	
		switch(this.player.GetPlayState())
		{
			case 0: return "Stopped";
			case 1: return "Contacting..";
			case 2: return "Buffering..";
			case 3: return "Playing..";
			case 4: return "Paused";
			case 5: return "Seeking..";
		}
	}
	return "";
});

RealObject.method('registerMediaEndCallback', function(fCallback) 
{
	if (this.player)
	{
		window.__wmp_ie_ps_callback = fCallback;
		if (this.player.attachEvent)
		{
			this.player.attachEvent('OnClipClosed', function() 
			{ 
				window.__wmp_ie_ps_callback();
				return true;
			});
		}
		return true;
	}
	return false;
});

RealObject.method('featureSupported', function(sFeature) 
{ 
	return true;
});
/**** END REAL MEDIA PLAYER OBJECT CLASS ****/

/**** QUICKTIME PLAYER OBJECT CLASS ****/
function QTObject(sDivId, iWidth, iHeight)
{
	this.constructor(sDivId, iWidth, iHeight);
}

QTObject.inherits(MediaObject);
QTObject.method('showPlayer', function() 
{
	this.div.innerHTML = '<object name="__qt_player" id="__qt_player" width="' + this.width + '"' +
			     ' height="' + this.height + '" classid="CLSID:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"' +
			     ' codebase="http://www.apple.com/qtactivex/qtplugin.cab">' +
			     '<param name="autoplay" value="false" /><param name="controller" value="false" />' +
			     '</object>';

	this.player = document.getElementById('__qt_player');
	this.player.SetResetPropertiesOnReload(false);
	this.player.SetIsLooping(false);
	window.__qt_object = this;
	window.__wm_timer_object.addTimerCallback(this.statusTimer);

	this.playing = false;
	this.status = "Waiting..";
	this.paused = false;

	if (this.player)
	{
		return true;
	}
	return false;
});

QTObject.method('hidePlayer', function()
{
	window.__wm_timer_object.removeTimerCallback(this.statusTimer);
	this.div.innerHTML = '';
});

QTObject.method('statusTimer', function()
{
	obj = window.__qt_object;
	if (obj.playing && !obj.paused)
	{
		switch(obj.player.GetPluginStatus())
		{
			case "Waiting":
			case "Loading":
				obj.status = "Buffering..";
				break;
			case "Playable":
				switch (obj.status)
				{
					case "Waiting..":
					case "Stopped..":
						obj.status = "Buffering (25%)..";
						return;
					case "Buffering (25%)..":
						obj.status = "Buffering (50%)..";
						return;
					case "Buffering (50%)..":
						obj.status = "Buffering (75%)..";
						return;
					case "Buffering (75%)..":
						obj.status = "Buffering (100%)..";
						return;
					case "Buffering (100%)..":
					// fall through
				}
				// fall through
			case "Complete":
				if (obj.mediaEnd && obj.player.GetDuration() == obj.player.GetTime())
				{
					obj.playing = false;
					obj.status = "Stopped";
					obj.mediaEnd();
				}
				else
				{
					obj.player.SetAutoPlay(false);
					obj.player.Play();
					obj.status = "Playing..";
				}
				break;
			default:
				obj.status = "Stopped";
		}
	}
	else if (obj.paused)
	{
		obj.status = "Paused";
	}
	else
	{
		obj.status = "Stopped";
	}
});

QTObject.method('setContent', function(sContentUrl) 
{
	if (this.player)
	{
		this.playing = false;
		this.paused = false;
		this.player.SetURL(sContentUrl);
		return true;
	}
	return false;	
});

QTObject.method('play', function () 
{
	if (this.player)
	{
		this.playing = true;
		this.paused = false;
		if (this.player.GetPluginStatus() == "Playable" ||
		    this.player.GetPluginStatus() == "Complete")
		{
			this.player.Play();
		}
		else
		{
			this.player.SetAutoPlay(true); 
		}

		return true;
	}
	return false;
});

QTObject.method('pause', function () 
{
	if (this.player && this.playing)
	{
		this.paused = true;
		this.playing = false;
		this.player.SetRate(0);
		return true;
	}
	return false;
});

QTObject.method('stop', function () 
{
	if (this.player);
	{
		this.playing = false;
		this.paused = false;
		this.player.Stop();
		this.player.Rewind();
		return true;
	}
	return false;
});

QTObject.method('isPlaying', function()
{
	return this.playing;
});

QTObject.method('mute', function (bMute) 
{
	if (this.mute.arguments.length == 0)
	{
		if (this.player)
		{
			return this.player.GetVolume() < 0;
		}
	}

	if (this.player)
	{
		var iCurrentVolume = this.player.GetVolume();
		if (this.player.GetVolume() > 0)
		{
			this.prev_mute_volume = this.player.GetVolume();
			this.player.SetVolume(-1);
		}
		else
		{
			this.player.SetVolume(this.prev_mute_volume);
		}
		return iCurrentVolume < 0;
	}
	return false;
});

QTObject.method('setVolume', function (iPercentVolume) 
{
	if (this.player)
	{
		var fPct = iPercentVolume / 100;
		this.player.SetVolume(Math.floor(255 * fPct)); 
		return true;
	}
	return false;
});

QTObject.method('getDuration', function () 
{ 
	if (!this.player)
	{
		return 0;
	}

	switch (this.player.getPluginStatus())
	{
		case "Playable":
		case "Complete":
			if (this.player && this.playing)
			{
				return Math.round(this.player.GetDuration() / 1000);
			}
	}
	return 0;
});

QTObject.method('getPosition', function () 
{ 
	if (!this.player)
	{
		return 0;
	}

	switch (this.player.getPluginStatus())
	{
		case "Playable":
		case "Complete":
			if (this.player && this.playing)
			{
				return Math.round(this.player.GetTime() / 1000);
			}
	}
	return 0;
});

QTObject.method('fullScreen', function() 
{
	return false; // XXX is this supported?
});

QTObject.method('getStatusString', function() 
{ 
	return this.status;
});

QTObject.method('registerMediaEndCallback', function(fCallback) 
{
	if (this.player)
	{
		this.mediaEnd = fCallback;
		return true;
	}
	return false;
});

QTObject.method('featureSupported', function(sFeature) 
{ 
	switch(sFeature)
	{
		case "play":
		case "pause":
		case "stop":
		case "position":
			return true;
	}
	return false;
});
/**** END QUICKTIME PLAYER OBJECT CLASS ****/

/**** OBJECT FACTORY CLASS ****/
function ObjectFactory()
{
}

ObjectFactory.method('createObjectFromMIME', function(sMimeType, sDivId, iWidth, iHeight, iSource)
{
	switch(sMimeType)
	{
		case 'video/mpeg':
		case 'video/x-ms-wmv':
		case 'video/x-ms-asf':
		case 'video/x-msvideo':
			return new WMPObject(sDivId, iWidth, iHeight, iSource);
		case 'application/vnd.rn-realmedia':
		case 'application/x-pn-realvideo':
		case 'application/x-pn-realaudio':
			return new RealObject(sDivId, iWidth, iHeight);
		case 'video/x-flv':
			return new FLVObject(sDivId, iWidth, iHeight);
		case 'video/quicktime':
			return new QTObject(sDivId, iWidth, iHeight);
	}
	return false;
});

ObjectFactory.method('supportedType', function(sMimeType)
{
	return (this.createObjectFromMIME(sMimeType, '', 0, 0) != false);
});

/**** END OBJECT FACTORY CLASS ****/


/**** MEDIA PLAYER CLASS ****/
function MediaPlayer(sDivId, iWidth, iHeight)
{
	// standard stuff
	this.div = sDivId;
	this.width = iWidth;
	this.height = iHeight;
	this.objectFactory = new ObjectFactory();
	this.currentObject = false;
	this.currentMimeType = false;

	// timer stuff
	window.__wm_timer_object = this;
	setInterval(this._timer, 500);
	this.timerCallbacks = new Array();

	// playlist stuff
	this.using_playlist = false;
	this.playlist = new Array(); // 0 - tagID, 1 - mimeType, 2 - mediaURL, 3 - Title
	this.current_index = 0;
	this.mediaChangeCallbacks = new Array();
	this.mimeCallbacks = new Array();

	// GUI support stuff
	this.volumeImg = false;
	this.volumeImages = Array();
	this.playImg = false;
	this.playImages = Array(); // 0 - play, 1 - pause, 2 - stop
	this.stopImg = false;
	this.stopImages = Array(); // 0 - stop, 1 - no stop
	this.skipBackImg = false;
	this.skipBackImages = Array(); // 0 - stop, 1 - no stop
	this.skipForwardImg = false;
	this.skipForwardImages = Array(); // 0 - stop, 1 - no stop
	this.muteImg = false;
	this.muteImages = Array(); // 0 - mute off, 1 - mute on
	this.statusDiv = false;
	this.positionDiv = false;
}

MediaPlayer.method('featureSupported', function(sFeature)
{
	if (!this.currentObject)
	{
		return false;
	}

	return this.currentObject.featureSupported(sFeature);
});

MediaPlayer.method('_timer', function()
{
	// Media Player specific actions...
	if (__wm_timer_object.playImg && __wm_timer_object.currentObject)
	{
		// they gave us play/pause/stop images.. keep them
		// up to date
		if (__wm_timer_object.currentObject.isPlaying())
		{
			if (__wm_timer_object.currentObject.featureSupported('pause'))
			{
				if (__wm_timer_object.playImg.src != __wm_timer_object.playImages[1].src)
				{
					__wm_timer_object.playImg.src = __wm_timer_object.playImages[1].src;
					__wm_timer_object.playImg.alt = "Pause";
				}
			}
			else // pause is not supported.. show stop
			{
				if (__wm_timer_object.playImg.src != __wm_timer_object.playImages[2].src)
				{
					__wm_timer_object.playImg.src = __wm_timer_object.playImages[2].src;
					__wm_timer_object.playImg.alt = "Stop";
				}
			}
		}
		else
		{
			if (__wm_timer_object.playImg.src != __wm_timer_object.playImages[0].src)
			{
				__wm_timer_object.playImg.src = __wm_timer_object.playImages[0].src;
				__wm_timer_object.playImg.alt = "Play";
			}
		}
	}
	if (__wm_timer_object.stopImg && __wm_timer_object.currentObject)
	{
		// they gave us stop/nostop images.. keep them
		// up to date
		if (__wm_timer_object.currentObject.isPlaying())
		{
			if (__wm_timer_object.stopImg.src != __wm_timer_object.stopImages[0].src)
			{
				__wm_timer_object.stopImg.src = __wm_timer_object.stopImages[0].src;
				__wm_timer_object.stopImg.alt = "Stop";
			}
		}
		else
		{
			if (__wm_timer_object.stopImg.src != __wm_timer_object.stopImages[1].src)
			{
				__wm_timer_object.stopImg.src = __wm_timer_object.stopImages[1].src;
				__wm_timer_object.stopImg.alt = ""; // not playing, cannot stop
			}
		}
	}
	if (__wm_timer_object.skipBackImg && __wm_timer_object.currentObject)
	{
		// they gave us skip back images.. keep them up to date
		if (__wm_timer_object.current_index > 0 && __wm_timer_object.using_playlist)
		{
			if (__wm_timer_object.skipBackImg.src != __wm_timer_object.skipBackImages[0].src)
			{
				__wm_timer_object.skipBackImg.src = __wm_timer_object.skipBackImages[0].src;
			}
			__wm_timer_object.skipBackImg.alt = "Prev: " + __wm_timer_object.playlist[__wm_timer_object.current_index - 1][3];
		}
		else 
		{
			if (__wm_timer_object.skipBackImg.src != __wm_timer_object.skipBackImages[1].src)
			{
				__wm_timer_object.skipBackImg.src = __wm_timer_object.skipBackImages[1].src;
			}
			__wm_timer_object.skipBackImg.alt = "";
		}
	}
	if (__wm_timer_object.skipForwardImg && __wm_timer_object.currentObject)
	{
		// they gave us skip forward images.. keep them up to date
		if (__wm_timer_object.current_index < __wm_timer_object.playlist.length - 1 && __wm_timer_object.using_playlist)
		{
			if (__wm_timer_object.skipForwardImg.src != __wm_timer_object.skipForwardImages[0].src)
			{
				__wm_timer_object.skipForwardImg.src = __wm_timer_object.skipForwardImages[0].src;
			}
			__wm_timer_object.skipForwardImg.alt = "Next: " + __wm_timer_object.playlist[__wm_timer_object.current_index + 1][3];
		}
		else
		{
			if (__wm_timer_object.skipForwardImg.src != __wm_timer_object.skipForwardImages[1].src)
			{
				__wm_timer_object.skipForwardImg.src = __wm_timer_object.skipForwardImages[1].src;
			}
			__wm_timer_object.skipForwardImg.alt = "";
		}
	}
	if (__wm_timer_object.muteImg && __wm_timer_object.currentObject)
	{
		// they gave us mute images.. we need to keep them up to
		// date.
		var bMute = __wm_timer_object.currentObject.mute();

		if (!__wm_timer_object.currentObject.featureSupported('mute'))
		{
			__wm_timer_object.muteImg.style.display = 'none';
		}
		else if (bMute)
		{
			__wm_timer_object.muteImg.style.display = 'block';
			if (__wm_timer_object.muteImg.src != __wm_timer_object.muteImages[1].src)
			{
				__wm_timer_object.muteImg.src = __wm_timer_object.muteImages[1].src;
			}
		}
		else
		{
			__wm_timer_object.muteImg.style.display = 'block';
			if (__wm_timer_object.muteImg.src != __wm_timer_object.muteImages[0].src)
			{
				__wm_timer_object.muteImg.src = __wm_timer_object.muteImages[0].src;
			}
		}
	}	
	if (__wm_timer_object.statusDiv && __wm_timer_object.currentObject)
	{
		var status = __wm_timer_object.currentObject.getStatusString();
		if ((status == 'Playing..' || !__wm_timer_object.currentObject.featureSupported('status')) && __wm_timer_object.using_playlist && 
		    __wm_timer_object.current_index + 1 < __wm_timer_object.playlist.length)
		{
			status = "Next: " + __wm_timer_object.playlist[__wm_timer_object.current_index + 1][3];
			if (__wm_timer_object.currentObject.featureSupported('mediaCallback'))
			{
				status = "Up " + status; 
			}
		}
		__wm_timer_object.statusDiv.innerHTML = status;
	}
	if (__wm_timer_object.positionDiv && __wm_timer_object.currentObject)
	{
		if (!__wm_timer_object.currentObject.featureSupported('position'))
		{
			__wm_timer_object.positionDiv.innerHTML = '';
		}
		else
		{
			var sCurrentPos = __wm_timer_object.currentObject.getPositionString();
			if (sCurrentPos == "")
			{
				sCurrentPos = "00:00:00" 
			}
			var sDuration = __wm_timer_object.currentObject.getDurationString();
			__wm_timer_object.positionDiv.innerHTML = sCurrentPos + " / " + sDuration;
		}
	}

	// call all other timer events
	var len = window.__wm_timer_object.timerCallbacks.length;
	while (len--)
	{
		window.__wm_timer_object.timerCallbacks[len]();
	}
});

MediaPlayer.method('addTimerCallback', function(fCallback)
{
	this.timerCallbacks[this.timerCallbacks.length] = fCallback;
});

MediaPlayer.method('removeTimerCallback', function(fCallback)
{
	var len = this.timerCallbacks.length;
	while (len--)
	{
		if (fCallback = this.timerCallbacks[len])
		{
			this.timerCallbacks.splice(len, 1);
		}
	}
});

MediaPlayer.method('setStatusDiv', function(sDivID)
{
	this.statusDiv = document.getElementById(sDivID);
	return this.statusDiv != false;
});	

MediaPlayer.method('setPositionDiv', function(sDivID)
{
	this.positionDiv = document.getElementById(sDivID);
	return this.positionDiv != false;
});	

MediaPlayer.method('onMediaEnd', function()
{
	if (__wm_timer_object.using_playlist)
	{
		window.__wm_timer_object.skipForward();
	}
});

MediaPlayer.method('setMedia', function(sMimeType, sURL)
{
	if (!this.objectFactory.supportedType(sMimeType))
	{
		alert("Unable to find suitable player for selected video type " + sMimeType);
		return false;
	}
	
	// play single media item
	this.using_playlist = false;
	this.currentMimeType = sMimeType;
	this.source = sURL;
	this.currentObject = this.objectFactory.createObjectFromMIME(sMimeType, this.div, this.width, this.height, this.source);
	this.currentObject.showPlayer();
	this.currentObject.registerMediaEndCallback(this.onMediaEnd);
	this.currentObject.setContent(sURL);
});

MediaPlayer.method('addToPlayList', function(sTag, sMimeType, sURL, sTitle)
{
	// setup a playlist to play.  Playlist does not have to be all the same
	// player type, which is cool.

	if (!this.objectFactory.supportedType(sMimeType))
	{
		alert("Unable to find suitable player for selected video type " + sMimeType);
		return false;
	}

	if (this.playlist.length == 0)
	{
		this.using_playlist = true;
	}

	var newMedia = new Array();
	newMedia[0] = sTag;
	newMedia[1] = sMimeType;
	newMedia[2] = sURL;
	newMedia[3] = sTitle;
	this.playlist[this.playlist.length] = newMedia;

	if (this.playlist.length == 1)
	{
		this.skipTo(0);
	}
});

MediaPlayer.method('skipTo', function(iIndex)
{
	if (!this.playlist[iIndex])
	{
		return false;
	}

	if (this.currentObject && this.currentObject.isPlaying())
	{
		this.currentObject.stop();
	}
	
	if (this.currentObject)
	{
		this.currentObject.hidePlayer();
	}

	var newPlayer = false;
	if (this.currentMimeType != this.playlist[iIndex][1])
	{
		this.currentMimeType = this.playlist[iIndex][1];
		this.currentObject = this.objectFactory.createObjectFromMIME(this.currentMimeType, this.div, 
		                                                             this.width, this.height, this.source);
		var newPlayer = true;
	}

	this.currentObject.showPlayer();
	this.currentObject.registerMediaEndCallback(this.onMediaEnd);
	this.currentObject.setContent(this.playlist[iIndex][2]);
	this.current_index = iIndex;

	if (newPlayer && this.mimeCallbacks.length > 0)
	{
		var len = this.mimeCallbacks.length;
		while (len--)
		{
			this.mimeCallbacks[len](this.currentMimeType);
		}
	}
		
	
	return true;
});

MediaPlayer.method('setFirstItem', function(sTag)
{
	if (!this.using_playlist || this.playlist.length == 0)
	{
		return false;
	}
	
	var len = this.playlist.length;
	// re-order playlist to start with this sTag
	var temp_playlist = new Array();
	var start_item = -1;
	for (var cur_item; start_item < len; start_item++)
	{
		if (this.playlist[start_item][0] == sTag || temp_playlist.length > 0)
		{
			if (start_item == -1)
			{
				start_item = cur_item;
			}
			temp_playlist[temp_playlist.length] = this.playlist[start_item];
		}
	}
	for (var cur_item = 0; cur_item < start_item; cur_item++)
	{
		temp_playlist[temp_playlist.length] = this.playlist[cur_item];
	}
	this.playlist = temp_playlist;

	return this.skipTo(0);
});

MediaPlayer.method('play', function()
{
	return this.currentObject.play();
});

MediaPlayer.method('pause', function()
{
	return this.currentObject.pause();
});

MediaPlayer.method('playOrPause', function()
{
	if (this.currentObject.isPlaying())
	{
		if (this.currentObject.featureSupported('pause'))
		{
			this.pause();
			this._timer();
		}
		else
		{
			this.stop();
			this._timer();
		}
	}
	else
	{
		this.play();
		this._timer();
	}
});

MediaPlayer.method('stop', function()
{
	return this.currentObject.stop();
});

MediaPlayer.method('setPlayPauseImages', function(sImgID, sPlaySrc, sPauseSrc, sStopSrc)
{
	this.playImg = document.getElementById(sImgID);
	if (!this.playImg)
	{
		return false;
	}

	this.playImages[0] = new Image();
	this.playImages[0].src = sPlaySrc;

	this.playImages[1] = new Image();
	this.playImages[1].src = sPauseSrc;

	this.playImages[2] = new Image();
	this.playImages[2].src = sStopSrc;

	return true;
});

MediaPlayer.method('setStopImages', function(sImgID, sStopSrc, sNoStopSrc)
{
	this.stopImg = document.getElementById(sImgID);
	if (!this.stopImg)
	{
		return false;
	}

	this.stopImages[0] = new Image();
	this.stopImages[0].src = sStopSrc;

	this.stopImages[1] = new Image();
	this.stopImages[1].src = sNoStopSrc;

	return true;
});

MediaPlayer.method('setSkipBackImage', function(sImgID, sSkipSrc, sNoSkipSrc)
{
	this.skipBackImg = document.getElementById(sImgID);
	if (!this.skipBackImg)
	{
		return false;
	}

	this.skipBackImages[0] = new Image();
	this.skipBackImages[0].src = sSkipSrc;

	this.skipBackImages[1] = new Image();
	this.skipBackImages[1].src = sNoSkipSrc;

	return true;
});

MediaPlayer.method('setSkipForwardImage', function(sImgID, sSkipSrc, sNoSkipSrc)
{
	this.skipForwardImg = document.getElementById(sImgID);
	if (!this.skipForwardImg)
	{
		return false;
	}

	this.skipForwardImages[0] = new Image();
	this.skipForwardImages[0].src = sSkipSrc;

	this.skipForwardImages[1] = new Image();
	this.skipForwardImages[1].src = sNoSkipSrc;

	return true;
});

MediaPlayer.method('fastForward', function()
{
	return this.currentObject.fastForward();
});

MediaPlayer.method('fastReverse', function()
{
	return this.currentObject.fastReverse();
});

MediaPlayer.method('addMediaChangeCallback', function(fCallback)
{
	this.mediaChangeCallbacks[this.mediaChangeCallbacks.length] = fCallback;
});

MediaPlayer.method('addMimeChangeCallback', function(fCallback)
{
	this.mimeCallbacks[this.mimeCallbacks.length] = fCallback;
});

MediaPlayer.method('doMediaChangeCallbacks', function(sOldTag, sNewTag)
{
	var len = this.mediaChangeCallbacks.length;
	while(len--)
	{
		if (!this.mediaChangeCallbacks[len](sOldTag, sNewTag))
		{
			return false;
		}
	}
	return true;
});

MediaPlayer.method('skipForward', function()
{
	var success = this.skipTo(this.current_index + 1) && this.play();
	return success && this.doMediaChangeCallbacks(this.playlist[this.current_index - 1][0],
	                                              this.playlist[this.current_index][0]);
});

MediaPlayer.method('skipBackward', function()
{
	var success = this.skipTo(this.current_index - 1) && this.play();
	return success && this.doMediaChangeCallbacks(this.playlist[this.current_index + 1][0],
	                                              this.playlist[this.current_index][0]);
});

MediaPlayer.method('fullScreen', function()
{
	return this.currentObject.fullScreen();
});

MediaPlayer.method('mute', function(bMute)
{
	if (this.mute.arguments.length == 0)
	{
		return this.currentObject.mute(!this.currentObject.mute());
	}
	return this.currentObject.mute(bMute);
});

MediaPlayer.method('setMuteImages', function(sImgID, sMuteOffSrc, sMuteOnSrc)
{
	this.muteImg = document.getElementById(sImgID);
	if (!this.muteImg)
	{
		return false;
	}
	
	this.muteImages[0] = new Image();
	this.muteImages[0].src = sMuteOffSrc;

	this.muteImages[1] = new Image();
	this.muteImages[1].src = sMuteOnSrc;

	return true;
});

MediaPlayer.method('setVolume', function(iLevel, iMaxLevel)
{
	iPctLevel = Math.floor((iLevel / iMaxLevel) * 100);

	if (this.volumeImg)
	{
		this.volumeImg.src = this.volumeImages[iLevel].src;
	}

	return this.currentObject.setVolume(iPctLevel);
});

MediaPlayer.method('setVolumeImages', function(/* var args: sImgId, img, img, img, ... */)
{
	var arguments = this.setVolumeImages.arguments;
	this.volumeImg = document.getElementById(arguments[0]);

	if (!this.volumeImg)
	{
		return false;
	}
	
	var len = arguments.length;
	for (var i = 1; i < len; i++)
	{
		this.volumeImages[i] = new Image();
		this.volumeImages[i].src = arguments[i];
	}

	return true;
});


/**** FLASH VIDEO OBJECT BASE CLASS ****/
// Global variables needed to allow passage of information between flash player and media player object.

var flash_com_uid = "undefined";  	// will get set to a random id for linking to the flash communication object.
var commandArray = new Array();		// holds any pending flash commands, which get sent to flash periodically.
var statusObject = new Object();	// holds values that flash sends back about the video file, like duration, position, which are updated on a regular basis.
var flashProxy;				// will be the flashProxy object for getting info RELIABLY from Flash.
var flashVolume = -10;			// holds the current flash player volume.
var loaded_flash_already = false;	// flag for determining if the flash player has been loaded yet.
var flash_lock;				// flag for letting Flash load before commands are sent from JS.
var isInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;

// Functions
function FLVObject_UpdateStatus(arg_object)
{	// Captures status information sent from Flash, puts it into the statusObject for the player to access.
	var arg_array = arg_object.split("+++");
	statusObject.duration = arg_array[0];
	statusObject.position = arg_array[1];
	statusObject.playstate = arg_array[2];
	if (statusObject.playstate == "ended")
	{
		FLVObject_mediaEnd();
	}
}

function FLVObject_Unlock ()
{	// This is sent from Flash - unlocks the flag to announce the Flash player is loaded and ready.
	flash_lock = false;
}

function FLVObject_Lock ()
{	// Sets the lock flag, which Flash will unlock when it's ready to accept commands.
	flash_lock = true;
}

function FLVObject_make_flash_calls ()
{	// This command is executed on an interval to send commands to Flash.
	if (commandArray.length > 0)
	{
		if (flash_lock == false)
		{
		commandArray.reverse();
		var callitem = commandArray.pop();
		commandArray.reverse();
		FLVObject_sendCommand(callitem[0]+"+++" + callitem[1]);
		}
	}
}

function FLVObject_sendCommand(args)
{	// Sends a command to Flash.
	var sendText = args;
	var flashid = 'flv_player';
	if (isInternetExplorer)
	{
		if (document.getElementById) 
		{
			document.getElementById(flashid).SetVariable("command_JS", sendText);
		} 
		else
		{
			document.flashid.SetVariable("command_JS", sendText);
		}
	} 
	else 
	{
			document[flashid].SetVariable("command_JS", sendText);
	}
}

function FLVObject(sDivId, iWidth, iHeight)
{	
	this.construct(sDivId, iWidth, iHeight);
}

FLVObject.method('construct', function(sDivId, iWidth, iHeight)
{
	this.div_id = sDivId;
	this.div    = (document.getElementById ? document.getElementById(sDivId) : document.sDivId);
	this.width  = iWidth;
	this.height = iHeight;
	this.uid = new Date().getTime();
	flash_com_uid = this.uid;
	var flashpath = doc_root + 'JavaScriptFlashGateway.swf';
	flashProxy = new FlashProxy(flash_com_uid, flashpath);
});

FLVObject.method('showPlayer', function() 
{
	statusObject.ismute = true;
	if (!loaded_flash_already)
 	{
		flash_lock = true;
		loaded_flash_already = true;
	}
	var flashplayersource = doc_root + "__flv_player.swf"; 
	var tag = new FlashTag(flashplayersource, this.width, this.height, '7,0,0,0'); 
	tag.setFlashvars('lcId=' + this.uid);
	tag.setId('flv_player');
	this.div.innerHTML = tag;
	var flashid = 'flv_player';
	if (isInternetExplorer)
	{
		this.player = (document.getElementById ? document.getElementById(flashid) : document.flashid);
	} else {
		this.player = document[flashid];
	}
	this.interval1 = setInterval(FLVObject_make_flash_calls, 430);  //CANNOT send commands to flash any quicker than this.  Otherwise one of the commands may not be received.
	if (this.player)
	{
		return true;
	}
	return false;
});

FLVObject.method('hidePlayer', function()
{
	clearInterval(this.interval1);
	commandArray = new Array(0);
	this.div.innerHTML = '';
	flash_lock = true;
});

FLVObject.method('setContent', function(sContentUrl) 
{
	if (this.player)
	{
		commandArray.push(['setContentURL', sContentUrl]);
		return true;
	}
	return false;	
});

FLVObject.method('play', function () 
{
	if (this.player)
	{	
		commandArray.push(['pauseResume', 0]);
		return true;
	}
	return false;
});

FLVObject.method('pause', function () 
{
	if (this.player)
	{
		commandArray.push(['pauseResume', 1]);
		return true;
	}
	return false;
});

FLVObject.method('stop', function () 
{
	if (this.player)
	{
		commandArray.push(['pauseResume', 2]);
		return true;
	}
	return false;
});

FLVObject.method('isPlaying', function()
{
	if (!this.player)
	{
		return false;
	}
	var playstate = statusObject.playstate;
	if (playstate == "playing")
	{
		return true;
	}
	
	return false;
});

FLVObject.method('mute', function (bMute) 
{
	if (this.mute.arguments.length == 0)
	{
		if (this.player)
		{
			var ismuted = !statusObject.ismute;
			return ismuted;
		}
	}

	if (this.player)
	{
		var ismuted = statusObject.ismute;
		commandArray.push(['muteSound', bMute]);
		statusObject.ismute = !ismuted;
		return !ismuted;
	}
	return false;
});

FLVObject.method('setVolume', function (iPercentVolume) 
{
	if (this.player)
	{
		if (statusObject.ismute == false)
		{
			statusObject.ismute = true;
		}
		commandArray.push(['adjustVolume', iPercentVolume]);
		flashVolume = iPercentVolume;
		return true;
	}
	return false;
});

FLVObject.method('getDuration', function () 
{ 
	if (this.player )
	{
		var duration = statusObject.duration;
		// not all FLV files support duration.  It will default to 0 if the file does not contain duration metadata.
		return Math.round(duration);
	}
	return 0;
});

FLVObject.method('getPosition', function () 
{ 
	if (this.player)
	{
		var position = statusObject.position; 
		// not all FLV files support position.  It will default to 0 if the file does not contain position metadata.
		return Math.round(position);
	}
	return 0;
});

FLVObject.method('secondsToString', function (iSeconds)
{
	if (iSeconds.indexOf(":") >= 0)		// Flash sends time already formatted.  How Nice!
	{
	var sOutput = "";
	var iHours = 0;
	while (iSeconds > 60 * 60)
	{
		iHours++;
		iSeconds = iSeconds - 60 * 60;
	}
	if (iHours > 0)
	{
		sOutput = iHours + ":";
	}

	var iMinutes = 0;
	while (iSeconds > 60)
	{
		iMinutes++;
		iSeconds = iSeconds - 60;
	}

	if (iHours > 0 && iMinutes < 10)
	{
		iMinutes = "0" + iMinutes;
	}

	sOutput = sOutput + iMinutes + ":";

	if (iSeconds < 10)
	{
		iSeconds = "0" + iSeconds;
	}

	return sOutput + iSeconds;
	}
	return iSeconds;

});

FLVObject.method('getDurationString', function () 
{
	return this.secondsToString(this.getDuration());
});

FLVObject.method('getPositionString', function ()
{
	return this.secondsToString(this.getPosition());
});

FLVObject.method('fullScreen', function() { return false;});
FLVObject.method('displayFullScreenWarning', function() 
{
	return false;
});

FLVObject.method('getStatusString', function()
{
	if (this.player)
	{	
		if ((statusObject.playstate != "") && (statusObject.playstate != "loading player"))
		{
			return statusObject.playstate;
		}
	}
	return false;
});

FLVObject.method('registerMediaEndCallback', function(fCallback)
{
	if (this.player)
	{
		FLVObject_mediaEnd = fCallback;
		return true;
	}
	return false;							  
});

FLVObject.method('featureSupported', function(sFeature) 
{ 
	switch(sFeature)
	{
		case 'volume':
		case 'mute':
		case 'pause':
		case 'play':
		case 'stop':
		case 'setContent':
			return true;
	}
	return false;											  
});

/**** END FLASH VIDEO OBJECT BASE CLASS ****/

/**** FLASH COMMUNICATION HELPERS ****/
// These are Macromedia-developed functions for passing information from JavaScript to Flash.  
// So I didn't write 'em.
// So give me a break on CR.
function Exception(name, message)
{
    if (name)
        this.name = name;
    if (message)
        this.message = message;
}
Exception.prototype.setName = function(name)
{
    this.name = name;
}
Exception.prototype.getName = function()
{
    return this.name;
}
Exception.prototype.setMessage = function(msg)
{
    this.message = msg;
}
Exception.prototype.getMessage = function()
{
    return this.message;
}

function FlashTag(src, width, height)
{
    this.src       = src;
    this.width     = width;
    this.height    = height;
    this.version   = '7,0,14,0';
    this.id        = null;
    this.bgcolor   = '000000';
    this.flashVars = null;
}
FlashTag.prototype.setVersion = function(v)
{
    this.version = v;
}
FlashTag.prototype.setId = function(id)
{
    this.id = id;
}
FlashTag.prototype.setBgcolor = function(bgc)
{
    this.bgcolor = bgc;
}
FlashTag.prototype.setFlashvars = function(fv)
{
    this.flashVars = fv;
}
FlashTag.prototype.toString = function()
{
    var ie = (navigator.appName.indexOf ("Microsoft") != -1) ? 1 : 0;
    var flashTag = new String();
    if (ie)
    {
        flashTag += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
        if (this.id != null)
        {
            flashTag += 'id="'+this.id+'" ';
        }
        flashTag += 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version='+this.version+'" ';
        flashTag += 'width="'+this.width+'" ';
        flashTag += 'height="'+this.height+'">';
        flashTag += '<param name="movie" value="'+this.src+'" />';
        flashTag += '<param name="quality" value="high" />';
        flashTag += '<param name="bgcolor" value="#'+this.bgcolor+'" />';
		flashTag += '<param name="scale" value="exactfit" />';
		flashTag += '<param name="wmode" value="transparent" />';
        if (this.flashVars != null)
        {
            flashTag += '<param name="flashvars" value="'+this.flashVars+'" />';
        }
        flashTag += '</object>';
    }
    else
    {
        flashTag += '<embed src="'+this.src+'" ';
        flashTag += 'quality="high" '; 
        flashTag += 'bgcolor="#'+this.bgcolor+'" ';
		flashTag += 'scale="exactfit" ';
		flashTag += 'wmode="transparent" ';
        flashTag += 'width="'+this.width+'" ';
        flashTag += 'height="'+this.height+'" ';
        flashTag += 'type="application/x-shockwave-flash" ';
        if (this.flashVars != null)
        {
            flashTag += 'flashvars="'+this.flashVars+'" ';
        }
        if (this.id != null)
        {
            flashTag += 'name="'+this.id+'" ';
        }
        flashTag += 'swLiveConnect="true" pluginspage="http://www.macromedia.com/go/getflashplayer">';
        flashTag += '</embed>';
    }
    return flashTag;
}
FlashTag.prototype.write = function(doc)
{
    doc.write(this.toString());
}

function FlashSerializer(useCdata)
{
    this.useCdata = useCdata;
}
FlashSerializer.prototype.serialize = function(args)
{
    var qs = new String();

    for (var i = 0; i < args.length; ++i)
    {
        switch(typeof(args[i]))
        {
            case 'undefined':
                qs += 't'+(i)+'=undf';
                break;
            case 'string':
                qs += 't'+(i)+'=str&d'+(i)+'='+escape(args[i]);
                break;
            case 'number':
                qs += 't'+(i)+'=num&d'+(i)+'='+escape(args[i]);
                break;
            case 'boolean':
                qs += 't'+(i)+'=bool&d'+(i)+'='+escape(args[i]);
                break;
            case 'object':
                if (args[i] == null)
                {
                    qs += 't'+(i)+'=null';
                }
                else if (args[i] instanceof Date)
                {
                    qs += 't'+(i)+'=date&d'+(i)+'='+escape(args[i].getTime());
                }
                else // array or object
                {
                    try
                    {
                        qs += 't'+(i)+'=xser&d'+(i)+'='+escape(this._serializeXML(args[i]));
                    }
                    catch (exception)
                    {
                        throw new Exception("FlashSerializationException",
                                            "The following error occurred during complex object serialization: " + exception.getMessage());
                    }
                }
                break;
            default:
                throw new Exception("FlashSerializationException",
                                    "You can only serialize strings, numbers, booleans, dates, objects, arrays, nulls, and undefined.");
        }

        if (i != (args.length - 1))
        {
            qs += '&';
        }
    }

    return qs;
}
FlashSerializer.prototype._serializeXML = function(obj)
{
    var doc = new Object();
    doc.xml = '<fp>'; 
    this._serializeNode(obj, doc, null);
    doc.xml += '</fp>'; 
    return doc.xml;
}
FlashSerializer.prototype._serializeNode = function(obj, doc, name)
{
    switch(typeof(obj))
    {
        case 'undefined':
            doc.xml += '<undf'+this._addName(name)+'/>';
            break;
        case 'string':
            doc.xml += '<str'+this._addName(name)+'>'+this._escapeXml(obj)+'</str>';
            break;
        case 'number':
            doc.xml += '<num'+this._addName(name)+'>'+obj+'</num>';
            break;
        case 'boolean':
            doc.xml += '<bool'+this._addName(name)+' val="'+obj+'"/>';
            break;
        case 'object':
            if (obj == null)
            {
                doc.xml += '<null'+this._addName(name)+'/>';
            }
            else if (obj instanceof Date)
            {
                doc.xml += '<date'+this._addName(name)+'>'+obj.getTime()+'</date>';
            }
            else if (obj instanceof Array)
            {
                doc.xml += '<array'+this._addName(name)+'>';
                for (var i = 0; i < obj.length; ++i)
                {
                    this._serializeNode(obj[i], doc, null);
                }
                doc.xml += '</array>';
            }
            else
            {
                doc.xml += '<obj'+this._addName(name)+'>';
                for (var n in obj)
                {
                    if (typeof(obj[n]) == 'function')
                        continue;
                    this._serializeNode(obj[n], doc, n);
                }
                doc.xml += '</obj>';
            }
            break;
        default:
            throw new Exception("FlashSerializationException",
                                "You can only serialize strings, numbers, booleans, objects, dates, arrays, nulls and undefined");
            break;
    }
}
FlashSerializer.prototype._addName= function(name)
{
    if (name != null)
    {
        return ' name="'+name+'"';
    }
    return '';
}
FlashSerializer.prototype._escapeXml = function(str)
{
    if (this.useCdata)
        return '<![CDATA['+str+']]>';
    else
        return str.replace(/&/g,'&amp;').replace(/</g,'&lt;');
}

function FlashProxy(uid, proxySwfName)
{
    this.uid = uid;
    this.proxySwfName = proxySwfName;
    this.flashSerializer = new FlashSerializer(false);
}
FlashProxy.prototype.call = function()
{

    if (arguments.length == 0)
    {
        throw new Exception("Flash Proxy Exception",
                            "The first argument should be the function name followed by any number of additional arguments.");
    }

    var qs = 'lcId=' + escape(this.uid) + '&functionName=' + escape(arguments[0]);

    if (arguments.length > 1)
    {
        var justArgs = new Array();
        for (var i = 1; i < arguments.length; ++i)
        {
            justArgs.push(arguments[i]);
        }
        qs += ('&' + this.flashSerializer.serialize(justArgs));
    }

    var divName = '_flash_proxy_' + this.uid;
    if(!document.getElementById(divName))
    {
        var newTarget = document.createElement("div");
        newTarget.id = divName;
        document.body.appendChild(newTarget);
    }
    var target = document.getElementById(divName);
    var ft = new FlashTag(this.proxySwfName, 1, 1);
    ft.setVersion('6,0,65,0');
    ft.setFlashvars(qs);
    target.innerHTML = ft.toString();
}
FlashProxy.callJS = function()
{
    var functionToCall = eval(arguments[0]);
    var argArray = new Array();
    for (var i = 1; i < arguments.length; ++i)
    {
        argArray.push(arguments[i]);
    }
    functionToCall.apply(functionToCall, argArray);
}
/**** END FLASH COMMUNICATION HELPERS ****/
