function PagePlayer(oConfigOverride) { var self = this; var pl = this; var sm = soundManager; var isIE = navigator.userAgent.match(/msie/i); var isOpera = navigator.userAgent.match(/opera/i); var isFirefox = navigator.userAgent.match(/firefox/i); this.config = {flashVersion: 9,usePeakData: true,useWaveformData: false,useEQData: false,fillGraph: false,allowRightClick:true,useThrottling: false,autoStart: true,playNext: true,updatePageTitle: false,emptyTime: '-:--',useFavIcon: true}


this._mergeObjects = function(oMain,oAdd) {
var o1 = {}; 
for (var i in oMain) {o1[i] = oMain[i];}
var o2 = (typeof oAdd == 'undefined'?{}:oAdd);
for (var o in o2) {
if (typeof o1[o] == 'undefined') o1[o] = o2[o];
}
return o1;
}

if (typeof oConfigOverride != 'undefined' && oConfigOverride) {this.config = this._mergeObjects(oConfigOverride,this.config);}

this.css = {sDefault: 'sm2_link',sLoading: 'sm2_loading',sPlaying: 'sm2_playing',sPaused: 'sm2_paused'}

this.cssBase = []; 
if (this.config.usePeakData) this.cssBase.push('use-peak');
if (this.config.useWaveformData || this.config.useEQData) this.cssBase.push('use-spectrum');
this.cssBase = this.cssBase.join(' ');

sm.flashVersion = this.config.flashVersion;
if (sm.flashVersion >= 9) {
sm.useMovieStar = this.config.useMovieStar;
sm.movieStarOptions.useVideo = this.config.useVideo;
sm.defaultOptions.usePeakData = this.config.usePeakData;
sm.defaultOptions.useWaveformData = this.config.useWaveformData;
sm.defaultOptions.useEQData = this.config.useEQData;
}

this.links = [];this.sounds = [];this.soundsByObject = [];this.lastSound = null;this.soundCount = 0;this.strings = [];this.dragActive = false;this.dragExec = new Date();this.dragTimer = null;this.pageTitle = document.title;this.lastWPExec = new Date();this.vuMeterData = [];this.oControls = null;

this.addEventHandler = function(o,evtName,evtHandler) 
{
typeof(attachEvent)=='undefined'?o.addEventListener(evtName,evtHandler,false):o.attachEvent('on'+evtName,evtHandler);
}

this.removeEventHandler = function(o,evtName,evtHandler) {
typeof(attachEvent)=='undefined'?o.removeEventListener(evtName,evtHandler,false):o.detachEvent('on'+evtName,evtHandler);
}

this.hasClass = function(o,cStr) {
return (typeof(o.className)!='undefined'?new RegExp('(^|\\s)'+cStr+'(\\s|$)').test(o.className):false);
}

this.addClass = function(o,cStr) {
if (!o || !cStr) return false;
if (self.hasClass(o,cStr)) return false;
o.className = (o.className?o.className+' ':'')+cStr;
}

this.removeClass = function(o,cStr) {
if (!o || !cStr) return false;
if (!self.hasClass(o,cStr)) return false;
o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
}

this.getElementsByClassName = function(className,tagNames,oParent) {
var doc = (oParent||document);
var matches = [];
var i,j;
var nodes = [];
if (typeof(tagNames)!='undefined' && typeof(tagNames)!='string') {
for (i=tagNames.length; i--;) {
if (!nodes || !nodes[tagNames[i]]) {
nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]);
}
}
} else if (tagNames) {
nodes = doc.getElementsByTagName(tagNames);
} else {
nodes = doc.all||doc.getElementsByTagName('*');
}
if (typeof(tagNames)!='string') {
for (i=tagNames.length; i--;) {
for (j=nodes[tagNames[i]].length; j--;) {
if (self.hasClass(nodes[tagNames[i]][j],className)) {
matches[matches.length] = nodes[tagNames[i]][j];
}
}
}
} else {
for (i=0; i<nodes.length; i++) {
if (self.hasClass(nodes[i],className)) {
matches[matches.length] = nodes[i];
}
}
}
return matches;
}
  
this.getOffX = function(o) {
var curleft = 0;
if (o.offsetParent) {
while (o.offsetParent) {
curleft += o.offsetLeft;
o = o.offsetParent;
}
}
else if (o.x) curleft += o.x;
return curleft;
}

this.isChildOfClass = function(oChild,oClass) {
if (!oChild || !oClass) return false;
while (oChild.parentNode && !self.hasClass(oChild,oClass)) {
oChild = oChild.parentNode;
}
return (self.hasClass(oChild,oClass));
}

this.getParentByNodeName = function(oChild,sParentNodeName) {
if (!oChild || !sParentNodeName) return false;
sParentNodeName = sParentNodeName.toLowerCase();
while (oChild.parentNode && sParentNodeName != oChild.parentNode.nodeName.toLowerCase()) {
oChild = oChild.parentNode;
}
return (oChild.parentNode && sParentNodeName == oChild.parentNode.nodeName.toLowerCase()?oChild.parentNode:null);
}
  
this.getTime = function(nMSec,bAsString) {
var nSec = Math.floor(nMSec/1000);
var min = Math.floor(nSec/60);
var sec = nSec-(min*60);
return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec});
}

this.getSoundByObject = function(o) {
return (typeof self.soundsByObject[o.rel] != 'undefined'?self.soundsByObject[o.rel]:null);
}

this.getSoundIndex = function(o) {
for (var i=self.links.length; i--;) {
if (self.links[i].rel == o.rel) return i;
}
return -1;
}

this.setPageTitle = function(sTitle) {
if (!self.config.updatePageTitle) return false;
try {
document.title = (sTitle?sTitle+' - ':'')+self.pageTitle;
} catch(e) {
self.setPageTitle = function() {return false;}
}
}

this.events = {
play: function() {
pl.removeClass(this._data.oLI,this._data.className);
this._data.className = pl.css.sPlaying;
pl.addClass(this._data.oLI,this._data.className);
self.setPageTitle(this._data.originalTitle);
},

stop: function() {
pl.removeClass(this._data.oLI,this._data.className);
this._data.className = '';
this._data.oPosition.style.width = '0px';
self.setPageTitle();
self.resetPageIcon();
},

pause: function() {
if (pl.dragActive) return false;
pl.removeClass(this._data.oLI,this._data.className);
this._data.className = pl.css.sPaused;
pl.addClass(this._data.oLI,this._data.className);
self.setPageTitle();
self.resetPageIcon();
},

resume: function() {
if (pl.dragActive) return false;
pl.removeClass(this._data.oLI,this._data.className);
this._data.className = pl.css.sPlaying;
pl.addClass(this._data.oLI,this._data.className);
},

finish: function() {
pl.removeClass(this._data.oLI,this._data.className);
this._data.className = '';
this._data.oPosition.style.width = '0px';
if (self.config.playNext && this._data.nIndex<pl.links.length-1) {
pl.handleClick({target:pl.links[this._data.nIndex+1]}); 
} else {
self.setPageTitle();
self.resetPageIcon();
}
},

whileloading: function() {
this._data.oLoading.style.width = (((this.bytesLoaded/this.bytesTotal)*100)+'%'); // theoretically, this should work.
if (!this._data.didRefresh && this._data.metadata) {
this._data.didRefresh = true;
this._data.metadata.refresh();
}
},

onload: function() {
if (!this.loaded) {
var oTemp = this._data.oLI.getElementsByTagName('a')[0];
var oString = oTemp.innerHTML;
var oThis = this;
oTemp.innerHTML = oString+' <span style="font-size:0.5em"> | Load failed, d\'oh! '+(sm.sandbox.noRemote?' Possible cause: Flash sandbox is denying remote URL access.':(sm.sandbox.noLocal?'Flash denying local filesystem access':'404?'))+'</span>';
setTimeout(function(){
oTemp.innerHTML = oString;
},5000);
} else {
if (this._data.metadata) {
this._data.metadata.refresh();
}
}
},

metadata: function() {
sm._wD('video metadata: '+this.width+'x'+this.height);
sm.oMC.style.width = this.width+'px';	
sm.oMC.style.height = this.height+'px';
},

whileplaying: function() {
var d = null;
if (pl.dragActive || !pl.config.useThrottling) {
self.updateTime.apply(this);
if (sm.flashVersion >= 9) {
if (pl.config.usePeakData && this.instanceOptions.usePeakData) self.updatePeaks.apply(this);
if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {
self.updateGraph.apply(this);
}
}
if (this._data.metadata) {
d = new Date();
if (d && d-self.lastWPExec>500) {
self.refreshMetadata(this);
self.lastWPExec = d;
}
}
this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');
} else {
d = new Date();
if (d-self.lastWPExec>500) {
self.updateTime.apply(this);
if (sm.flashVersion >= 9) {
if (pl.config.usePeakData && this.instanceOptions.usePeakData) {
self.updatePeaks.apply(this);
}
if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {
self.updateGraph.apply(this);
}
}
if (this._data.metadata) self.refreshMetadata(this);
this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');
self.lastWPExec = d;
}
}
}
}

var _head = document.getElementsByTagName('head')[0];
this.setPageIcon = function(sDataURL) {
if (!self.config.useFavIcon || !self.config.usePeakData || !sDataURL) {
return false;
}
var link = document.getElementById('sm2-favicon');
if (link) {
_head.removeChild(link);
link = null;
}
if (!link) {
link = document.createElement('link');
link.id = 'sm2-favicon';
link.rel = 'shortcut icon';
link.type = 'image/png';
link.href = sDataURL;
document.getElementsByTagName('head')[0].appendChild(link);
}
}

this.resetPageIcon = function() {
if (!self.config.useFavIcon) {
return false;
}
var link = document.getElementById('favicon');
if (link) {
link.href = '/favicon.ico';
}
}

this.updatePeaks = function() {
var o = this._data.oPeak;
var oSpan = o.getElementsByTagName('span');
oSpan[0].style.width = (0+(Math.floor(100*this.peakData.left))+'px');
oSpan[1].style.width = (0+(Math.floor(100*this.peakData.right))+'px');
if (self.config.flashVersion > 8 && self.config.useFavIcon && self.config.usePeakData) {
self.setPageIcon(self.vuMeterData[parseInt(16*this.peakData.left)][parseInt(16*this.peakData.right)]);
}
}
  
this.updateGraph = function() {
if ((!pl.config.useWaveformData && !pl.config.useEQData) || pl.config.flashVersion<9) return false;
var sbC = this._data.oGraph.getElementsByTagName('div');
if (pl.config.useWaveformData) {
var scale = 8; 
for (var i=255; i--;) {
sbC[255-i].style.marginTop = (1+scale+Math.ceil(this.waveformData.left[i]*-scale))+'px';
}
} else {
var offset = 9;
for (var i=255; i--;) {
sbC[255-i].style.marginTop = ((offset*2)-1+Math.ceil(this.eqData[i]*-offset))+'px';
}
}
}
this.resetGraph = function() {
if (!pl.config.useEQData || pl.config.flashVersion<9) return false;
var sbC = this._data.oGraph.getElementsByTagName('div');
var scale = (!pl.config.useEQData?'9px':'17px');
var nHeight = (!pl.config.fillGraph?'1px':'32px');
for (var i=255; i--;) {
sbC[255-i].style.marginTop = scale; // EQ scale
sbC[255-i].style.height = nHeight;
}
}

this.refreshMetadata = function(oSound) {
var index = null;
var now = oSound.position;
var metadata = oSound._data.metadata.data;
for (var i=0, j=metadata.length; i<j; i++) {
if (now >= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) {
index = i;
break;
}
}
if (index != metadata.currentItem) {
oSound._data.oLink.innerHTML = metadata.mainTitle+' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">'+metadata[index].title+'</span></span>';
self.setPageTitle(metadata[index].title+' | '+metadata.mainTitle);
metadata.currentItem = index;
}
}

this.updateTime = function() {
var str = self.strings['timing'].replace('%s1',self.getTime(this.position,true));
str = str.replace('%s2',self.getTime(self.getDurationEstimate(this),true));
this._data.oTiming.innerHTML = str;
}
this.getTheDamnTarget = function(e) {
return (e.target||e.srcElement||window.event.srcElement);
}
this.withinStatusBar = function(o) {
return (self.isChildOfClass(o,'controls'));
}

this.handleClick = function(e) {
if (e.button == 2) {
if (!pl.config.allowRightClick) pl.stopEvent(e);
return (pl.config.allowRightClick);
}
var o = self.getTheDamnTarget(e);
if (self.dragActive) self.stopDrag();
if (self.withinStatusBar(o)) {
return false;
}
if (o.nodeName.toLowerCase() != 'a') {
o = self.getParentByNodeName(o,'a');
}
if (!o) {
return true;
}
var sURL = o.getAttribute('href');
if (!o.href || (!sm.canPlayURL(o.href) && !self.hasClass(o,'playable')) || self.hasClass(o,'exclude')) {
if (isIE && o.onclick) {
return false;
}
return true; 
}
var soundURL = o.href;
var thisSound = self.getSoundByObject(o);
if (thisSound) {
self.setPageTitle(thisSound._data.originalTitle);
if (thisSound == self.lastSound) {
if (thisSound.readyState != 2) {
if (thisSound.playState != 1) {
thisSound.play();
} else {
thisSound.togglePause();
}
} else {
sm._writeDebug('Warning: sound failed to load (security restrictions, 404 or bad format)',2);
}
} else {
if (self.lastSound) self.stopSound(self.lastSound);
thisSound._data.oTimingBox.appendChild(document.getElementById('spectrum-container'));
thisSound.togglePause(); 
}
} else {
thisSound = sm.createSound({
id:'pagePlayerMP3Sound'+(self.soundCount++),
url:soundURL,
onplay:self.events.play,
onstop:self.events.stop,
onpause:self.events.pause,
onresume:self.events.resume,
onfinish:self.events.finish,
whileloading:self.events.whileloading,
whileplaying:self.events.whileplaying,
onmetadata:self.events.metadata,
onload:self.events.onload
});

var oControls = self.oControls.cloneNode(true);
o.parentNode.appendChild(oControls);
o.parentNode.appendChild(document.getElementById('spectrum-container'));
self.soundsByObject[o.rel] = thisSound;
thisSound._data = {
oLink: o,
oLI: o.parentNode,
oControls: self.getElementsByClassName('controls','div',o.parentNode)[0],
oStatus: self.getElementsByClassName('statusbar','div',o.parentNode)[0],
oLoading: self.getElementsByClassName('loading','div',o.parentNode)[0],
oPosition: self.getElementsByClassName('position','div',o.parentNode)[0],
oTimingBox: self.getElementsByClassName('timing','div',o.parentNode)[0],
oTiming: self.getElementsByClassName('timing','div',o.parentNode)[0].getElementsByTagName('div')[0],
oPeak: document.getElementById('peak'),
oGraph: self.getElementsByClassName('spectrum-box','div',o.parentNode)[0],
nIndex: self.getSoundIndex(o),
className: self.css.sPlaying,
originalTitle: o.innerHTML,
metadata: null
};
thisSound._data.oTimingBox.appendChild(document.getElementById('spectrum-container'));
if (thisSound._data.oLI.getElementsByTagName('ul').length) {
thisSound._data.metadata = new Metadata(thisSound);
}
var str = self.strings['timing'].replace('%s1',self.config.emptyTime);
str = str.replace('%s2',self.config.emptyTime);
thisSound._data.oTiming.innerHTML = str;
self.sounds.push(thisSound);
if (self.lastSound) self.stopSound(self.lastSound);
self.resetGraph.apply(thisSound);
thisSound.play();
}
self.lastSound = thisSound;
return self.stopEvent(e);
}
  
this.handleMouseDown = function(e) {
if (e.button == 2) {
if (!pl.config.allowRightClick) pl.stopEvent(e);
return (pl.config.allowRightClick); 
}
var o = self.getTheDamnTarget(e);
if (!self.withinStatusBar(o)) return true;
self.dragActive = true;
self.lastSound.pause();
self.setPosition(e);
self.addEventHandler(document,'mousemove',self.handleMouseMove);
self.addClass(self.lastSound._data.oControls,'dragging');
self.stopEvent(e);
return false;
}
  
this.handleMouseMove = function(e) {
if (self.dragActive) {
if (self.config.useThrottling) {
var d = new Date();
if (d-self.dragExec>20) {
self.setPosition(e);
} else {
window.clearTimeout(self.dragTimer);
self.dragTimer = window.setTimeout(function(){self.setPosition(e)},20);
}
self.dragExec = d;
} else {
self.setPosition(e);
}
} else {
self.stopDrag();
}
return false;
}
  
this.stopDrag = function(e) {
if (self.dragActive) {
self.removeClass(self.lastSound._data.oControls,'dragging');
self.removeEventHandler(document,'mousemove',self.handleMouseMove);
if (!pl.hasClass(self.lastSound._data.oLI,self.css.sPaused)) {
self.lastSound.resume();
}
self.dragActive = false;
self.stopEvent(e);
return false;
}
}
  
this.handleStatusClick = function(e) {
self.setPosition(e);
if (!pl.hasClass(self.lastSound._data.oLI,self.css.sPaused)) self.resume();
return self.stopEvent(e);
}
  
this.stopEvent = function(e) {
if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
e.preventDefault();
} else if (typeof event != 'undefined' && typeof event.returnValue != 'undefined') {
event.returnValue = false;
}
return false;
}
 
  this.setPosition = function(e) {
    var oThis = self.getTheDamnTarget(e);
    var oControl = oThis;
    while (!self.hasClass(oControl,'controls') && oControl.parentNode) {
      oControl = oControl.parentNode;
    }
    var oSound = self.lastSound;
    var x = parseInt(e.clientX);
    var nMsecOffset = Math.floor((x-self.getOffX(oControl)-4)/(oControl.offsetWidth)*self.getDurationEstimate(oSound));
    if (!isNaN(nMsecOffset)) nMsecOffset = Math.min(nMsecOffset,oSound.duration);
    if (!isNaN(nMsecOffset)) oSound.setPosition(nMsecOffset);
  }

  this.stopSound = function(oSound) {
    sm._writeDebug('stopping sound: '+oSound.sID);
    sm.stop(oSound.sID);
    sm.unload(oSound.sID);
  }

  this.getDurationEstimate = function(oSound) {
    if (oSound.instanceOptions.isMovieStar) {
	  return (oSound.duration);
    } else {
      return (!oSound._data.metadata || !oSound._data.metadata.data.givenDuration?oSound.durationEstimate:oSound._data.metadata.data.givenDuration);
    }
  }

  this.createVUData = function() {
    var i=0;
    var j=0;
	var canvas = vuDataCanvas.getContext('2d');
	var vuGrad = canvas.createLinearGradient(0, 16, 0, 0);
	vuGrad.addColorStop(0,'rgb(0,192,0)');
	vuGrad.addColorStop(0.30,'rgb(0,255,0)');
	vuGrad.addColorStop(0.625,'rgb(255,255,0)');
	vuGrad.addColorStop(0.85,'rgb(255,0,0)');
	var bgGrad = canvas.createLinearGradient(0, 16, 0, 0);
	var outline = 'rgba(0,0,0,0.2)';
	bgGrad.addColorStop(0,outline);
	bgGrad.addColorStop(1,'rgba(0,0,0,0.5)');
    for (i=0; i<16; i++) {
      self.vuMeterData[i] = [];
    }
    for (var i=0; i<16; i++) {
      for (j=0; j<16; j++) {
		vuDataCanvas.setAttribute('width',16);
		vuDataCanvas.setAttribute('height',16);
	    canvas.fillStyle = bgGrad;
 		canvas.fillRect(0,0,7,15);
 		canvas.fillRect(8,0,7,15);
        canvas.fillStyle = vuGrad;
        canvas.fillRect(0,15-i,7,16-(16-i));
        canvas.fillRect(8,15-j,7,16-(16-j));
		canvas.clearRect(0,3,16,1);
		canvas.clearRect(0,7,16,1);
		canvas.clearRect(0,11,16,1);
        self.vuMeterData[i][j] = vuDataCanvas.toDataURL('image/png');
      }
    }
  };

  var vuDataCanvas = null;

  this.testCanvas = function() {
    var c = document.createElement('canvas');
	var ctx = null;
    if (!c || typeof c.getContext == 'undefined') {
	  return null;
    }
    ctx = c.getContext('2d');
	if (!ctx || typeof c.toDataURL != 'function') {
		return null;
	}
	try {
		var ok = c.toDataURL('image/png');
	} catch(e) {
	  return null;	
	}
	return c;
  }

  if (this.config.useFavIcon) {
	vuDataCanvas = self.testCanvas();
	if (vuDataCanvas && (isFirefox || isOpera)) {
	  self.createVUData();
	} else {
	  this.config.useFavIcon = false;
	}
  }

  this.init = function() {
    sm._writeDebug('pagePlayer.init()');
    var oLinks = document.getElementsByTagName('a');
    var foundItems = 0;
    for (var i=0; i<oLinks.length; i++) {
      if ((sm.canPlayURL(oLinks[i].href) || self.hasClass(oLinks[i],'playable')) && !self.hasClass(oLinks[i],'exclude')) {
        oLinks[i].rel = 'pagePlayerMP3Sound'+i;
        self.links[self.links.length] = oLinks[i];
        self.addClass(oLinks[i],self.css.sDefault); 
        foundItems++;
      }
    }
    if (foundItems>0) {
      var oTiming = document.getElementById('sm2_timing');
      self.strings['timing'] = oTiming.innerHTML;
      oTiming.innerHTML = '';
      oTiming.id = '';
      self.addEventHandler(document,'click',self.handleClick);
      self.addEventHandler(document,'mousedown',self.handleMouseDown);
      self.addEventHandler(document,'mouseup',self.stopDrag);
      self.addEventHandler(window,'unload',function(){}); 
    }
    sm._writeDebug('pagePlayer.init(): Found '+foundItems+' relevant items.');
    if (self.config.autoStart) {
      pl.handleClick({target:pl.links[0]});
    }
  }

var Metadata = function(oSound) {
  var self = this;
  var oLI = oSound._data.oLI;
  var o = oLI.getElementsByTagName('ul')[0];
  var oItems = o.getElementsByTagName('li');
  var oTemplate = document.createElement('div');
  oTemplate.innerHTML = '<span>&nbsp;</span>';
  oTemplate.className = 'annotation';
  var oTemplate2 = document.createElement('div');
  oTemplate2.innerHTML = '<span>&nbsp;</span>';
  oTemplate2.className = 'annotation alt';

  var oTemplate3 = document.createElement('div');
  oTemplate3.className = 'note';

  this.totalTime = 0;
  this.strToTime = function(sTime) {
    var segments = sTime.split(':');
    var seconds = 0;
    for (var i=segments.length; i--;) {
      seconds += parseInt(segments[i])*Math.pow(60,segments.length-1-i,10); 
    }
    return seconds;
  }
  this.data = [];
  this.data.givenDuration = null;
  this.data.currentItem = null;
  this.data.mainTitle = oSound._data.oLink.innerHTML;
  for (var i=0; i<oItems.length; i++) {
    this.data[i] = {
      o: null,
      title: oItems[i].getElementsByTagName('p')[0].innerHTML,
      startTime: oItems[i].getElementsByTagName('span')[0].innerHTML,
      startSeconds: self.strToTime(oItems[i].getElementsByTagName('span')[0].innerHTML.replace(/[()]/g,'')),
      duration: 0,
      durationMS: null,
      startTimeMS: null,
      endTimeMS: null,
      oNote: null
    }
  }
  var oDuration = pl.getElementsByClassName('duration','div',oLI);
  this.data.givenDuration = (oDuration.length?self.strToTime(oDuration[0].innerHTML)*1000:0);
  for (i=0; i<this.data.length; i++) {
    this.data[i].duration = parseInt(this.data[i+1]?this.data[i+1].startSeconds:(self.data.givenDuration?self.data.givenDuration:oSound.durationEstimate)/1000)-this.data[i].startSeconds;
    this.data[i].startTimeMS = this.data[i].startSeconds*1000;
    this.data[i].durationMS = this.data[i].duration*1000;
    this.data[i].endTimeMS = this.data[i].startTimeMS+this.data[i].durationMS;
    this.totalTime += this.data[i].duration;
  }
  this.createElements = function() {
    var oFrag = document.createDocumentFragment();
    var oNode = null;
    var oNodeSpan = null;
    var oNode2 = null;
    for (var i=0; i<self.data.length; i++) {
      oNode = (i%2==0?oTemplate:oTemplate2).cloneNode(true);
      oNodeSpan = oNode.getElementsByTagName('span')[0];
      oNode.rel = i;
      self.data[i].o = oNode;
      oNode2 = oTemplate3.cloneNode(true);
      if (i%2==0) oNode2.className = 'note alt';
      oNode2.innerHTML = this.data[i].title;
      oNode.onmouseover = self.mouseover;
      oNode.onmouseout = self.mouseout;
      this.data[i].oNote = oNode2;
      oSound._data.oControls.appendChild(oNode2);
      oFrag.appendChild(oNode);
    }
    self.refresh();
    oSound._data.oStatus.appendChild(oFrag);
  }

  this.refresh = function() {
    var offset = 0;
    var relWidth = null;
    var duration = (self.data.givenDuration?self.data.givenDuration:oSound.durationEstimate);
    for (var i=0; i<self.data.length; i++) {
      if (duration) {
        relWidth = (((self.data[i].duration*1000)/duration)*100);
        self.data[i].o.style.left = (offset?offset+'%':'-2px');
        self.data[i].oNote.style.left = (offset?offset+'%':'0px');
        offset += relWidth;
      }
    }
  }

  this.mouseover = function(e) {
    self.data[this.rel].oNote.style.visibility = 'hidden';
    self.data[this.rel].oNote.style.display = 'inline-block';
    self.data[this.rel].oNote.style.marginLeft = -parseInt(self.data[this.rel].oNote.offsetWidth/2)+'px';
    self.data[this.rel].oNote.style.visibility = 'visible';
  }

  this.mouseout = function() { 
    self.data[this.rel].oNote.style.display = 'none';
  }

  this.createElements();
  this.refresh();
  
}

  this.initDOM = function() {
    var sb = self.getElementsByClassName('spectrum-box','div',document.documentElement)[0];
    if (sm.flashVersion >= 9) {
      self.addClass(self.getElementsByClassName('playlist','ul',document.documentElement)[0],self.cssBase);
      var sbC = sb.getElementsByTagName('div')[0];
      var oF = document.createDocumentFragment();
      var oClone = null;
      for (var i=256; i--;) {
        oClone = sbC.cloneNode(false);
        oClone.style.left = (i)+'px';
        oF.appendChild(oClone);
      }
      sb.removeChild(sbC);
      sb.appendChild(oF);
    }
    this.oControls = document.getElementById('control-template').cloneNode(true);
    this.oControls.id = '';
    this.init();
  }

}

var pagePlayer = new PagePlayer(typeof PP_CONFIG != 'undefined'?PP_CONFIG:null);
soundManager.onready(function() { if (soundManager.supported()) {pagePlayer.initDOM();}
});