  var orgCursor 		= null;
  var dragOK 				= false;
  var disableDrag		= false;
  var dragXoffset 	= 0;
  var dragYoffset 	= 0;
  var savedTarget	=	null;
	var loginDisplay;
	var welcomeDisplay;
	var rosterDisplay;
	var chatDisplay;
	var roomDisplay;
	var winDisplay;
	var popupDisplay;
	var popupCounter = 0;
	var popupQueue = new Array();
	var popupDir 			= 'up';
	var winTitle					= "";
  var selected 				= "";
  var conn 						= true;
  var userID					=	"";
  var nickName			=	"";
  var roomTheme	=	"wildwest";
  var soundOn				=	'yes';
  var popupOn			=	'yes';
  var tabs 						= new Array();
  var contacts 			= new Array();
  var texts 						= new Array();
  var nicks 						= new Array();

	function findPosX(obj) {
    var curleft = 0;
    if(obj.offsetParent)
        while(1) {
          curleft += obj.offsetLeft;
          if(!obj.offsetParent)
            break;
          obj = obj.offsetParent;
        }
    else if(obj.x)
        curleft += obj.x;
    return curleft;
	}

function findPosY(obj) {
    var curtop = 0;
    if(obj.offsetParent)
        while(1) {
          curtop += obj.offsetTop;
          if(!obj.offsetParent)
            break;
          obj = obj.offsetParent;
        }
    else if(obj.y)
        curtop += obj.y;
    return curtop;
}

	function moveWinHandler(e){
      if(e == null) e = window.event;
      if(e.button<=1 && dragOK){
         winDisplay.style.left=e.clientX-dragXoffset+'px';
         winDisplay.style.top=e.clientY-dragYoffset+'px';
         return false;
      }
	}

	function cleanupWin(e) {
      winDisplay.onMousemove = null;
      winDisplay.onMouseup = null;
      winDisplay.style.cursor = orgCursor;
      dragOK = false;
	}

	function dragWinHandler(e){
    var htype='-moz-grabbing';
    if(e == null) { e = window.event; htype = 'move';} 
		orgCursor=winDisplay.style.cursor;
		winDisplay.style.cursor = htype;
		dragOK = true;
		dragXoffset = e.clientX-parseInt(winDisplay.style.left);
		dragYoffset = e.clientY-parseInt(winDisplay.style.top);
		return false;
	}
   
	function moveRosterHandler(e){
		if(e == null) e = window.event;
		if(e.button<=1 && dragOK){
			rosterDisplay.style.left=e.clientX-dragXoffset+'px';
			rosterDisplay.style.top=e.clientY-dragYoffset+'px';
			return false;
		}
	}

	function cleanupRoster(e) {
		rosterDisplay.onMousemove = null;
		rosterDisplay.onMouseup = null;
		rosterDisplay.style.cursor = orgCursor;
		dragOK = false;
	}

	function dragRosterHandler(e){
    var htype='-moz-grabbing';
    if(e == null) { e = window.event; htype = 'move';} 
		orgCursor=rosterDisplay.style.cursor;
		rosterDisplay.style.cursor = htype;
		dragOK = true;
		dragXoffset = e.clientX-parseInt(rosterDisplay.style.left);
		dragYoffset = e.clientY-parseInt(rosterDisplay.style.top);
		return false;
	}

	function moveChatHandler(e){
		if(e == null) e = window.event;
		if(e.button<=1 && dragOK) {
			chatDisplay.style.left=e.clientX-dragXoffset+'px';
			chatDisplay.style.top=e.clientY-dragYoffset+'px';
			return false;
		}
	}

	function cleanupChat(e) {
		chatDisplay.onMousemove = null;
		chatDisplay.onMouseup = null;
		chatDisplay.style.cursor = orgCursor;
		dragOK = false;
	}

	function dragChatHandler(e){
		if(disableDrag) return;
    var htype='-moz-grabbing';
    if(e == null) { e = window.event; htype = 'move';} 
		orgCursor=chatDisplay.style.cursor;
		chatDisplay.style.cursor = htype;
		dragOK = true;
		dragXoffset = e.clientX-parseInt(chatDisplay.style.left);
		dragYoffset = e.clientY-parseInt(chatDisplay.style.top);
		return false;
	}
	
	function moveIconHandler(e){
		if(e == null) e = window.event;
		if(dragOK){
			savedTarget.style.left=e.clientX-dragXoffset+'px';
			savedTarget.style.top=e.clientY-dragYoffset+'px';
			return false;
		}
	}

	function cleanupIcon(e) {
		document.onMousemove = null;
		document.onMouseup = null;
		savedTarget.style.cursor = orgCursor;
		dragOK = false;
	}

	function dragIconHandler(e){
    var htype='-moz-grabbing';
    if(e == null) { e = window.event; htype = 'move';} 
    var target = e.target != null ? e.target : e.srcElement;
    //alert(target.className);
    if((target.tagName=="DIV") && ((target.id != "chat_room") || (target.id != "room_div"))) { 
    	savedTarget=target;
			orgCursor=target.style.cursor;
			target.style.cursor = htype;
			dragOK = true;
			dragXoffset = e.clientX-parseInt(target.style.left);
			dragYoffset = e.clientY-parseInt(target.style.top);
			document.onmousemove=moveIconHandler;
			document.onmouseup=cleanupIcon;
			return false;
		}
	}	

  function addTab(tabID) {
  	if(!tabID) return;
  	if(selected == tabID) return;
  	if(userID == tabID) return;
  	if(tabs.length < 1)  showChat();
  	var exists = false;
  	for(d = 0; d < tabs.length; d++) {
  		if(tabs[d] == tabID) exists = true;
  	}
  	if(!exists) {
  		tabs.push(tabID);
  		soundManager.play("chat1Sound");
  	}
  	var tabTable = "";
  	for(i = 0; i < tabs.length; i++) {
  		var focus = false;
  		if(tabs[i] == tabID) {
  			selected = tabs[i];
  			focus = true;
			}
			tabTable += printTab(tabs[i],getNameFromJid(tabs[i]),focus);
		}
  	var lookupelement = document.getElementById("tab");
  	lookupelement.innerHTML = tabTable;
  	lookupelement.style.height = '16px';
  	lookupelement.style.visibility = 'visible';
  	previousText(selected);
  	document.getElementById("sender").focus();
	}

  function closeTab(tabID) {
  	if(!tabID) {
  		hideChat();
  		return;
  	}
  	var newTabs = new Array();
  	var d = 0;
  	for(b = 0; b < tabs.length; b++) {
  		if(tabs[b] != tabID)	{
  			newTabs[d] = tabs[b];
  			d++;
  		}
		}
		tabs = newTabs;		
  	var tabTable = "";
  	for(i = 0; i < tabs.length; i++) {
  			var focus = false;
  			if(tabs.length == 1) {
  				selected = tabs[i];
  			} else {
  				if((i+1) < tabs.length) {

  				} else {
  					selected = tabs[i];
  				}
				}
				if(selected == tabs[i]) focus = true;
				tabTable += printTab(tabs[i],getNameFromJid(tabs[i]),focus);
		}
  	var lookupelement = document.getElementById("tab");
  	lookupelement.innerHTML = tabTable;
  	lookupelement.style.height = '16px';
  	lookupelement.style.visibility = 'visible';
  	if(tabs.length < 1) {
  		hideChat();
  		selected = "";
  	} else {
  		previousText(selected);
  		document.getElementById("sender").focus();
		}
	}

  function changeTab(tabID) {
  	if(!tabID) return;
  	if(selected == tabID) return;
  	var tabTable = "";
  	for(i = 0; i < tabs.length; i++) {
  		var focus = false;
  		if(tabs[i] == tabID) {	
  			selected = tabs[i];
  			focus = true;
  		}
			tabTable += printTab(tabs[i],getNameFromJid(tabs[i]),focus);
		}
  	var lookupelement = document.getElementById("tab");
  	lookupelement.innerHTML = tabTable;
  	lookupelement.style.height = '16px';
  	lookupelement.style.visibility = 'visible';
  	previousText(selected);
  	document.getElementById("sender").focus();
	}

function SoundManager(smURL,smID) {
  var self = this;
  this.version = 'V2.0b.20070123';
  this.url = (smURL||'soundmanager2.swf');

  this.debugMode = false;
  this.useConsole = true;
  this.consoleOnly = true;

  this.defaultOptions = { 'autoLoad': false,'stream': true,'autoPlay': false,'onid3': null,'onload': null,'whileloading': null,'onplay': null,'whileplaying': null,'onstop': null,'onfinish': null,'onbeforefinish': null,'onbeforefinishtime': 5000,'onbeforefinishcomplete':null,'onjustbeforefinish':null,'onjustbeforefinishtime':200, 'multiShot': true,'pan': 0,'volume': 100 }
  this.allowPolling = true;
  this.enabled = false;
  this.o = null;
  this.id = (smID||'sm2movie');
  this.oMC = null;
  this.sounds = [];
  this.soundIDs = [];
  this.isIE = (navigator.userAgent.match(/MSIE/));
  this.isSafari = (navigator.userAgent.match(/safari/i));
  this.debugID = 'soundmanager-debug';
  this._debugOpen = true;
  this._didAppend = false;
  this._appendSuccess = false;
  this._didInit = false;
  this._disabled = false;
  this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined');
  this._debugLevels = !self.isSafari?['debug','info','warn','error']:['log','log','log','log'];

  this.getMovie = function(smID) {
    // return self.isIE?window[smID]:document[smID];
    return self.isIE?window[smID]:(self.isSafari?document[smID+'-embed']:document.getElementById(smID+'-embed'));
  }

  this.loadFromXML = function(sXmlUrl) {
    try {
      self.o._loadFromXML(sXmlUrl);
    } catch(e) {
      self._failSafely();
      return true;
    }
  }

  this.createSound = function(oOptions) {
    if (!self._didInit) throw new Error('soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods');
    if (arguments.length==2) {
      oOptions = {'id':arguments[0],'url':arguments[1]}
    }
    var thisOptions = self._mergeObjects(oOptions);
    if (self._idCheck(thisOptions.id,true)) {
      return false;
    }
    self.sounds[thisOptions.id] = new SMSound(self,thisOptions);
    self.soundIDs[self.soundIDs.length] = thisOptions.id;
    try {
      self.o._createSound(thisOptions.id,thisOptions.onjustbeforefinishtime);
    } catch(e) {
      self._failSafely();
      return true;
    }
    if (thisOptions.autoLoad || thisOptions.autoPlay) self.sounds[thisOptions.id].load(thisOptions);
    if (thisOptions.autoPlay) self.sounds[thisOptions.id].playState = 1; // we can only assume this sound will be playing soon.
  }

  this.load = function(sID,oOptions) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].load(oOptions);
  }

  this.unload = function(sID) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].unload();
  }

  this.play = function(sID,oOptions) {
    if (!self._idCheck(sID)) {
      if (typeof oOptions != 'Object') oOptions = {url:oOptions}; // overloading use case: play('mySound','/path/to/some.mp3');
      if (oOptions && oOptions.url) {
        oOptions.id = sID;
        self.createSound(oOptions);
      } else {
        return false;
      }
    }
    self.sounds[sID].play(oOptions);
  }

  this.start = this.play; // just for convenience

  this.setPosition = function(sID,nMsecOffset) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].setPosition(nMsecOffset);
  }

  this.stop = function(sID) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].stop(); 
  }

  this.stopAll = function() {
    for (var oSound in self.sounds) {
      if (oSound instanceof SMSound) oSound.stop(); // apply only to sound objects
    }
  }

  this.pause = function(sID) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].pause();
  }

  this.resume = function(sID) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].resume();
  }

  this.togglePause = function(sID) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].togglePause();
  }

  this.setPan = function(sID,nPan) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].setPan(nPan);
  }

  this.setVolume = function(sID,nVol) {
    if (!self._idCheck(sID)) return false;
    self.sounds[sID].setVolume(nVol);
  }

  this.setPolling = function(bPolling) {
    if (!self.o || !self.allowPolling) return false;
    self.o._setPolling(bPolling);
  }

  this.disable = function() {
    // destroy all functions
    if (self._disabled) return false;
    self._disabled = true;
    for (var i=self.soundIDs.length; i--;) {
      self._disableObject(self.sounds[self.soundIDs[i]]);
    }
    self.initComplete(); // fire "complete", despite fail
    self._disableObject(self);
  }

  this.getSoundById = function(sID,suppressDebug) {
    if (!sID) throw new Error('SoundManager.getSoundById(): sID is null/undefined');
    var result = self.sounds[sID];
    if (!result && !suppressDebug) {
    }
    return result;
  }

  //this.onload = function() {

  //}

  this.onerror = function() {
    //alert("Error in Soundmodule");
  }

  this._idCheck = this.getSoundById;

  this._disableObject = function(o) {
    for (var oProp in o) {
      if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') o[oProp] = function(){return false;}
    }
    oProp = null;
  }

  this._failSafely = function() {
    var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html';
    var fpgssTitle = 'You may need to whitelist this location/domain eg. file:///C:/ or C:/ or mysite.com, or set ALWAYS ALLOW under the Flash Player Global Security Settings page. Note that this seems to apply only to file system viewing.';
    var flashCPL = '<a href="'+flashCPLink+'" title="'+fpgssTitle+'">view/edit</a>';
    var FPGSS = '<a href="'+flashCPLink+'" title="Flash Player Global Security Settings">FPGSS</a>';
    if (!self._disabled) {
      self.disable();
    }
  }

  this._createMovie = function(smID,smURL) {
    if (self._didAppend && self._appendSuccess) return false; // ignore if already succeeded
    if (window.location.href.indexOf('debug=1')+1) self.debugMode = true; // allow force of debug mode via URL
    self._didAppend = true;
    var html = ['<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="16" height="16" id="'+smID+'"><param name="movie" value="'+smURL+'"><param name="quality" value="high"><param name="allowScriptAccess" value="always" /></object>','<embed name="'+smID+'-embed" id="'+smID+'-embed" src="'+smURL+'" width="1" height="1" quality="high" allowScriptAccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"></embed>'];
    var toggleElement = '<div id="'+self.debugID+'-toggle" style="position:fixed;_position:absolute;right:0px;bottom:0px;_top:0px;width:1.2em;height:1.2em;line-height:1.2em;margin:2px;padding:0px;text-align:center;border:1px solid #999;cursor:pointer;background:#fff;color:#333;z-index:706" title="Toggle SM2 debug console" onclick="soundManager._toggleDebug()">-</div>';
    var debugHTML = '<div id="'+self.debugID+'" style="display:'+(self.debugMode && ((!self._hasConsole||!self.useConsole)||(self.useConsole && self._hasConsole && !self.consoleOnly))?'block':'none')+';opacity:0.85"></div>';
    var appXHTML = 'soundManager._createMovie(): appendChild/innerHTML set failed. Serving application/xhtml+xml MIME type? Browser may be enforcing strict rules, not allowing write to innerHTML. (PS: If so, this means your commitment to XML validation is going to break stuff now, because this part isn\'t finished yet. ;))';

    var sHTML = '<div style="position:absolute;left:-256px;top:-256px;width:1px;height:1px" class="movieContainer">'+html[self.isIE?0:1]+'</div>'+(self.debugMode && ((!self._hasConsole||!self.useConsole)||(self.useConsole && self._hasConsole && !self.consoleOnly)) && !document.getElementById(self.debugID)?'x'+debugHTML+toggleElement:'');

    var oTarget = (document.body?document.body:document.getElementsByTagName('div')[0]);
    if (oTarget) {
      self.oMC = document.createElement('div');
      self.oMC.className = 'movieContainer';
      self.oMC.style.position = 'absolute';
      self.oMC.style.left = '-256px';
      self.oMC.style.width = '1px';
      self.oMC.style.height = '1px';
      try {
        oTarget.appendChild(self.oMC);
        self.oMC.innerHTML = html[self.isIE?0:1];
        self._appendSuccess = true;
      } catch(e) {
        throw new Error(appXHTML);
      }
      if (!document.getElementById(self.debugID) && ((!self._hasConsole||!self.useConsole)||(self.useConsole && self._hasConsole && !self.consoleOnly))) {
        var oDebug = document.createElement('div');
        oDebug.id = self.debugID;
        oDebug.style.display = (self.debugMode?'block':'none');
        if (self.debugMode) {
          try {
            var oD = document.createElement('div');
            oTarget.appendChild(oD);
            oD.innerHTML = toggleElement;
          } catch(e) {
            throw new Error(appXHTML);
          }
        }
        oTarget.appendChild(oDebug);
      }
      oTarget = null;
    }
  }

  this._writeDebug = function(sText,sType) {
    if (!self.debugMode) return false;
    if (self._hasConsole && self.useConsole) {
      console[self._debugLevels[sType]||'log'](sText); // firebug et al
      if (self.useConsoleOnly) return true;
    }
    var sDID = 'soundmanager-debug';
    try {
      var o = document.getElementById(sDID);
      if (!o) return false;
      var p = document.createElement('div');
      p.innerHTML = sText;
      o.insertBefore(p,o.firstChild);
    } catch(e) {
      // oh well
    }
    o = null;
  }
  this._writeDebug._protected = true;

  this._writeDebugAlert = function(sText) { alert(sText); }

  if (window.location.href.indexOf('debug=alert')+1) {
    self.debugMode = true;
    self._writeDebug = self._writeDebugAlert;
  }

  this._toggleDebug = function() {
    var o = document.getElementById(self.debugID);
    var oT = document.getElementById(self.debugID+'-toggle');
    if (!o) return false;
    if (self._debugOpen) {
      oT.innerHTML = '+';
      o.style.display = 'none';
    } else {
      oT.innerHTML = '-';
      o.style.display = 'block';
    }
    self._debugOpen = !self._debugOpen;
  }

  this._toggleDebug._protected = true;

  this._debug = function() {

  }

  this._mergeObjects = function(oMain,oAdd) {
    var o1 = oMain;
    var o2 = (typeof oAdd == 'undefined'?self.defaultOptions:oAdd);
    for (var o in o2) {
      if (typeof o1[o] == 'undefined') o1[o] = o2[o];
    }
    return o1;
  }

  this.createMovie = function(sURL) {
    if (sURL) self.url = sURL;
    self._initMovie();
  }

  this._initMovie = function() {
    if (self.o) return false; // pre-init may have fired this function before window.onload(), may already exist
    self.o = self.getMovie(self.id); // try to get flash movie (inline markup)
    if (!self.o) {
      self._createMovie(self.id,self.url);
      self.o = self.getMovie(self.id);
    }
  }

  this.initComplete = function() {
    if (self._didInit) return false;
    self._didInit = true;
    if (self._disabled) {
      self.onerror.apply(window);
      return false;
    }
    try {
      self.onload.apply(window);
    } catch(e) {
      throw e;
    }
  }

  this.init = function() {
    try {
      self.o._externalInterfaceTest(); // attempt to talk to Flash
      if (!self.allowPolling) self._writeDebug('Polling (whileloading/whileplaying support) is disabled.',1);
      self.setPolling(true);
      self.enabled = true;
    }  catch(e) {
      self._failSafely();
      self.initComplete();
      return false;
    }
    self.initComplete();
  }

  this.beginDelayedInit = function() {
    setTimeout(self.beginInit,200);
  }

  this.beginInit = function() {
    self.createMovie();
    self._initMovie();
    setTimeout(self.init,1000);
  }

  this.destruct = function() {
    if (self.isSafari) {
      for (var i=self.soundIDs.length; i--;) {
        if (self.sounds[self.soundIDs[i]].readyState == 1) self.sounds[self.soundIDs[i]].unload();
      }
    }
    self.disable();
  }
}

function SMSound(oSM,oOptions) {
  var self = this;
  var sm = oSM;
  this.sID = oOptions.id;
  this.url = oOptions.url;
  this.options = sm._mergeObjects(oOptions);
  this.id3 = {  }

  self.resetProperties = function(bLoaded) {
    self.bytesLoaded = null;
    self.bytesTotal = null;
    self.position = null;
    self.duration = null;
    self.durationEstimate = null;
    self.loaded = false;
    self.loadSuccess = null;
    self.playState = 0;
    self.paused = false;
    self.readyState = 0;
    self.didBeforeFinish = false;
    self.didJustBeforeFinish = false;
  }

  self.resetProperties();

  this.load = function(oOptions) {
    self.loaded = false;
    self.loadSuccess = null;
    self.readyState = 1;
    self.playState = (oOptions.autoPlay||false);
    var thisOptions = sm._mergeObjects(oOptions);
    if (typeof thisOptions.url == 'undefined') thisOptions.url = self.url;
    try {
      sm._writeDebug('loading '+thisOptions.url,1);
      sm.o._load(self.sID,thisOptions.url,thisOptions.stream,thisOptions.autoPlay,thisOptions.whileloading?1:0);
    } catch(e) {

    }
  }

  this.unload = function() {
    self.setPosition(0);
    sm.o._unload(self.sID,'data/null.mp3');
    self.resetProperties();
  }

  this.play = function(oOptions) {
    if (!oOptions) oOptions = {};

    if (oOptions.onfinish) self.options.onfinish = oOptions.onfinish;
    if (oOptions.onbeforefinish) self.options.onbeforefinish = oOptions.onbeforefinish;
    if (oOptions.onjustbeforefinish) self.options.onjustbeforefinish = oOptions.onjustbeforefinish;

    var thisOptions = sm._mergeObjects(oOptions);
    if (self.playState == 1) {
      var allowMulti = thisOptions.multiShot;
      if (!allowMulti) {
        return false;
      }
    }
    if (!self.loaded) {
      if (self.readyState == 0) {
        sm._writeDebug('SMSound.play(): .play() before load request. Attempting to load "'+self.sID+'"',1);
        thisOptions.stream = true;
        thisOptions.autoPlay = true;
        self.load(thisOptions); // try to get this sound playing ASAP
      } else if (self.readyState == 2) {
        return false;
      }
    }
    if (self.paused) {
      self.resume();
    } else {
      self.playState = 1;
      self.position = (thisOptions.offset||0);
      if (thisOptions.onplay) thisOptions.onplay.apply(self);
      self.setVolume(thisOptions.volume);
      self.setPan(thisOptions.pan);
      if (!thisOptions.autoPlay) {
        sm.o._start(self.sID,thisOptions.loop||1,self.position);
      }
    }
  }

  this.start = this.play; // just for convenience

  this.stop = function(bAll) {
    if (self.playState == 1) {
      self.playState = 0;
      self.paused = false;
      if (sm.defaultOptions.onstop) sm.defaultOptions.onstop.apply(self);
      sm.o._stop(self.sID);
    }
  }

  this.setPosition = function(nMsecOffset) {
    sm.o._setPosition(self.sID,nMsecOffset/1000,self.paused||!self.playState);
  }

  this.pause = function() {
    if (self.paused) return false;
    self.paused = true;
    sm.o._pause(self.sID);
  }

  this.resume = function() {
    if (!self.paused) return false;
    self.paused = false;
    sm.o._pause(self.sID);
  }

  this.togglePause = function() {
    sm._writeDebug('SMSound.togglePause()');
    if (!self.playState) {
      self.play({offset:self.position/1000});
      return false;
    }
    if (self.paused) {
      sm._writeDebug('SMSound.togglePause(): resuming..');
      self.resume();
    } else {
      sm._writeDebug('SMSound.togglePause(): pausing..');
      self.pause();
    }
  }

  this.setPan = function(nPan) {
    if (typeof nPan == 'undefined') nPan = 0;
    sm.o._setPan(self.sID,nPan);
    self.options.pan = nPan;
  }

  this.setVolume = function(nVol) {
    if (typeof nVol == 'undefined') nVol = 100;
    sm.o._setVolume(self.sID,nVol);
    self.options.volume = nVol;
  }

  this._whileloading = function(nBytesLoaded,nBytesTotal,nDuration) {
    self.bytesLoaded = nBytesLoaded;
    self.bytesTotal = nBytesTotal;
    self.duration = nDuration;
    self.durationEstimate = parseInt((self.bytesTotal/self.bytesLoaded)*self.duration);
    if (self.readyState != 3 && self.options.whileloading) self.options.whileloading.apply(self);
  }

  this._onid3 = function(oID3PropNames,oID3Data) {
    var oData = [];
    for (var i=0,j=oID3PropNames.length; i<j; i++) {
      oData[oID3PropNames[i]] = oID3Data[i];
    }
    self.id3 = sm._mergeObjects(self.id3,oData);
    if (self.options.onid3) self.options.onid3.apply(self);
  }

  this._whileplaying = function(nPosition) {
    if (isNaN(nPosition) || nPosition == null) return false;
    self.position = nPosition;
    if (self.playState == 1) {
      if (self.options.whileplaying) self.options.whileplaying.apply(self);
      if (self.loaded && self.options.onbeforefinish && self.options.onbeforefinishtime && !self.didBeforeFinish && self.duration-self.position <= self.options.onbeforefinishtime) {
        sm._writeDebug('duration-position &lt;= onbeforefinishtime: '+self.duration+' - '+self.position+' &lt= '+self.options.onbeforefinishtime+' ('+(self.duration-self.position)+')');
        self._onbeforefinish();
      }
    }
  }

  this._onload = function(bSuccess) {
    bSuccess = (bSuccess==1?true:false);
    self.loaded = bSuccess;
    self.loadSuccess = bSuccess;
    self.readyState = bSuccess?3:2;
    if (self.options.onload) self.options.onload.apply(self);
  }

  this._onbeforefinish = function() {
    if (!self.didBeforeFinish) {
      self.didBeforeFinish = true;
      if (self.options.onbeforefinish) self.options.onbeforefinish.apply(self);
    }
  }

  this._onjustbeforefinish = function(msOffset) {
    if (!self.didJustBeforeFinish) {
      self.didJustBeforeFinish = true;
      soundManager._writeDebug('SMSound._onjustbeforefinish()');
      if (self.options.onjustbeforefinish) self.options.onjustbeforefinish.apply(self);;
    }
  }

  this._onfinish = function() {
    self.playState = 0;
    self.paused = false;
    if (self.options.onfinish) self.options.onfinish.apply(self);
    if (self.options.onbeforefinishcomplete) self.options.onbeforefinishcomplete.apply(self);
    self.setPosition(0);
    self.didBeforeFinish = false;
    self.didJustBeforeFinish = false;
  }
}
