From 8868a6906f90181bdda0b55163556ab9d6571a53 Mon Sep 17 00:00:00 2001 From: yomguy Date: Thu, 24 Nov 2011 11:19:44 +0100 Subject: [PATCH] player: try html5, update soundmanager2 to 2.97a.20111030 --- .../timeside/js/libs/soundmanager2-jsmin.js | 103 + .../js/libs/soundmanager2-nodebug-jsmin.js | 151 +- .../timeside/js/libs/soundmanager2-nodebug.js | 2184 +++++++++ .../htdocs/timeside/js/libs/soundmanager2.js | 4207 +++++++++++------ telemeta/htdocs/timeside/js/player.js | 8 +- telemeta/htdocs/timeside/js/timeside.js | 2 +- .../telemeta_default/mediaitem_detail.html | 6 +- 7 files changed, 5225 insertions(+), 1436 deletions(-) create mode 100755 telemeta/htdocs/timeside/js/libs/soundmanager2-jsmin.js create mode 100755 telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug.js diff --git a/telemeta/htdocs/timeside/js/libs/soundmanager2-jsmin.js b/telemeta/htdocs/timeside/js/libs/soundmanager2-jsmin.js new file mode 100755 index 00000000..277efd1e --- /dev/null +++ b/telemeta/htdocs/timeside/js/libs/soundmanager2-jsmin.js @@ -0,0 +1,103 @@ +/** @license + + + SoundManager 2: JavaScript Sound for the Web + ---------------------------------------------- + http://schillmania.com/projects/soundmanager2/ + + Copyright (c) 2007, Scott Schiller. All rights reserved. + Code provided under the BSD License: + http://schillmania.com/projects/soundmanager2/license.txt + + V2.97a.20111030 +*/ +(function(S){function T(T,fa){function k(b){return function(a){return!this._t||!this._t._a?(this._t&&this._t.sID?c._wD(h+"ignoring "+a.type+": "+this._t.sID):c._wD(h+"ignoring "+a.type),null):b.call(this,a)}}this.flashVersion=8;this.debugMode=true;this.debugFlash=false;this.useConsole=true;this.waitForWindowLoad=this.consoleOnly=false;this.bgColor="#ffffff";this.useHighPerformance=false;this.flashPollingInterval=null;this.flashLoadTimeout=1E3;this.wmode=null;this.allowScriptAccess="always";this.useFlashBlock= +false;this.useHTML5Audio=true;this.html5Test=/^(probably|maybe)$/i;this.preferFlash=true;this.noSWFCache=false;this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:true},mp4:{related:["aac","m4a"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:false},ogg:{type:["audio/ogg; codecs=vorbis"],required:false},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave", +"audio/x-wav"],required:false}};this.defaultOptions={autoLoad:false,stream:true,autoPlay:false,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfailure:null,onfinish:null,multiShot:true,multiShotEvents:false,position:null,pan:0,type:null,usePolicyFile:false,volume:100};this.flash9Options={isMovieStar:null,usePeakData:false,useWaveformData:false,useEQData:false,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3, +serverURL:null,onconnect:null,duration:null};this.movieID="sm2-container";this.id=fa||"sm2movie";this.swfCSS={swfBox:"sm2-object-box",swfDefault:"movieContainer",swfError:"swf_error",swfTimedout:"swf_timedout",swfLoaded:"swf_loaded",swfUnblocked:"swf_unblocked",sm2Debug:"sm2_debug",highPerf:"high_performance",flashDebug:"flash_debug"};this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20111030";this.movieURL=this.version=null;this.url=T||null;this.altURL= +null;this.enabled=this.swfLoaded=false;this.oMC=this.o=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.specialWmodeCase=this.muted=false;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:false,peakData:false,waveformData:false,eqData:false,movieStar:false};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)", +localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};var J;try{J=typeof Audio!=="undefined"&&typeof(new Audio).canPlayType!=="undefined"}catch(Xa){J=false}this.hasHTML5=J;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=false;var ya,c=this,h="HTML5::",u,q=navigator.userAgent,i=S,K=i.location.href.toString(),g=document,ga,U,j,y=[],ha=true,r,L=false,M=false,m=false,v=false,ia=false,l,Qa=0,N,s,ja,C,D,V,za,ka,B,W,X,E,la,Y,Z,F,Aa, +ma,Ra=["log","info","warn","error"],Ba,$,Ca,O=null,na=null,n,oa,G,Da,aa,ba,pa,o,ca=false,qa=false,Ea,Fa,w=null,Ga,da,P,z,ra,sa,Ha,p,Ia=Array.prototype.slice,Q=false,t,ea,Ja,x,Ka,ta=q.match(/(ipad|iphone|ipod)/i),Sa=q.match(/firefox/i),Ta=q.match(/droid/i),A=q.match(/msie/i),Ua=q.match(/webkit/i),R=q.match(/safari/i)&&!q.match(/chrome/i),Va=q.match(/opera/i);J=q.match(/(mobile|pre\/|xoom)/i)||ta;var ua=!K.match(/usehtml5audio/i)&&!K.match(/sm2\-ignorebadua/i)&&R&&q.match(/OS X 10_6_([3-7])/i),va=typeof console!== +"undefined"&&typeof console.log!=="undefined",wa=typeof g.hasFocus!=="undefined"?g.hasFocus():null,H=R&&typeof g.hasFocus==="undefined",La=!H,Ma=/(mp3|mp4|mpa)/i,I=g.location?g.location.protocol.match(/http/i):null,Na=!I?"http://":"",Oa=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|mp4v|3gp|3g2)\s*(?:$|;)/i,Pa="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,mp4v,3gp,3g2".split(","),Wa=RegExp("\\.("+Pa.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL= +!I;this._global_a=null;if(J&&(c.useHTML5Audio=true,c.preferFlash=false,ta))Q=c.ignoreFlash=true;this.supported=this.ok=function(){return w?m&&!v:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return u(c)||g[c]||i[c]};this.createSound=function(b){function a(){e=aa(e);c.sounds[d.id]=new ya(d);c.soundIDs.push(d.id);return c.sounds[d.id]}var e=null,f=null,d=null;if(!m||!c.ok())return pa("soundManager.createSound(): "+n(!m?"notReady":"notOK")),false;arguments.length===2&&(b={id:arguments[0],url:arguments[1]}); +d=e=s(b);d.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+n("badID",d.id),2);c._wD("soundManager.createSound(): "+d.id+" ("+d.url+")",1);if(o(d.id,true))return c._wD("soundManager.createSound(): "+d.id+" exists",1),c.sounds[d.id];if(da(d))f=a(),c._wD("Loading sound "+d.id+" via HTML5"),f._setup_html5(d);else{if(j>8){if(d.isMovieStar===null)d.isMovieStar=d.serverURL||(d.type?d.type.match(Oa):false)||d.url.match(Wa);d.isMovieStar&&c._wD("soundManager.createSound(): using MovieStar handling"); +if(d.isMovieStar){if(d.usePeakData)l("noPeak"),d.usePeakData=false;d.loops>1&&l("noNSLoop")}}d=ba(d,"soundManager.createSound(): ");f=a();if(j===8)c.o._createSound(d.id,d.loops||1,d.usePolicyFile);else if(c.o._createSound(d.id,d.url,d.usePeakData,d.useWaveformData,d.useEQData,d.isMovieStar,d.isMovieStar?d.bufferTime:false,d.loops||1,d.serverURL,d.duration||null,d.autoPlay,true,d.autoLoad,d.usePolicyFile),!d.serverURL)f.connected=true,d.onconnect&&d.onconnect.apply(f);!d.serverURL&&(d.autoLoad||d.autoPlay)&& +f.load(d)}!d.serverURL&&d.autoPlay&&f.play();return f};this.destroySound=function(b,a){if(!o(b))return false;var e=c.sounds[b],f;e._iO={};e.stop();e.unload();for(f=0;f8&&b.match(Oa)||b.match(c.mimePattern)):null};this.canPlayURL=function(b){var a;c.hasHTML5&&(a=P({url:b}));return!w||a?a:b?!!b.match(c.filePattern):null};this.canPlayLink=function(b){return typeof b.type!=="undefined"&&b.type&&c.canPlayMIME(b.type)?true:c.canPlayURL(b.href)}; +this.getSoundById=function(b,a){if(!b)throw Error("soundManager.getSoundById(): sID is null/undefined");var e=c.sounds[b];!e&&!a&&c._wD('"'+b+'" is an invalid sound ID.',2);return e};this.onready=function(b,a){if(b&&b instanceof Function)return m&&c._wD(n("queue","onready")),a||(a=i),ja("onready",b,a),C(),true;else throw n("needFunction","onready");};this.ontimeout=function(b,a){if(b&&b instanceof Function)return m&&c._wD(n("queue","ontimeout")),a||(a=i),ja("ontimeout",b,a),C({type:"ontimeout"}), +true;else throw n("needFunction","ontimeout");};this._wD=this._writeDebug=function(b,a,e){var f,d;if(!c.debugMode)return false;typeof e!=="undefined"&&e&&(b=b+" | "+(new Date).getTime());if(va&&c.useConsole){e=Ra[a];if(typeof console[e]!=="undefined")console[e](b);else console.log(b);if(c.useConsoleOnly)return true}try{f=u("soundmanager-debug");if(!f)return false;d=g.createElement("div");if(++Qa%2===0)d.className="sm2-alt";a=typeof a==="undefined"?0:parseInt(a,10);d.appendChild(g.createTextNode(b)); +if(a){if(a>=2)d.style.fontWeight="bold";if(a===3)d.style.color="#ff3333"}f.insertBefore(d,f.firstChild)}catch(Ya){}return true};this._debug=function(){var b,a;l("currentObj",1);for(b=0,a=c.soundIDs.length;b0&&a.position===a.duration)c._wD('SMSound.play(): "'+a.sID+'": Sound at end, resetting to position:0'),a._iO.position=0;if(a.paused&&a.position&&a.position>0)c._wD('SMSound.play(): "'+a.sID+'" is resuming from paused state',1),a.resume();else{c._wD('SMSound.play(): "'+a.sID+'" is starting to play');a.playState=1;a.paused=false;(!a.instanceCount||a._iO.multiShotEvents||!a.isHTML5&&j>8&&!a.getAutoPlay())&&a.instanceCount++;a.position=typeof a._iO.position!=="undefined"&& +!isNaN(a._iO.position)?a._iO.position:0;if(!a.isHTML5)a._iO=ba(aa(a._iO));if(a._iO.onplay&&e)a._iO.onplay.apply(a),a._onplay_called=true;a.setVolume(a._iO.volume,true);a.setPan(a._iO.pan,true);a.isHTML5?(d(),f=a._setup_html5(),a.setPosition(a._iO.position),f.play()):c.o._start(a.sID,a._iO.loops||1,j===9?a._iO.position:a._iO.position/1E3)}return a};this.stop=function(b){if(a.playState===1){a._onbufferchange(0);a.resetOnPosition(0);a.paused=false;if(!a.isHTML5)a.playState=0;a._iO.onstop&&a._iO.onstop.apply(a); +if(a.isHTML5){if(a._a)a.setPosition(0),a._a.pause(),a.playState=0,a._onTimer(),f()}else c.o._stop(a.sID,b),a._iO.serverURL&&a.unload();a.instanceCount=0;a._iO={}}return a};this.setAutoPlay=function(b){c._wD("sound "+a.sID+" turned autoplay "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(c.o._setAutoPlay(a.sID,b),b&&!a.instanceCount&&a.readyState===1&&(a.instanceCount++,c._wD("sound "+a.sID+" incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition= +function(b){b===void 0&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a.resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a)if(a._html5_canplay){if(a._a.currentTime!==b){c._wD("setPosition("+b+"): setting position");try{a._a.currentTime=b,(a.playState===0||a.paused)&&a._a.pause()}catch(e){c._wD("setPosition("+b+"): setting position failed: "+e.message,2)}}}else c._wD("setPosition("+b+"): delaying, sound not ready")}else b= +j===9?a.position:b,a.readyState&&a.readyState!==2&&c.o._setPosition(a.sID,b,a.paused||!a.playState);a.isHTML5&&a.paused&&a._onTimer(true);return a};this.pause=function(b){if(a.paused||a.playState===0&&a.readyState!==1)return a;c._wD("SMSound.pause()");a.paused=true;a.isHTML5?(a._setup_html5().pause(),f()):(b||b===void 0)&&c.o._pause(a.sID);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){if(!a.paused)return a;c._wD("SMSound.resume()");a.paused=false;a.playState=1;a.isHTML5?(a._setup_html5().play(), +d()):(a._iO.isMovieStar&&a.setPosition(a.position),c.o._pause(a.sID));!a._onplay_called&&a._iO.onplay?(a._iO.onplay.apply(a),a._onplay_called=true):a._iO.onresume&&a._iO.onresume.apply(a);return a};this.togglePause=function(){c._wD("SMSound.togglePause()");if(a.playState===0)return a.play({position:j===9&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,d){typeof b==="undefined"&&(b=0);typeof d==="undefined"&&(d=false);a.isHTML5||c.o._setPan(a.sID, +b);a._iO.pan=b;if(!d)a.pan=b,a.options.pan=b;return a};this.setVolume=function(b,d){typeof b==="undefined"&&(b=100);typeof d==="undefined"&&(d=false);if(a.isHTML5){if(a._a)a._a.volume=Math.max(0,Math.min(1,b/100))}else c.o._setVolume(a.sID,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;if(!d)a.volume=b,a.options.volume=b;return a};this.mute=function(){a.muted=true;if(a.isHTML5){if(a._a)a._a.muted=true}else c.o._setVolume(a.sID,0);return a};this.unmute=function(){a.muted=false;var b=typeof a._iO.volume!== +"undefined";if(a.isHTML5){if(a._a)a._a.muted=false}else c.o._setVolume(a.sID,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=function(c,b,d){a._onPositionItems.push({position:c,method:b,scope:typeof d!=="undefined"?d:a,fired:false});return a};this.processOnPosition=function(){var b,d;b=a._onPositionItems.length;if(!b||!a.playState||a._onPositionFired>=b)return false;for(;b--;)if(d=a._onPositionItems[b],!d.fired&&a.position>= +d.position)d.fired=true,c._onPositionFired++,d.method.apply(d.scope,[d.position]);return true};this.resetOnPosition=function(b){var d,e;d=a._onPositionItems.length;if(!d)return false;for(;d--;)if(e=a._onPositionItems[d],e.fired&&b<=e.position)e.fired=false,c._onPositionFired--;return true};d=function(){a.isHTML5&&Ea(a)};f=function(){a.isHTML5&&Fa(a)};e=function(){a._onPositionItems=[];a._onPositionFired=0;a._hasTimer=null;a._onplay_called=false;a._a=null;a._html5_canplay=false;a.bytesLoaded=null; +a.bytesTotal=null;a.position=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.failures=0;a.loaded=false;a.playState=0;a.paused=false;a.readyState=0;a.muted=false;a.isBuffering=false;a.instanceOptions={};a.instanceCount=0;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.eqData=[];a.eqData.left=[];a.eqData.right=[]};e();this._onTimer=function(b){var d={};if(a._hasTimer||b)return a._a&&(b||(a.playState>0||a.readyState===1)&&!a.paused)?(a.duration=a._get_html5_duration(), +a.durationEstimate=a.duration,b=a._a.currentTime?a._a.currentTime*1E3:0,a._whileplaying(b,d,d,d,d),true):(c._wD('_onTimer: Warn for "'+a.sID+'": '+(!a._a?"Could not find element. ":"")+(a.playState===0?"playState bad, 0?":"playState = "+a.playState+", OK")),false)};this._get_html5_duration=function(){var c=a._a?a._a.duration*1E3:a._iO?a._iO.duration:void 0;return c&&!isNaN(c)&&c!==Infinity?c:a._iO?a._iO.duration:null};this._setup_html5=function(b){var b=s(a._iO,b),d=Q?c._global_a:a._a,f=decodeURI(b.url), +g=d&&d._t?d._t.instanceOptions:null;if(d){if(d._t&&g.url===b.url&&(!a._lastURL||a._lastURL===g.url))return d;c._wD("setting new URL on existing object: "+f+(a._lastURL?", old URL: "+a._lastURL:""));Q&&d._t&&d._t.playState&&b.url!==g.url&&d._t.stop();e();d.src=b.url;a.url=b.url;a._lastURL=b.url;d._called_load=false}else{c._wD("creating HTML5 Audio() element with URL: "+f);d=new Audio(b.url);d._called_load=false;if(Ta)d._called_load=true;if(Q)c._global_a=d}a.isHTML5=true;a._a=d;d._t=a;a._add_html5_events(); +d.loop=b.loops>1?"loop":"";b.autoLoad||b.autoPlay?(d.autobuffer="auto",d.preload="auto",a.load(),d._called_load=true):(d.autobuffer=false,d.preload="none");d.loop=b.loops>1?"loop":"";return d};this._add_html5_events=function(){if(a._a._added_events)return false;var b;c._wD(h+"adding event listeners: "+a.sID);a._a._added_events=true;for(b in x)x.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,x[b],false);return true};this._remove_html5_events=function(){var b;c._wD(h+"removing event listeners: "+ +a.sID);a._a._added_events=false;for(b in x)x.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,x[b],false)};this._onload=function(b){b=!!b;c._wD('SMSound._onload(): "'+a.sID+'"'+(b?" loaded.":" failed to load? - "+a.url),b?1:2);!b&&!a.isHTML5&&(c.sandbox.noRemote===true&&c._wD("SMSound._onload(): "+n("noNet"),1),c.sandbox.noLocal===true&&c._wD("SMSound._onload(): "+n("noLocal"),1));a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0);a._iO.onload&&a._iO.onload.apply(a,[b]);return true};this._onbufferchange= +function(b){if(a.playState===0)return false;if(b&&a.isBuffering||!b&&!a.isBuffering)return false;a.isBuffering=b===1;a._iO.onbufferchange&&(c._wD("SMSound._onbufferchange(): "+b),a._iO.onbufferchange.apply(a));return true};this._onsuspend=function(){a._iO.onsuspend&&(c._wD("SMSound._onsuspend()"),a._iO.onsuspend.apply(a));return true};this._onfailure=function(b,d,e){a.failures++;c._wD('SMSound._onfailure(): "'+a.sID+'" count '+a.failures);if(a._iO.onfailure&&a.failures===1)a._iO.onfailure(a,b,d,e); +else c._wD("SMSound._onfailure(): ignoring")};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a.resetOnPosition(0);if(a.instanceCount){a.instanceCount--;if(!a.instanceCount)a.playState=0,a.paused=false,a.instanceCount=0,a.instanceOptions={},a._iO={},f();if((!a.instanceCount||a._iO.multiShotEvents)&&b)c._wD('SMSound._onfinish(): "'+a.sID+'"'),b.apply(a)}};this._whileloading=function(c,b,d,e){a.bytesLoaded=c;a.bytesTotal=b;a.duration=Math.floor(d);a.bufferLength=e;if(a._iO.isMovieStar)a.durationEstimate= +a.duration;else if(a.durationEstimate=a._iO.duration?a.duration>a._iO.duration?a.duration:a._iO.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10),a.durationEstimate===void 0)a.durationEstimate=a.duration;a.readyState!==3&&a._iO.whileloading&&a._iO.whileloading.apply(a)};this._whileplaying=function(c,b,d,e,f){if(isNaN(c)||c===null)return false;a.position=c;a.processOnPosition();if(!a.isHTML5&&j>8){if(a._iO.usePeakData&&typeof b!=="undefined"&&b)a.peakData={left:b.leftPeak,right:b.rightPeak}; +if(a._iO.useWaveformData&&typeof d!=="undefined"&&d)a.waveformData={left:d.split(","),right:e.split(",")};if(a._iO.useEQData&&typeof f!=="undefined"&&f&&f.leftEQ&&(c=f.leftEQ.split(","),a.eqData=c,a.eqData.left=c,typeof f.rightEQ!=="undefined"&&f.rightEQ))a.eqData.right=f.rightEQ.split(",")}a.playState===1&&(!a.isHTML5&&j===8&&!a.position&&a.isBuffering&&a._onbufferchange(0),a._iO.whileplaying&&a._iO.whileplaying.apply(a));return true};this._onid3=function(b,d){c._wD('SMSound._onid3(): "'+this.sID+ +'" ID3 data received.');var e=[],f,g;for(f=0,g=b.length;f0&&(c._wD("SMSound._ondataerror(): "+ +b),a._iO.ondataerror&&a._iO.ondataerror.apply(a))}};Y=function(){return g.body||g._docElement||g.getElementsByTagName("div")[0]};u=function(b){return g.getElementById(b)};s=function(b,a){var e={},f,d;for(f in b)b.hasOwnProperty(f)&&(e[f]=b[f]);f=typeof a==="undefined"?c.defaultOptions:a;for(d in f)f.hasOwnProperty(d)&&typeof e[d]==="undefined"&&(e[d]=f[d]);return e};p=function(){function b(a){var a=Ia.call(a),b=a.length;c?(a[1]="on"+a[1],b>3&&a.pop()):b===3&&a.push(false);return a}function a(a,b){var g= +a.shift(),j=[f[b]];if(c)g[j](a[0],a[1]);else g[j].apply(g,a)}var c=i.attachEvent,f={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){a(b(arguments),"add")},remove:function(){a(b(arguments),"remove")}}}();x={abort:k(function(){c._wD(h+"abort: "+this._t.sID)}),canplay:k(function(){if(this._t._html5_canplay)return true;this._t._html5_canplay=true;c._wD(h+"canplay: "+this._t.sID+", "+this._t.url);this._t._onbufferchange(0);var b=!isNaN(this._t.position)? +this._t.position/1E3:null;if(this._t.position&&this.currentTime!==b){c._wD(h+"canplay: setting position to "+b);try{this.currentTime=b}catch(a){c._wD(h+"setting position failed: "+a.message,2)}}}),load:k(function(){this._t.loaded||(this._t._onbufferchange(0),this._t._whileloading(this._t.bytesTotal,this._t.bytesTotal,this._t._get_html5_duration()),this._t._onload(true))}),emptied:k(function(){c._wD(h+"emptied: "+this._t.sID)}),ended:k(function(){c._wD(h+"ended: "+this._t.sID);this._t._onfinish()}), +error:k(function(){c._wD(h+"error: "+this.error.code);this._t._onload(false)}),loadeddata:k(function(){var b=this._t,a=b.bytesTotal||1;c._wD(h+"loadeddata: "+this._t.sID);if(!b._loaded&&!R)b.duration=b._get_html5_duration(),b._whileloading(a,a,b._get_html5_duration()),b._onload(true)}),loadedmetadata:k(function(){c._wD(h+"loadedmetadata: "+this._t.sID)}),loadstart:k(function(){c._wD(h+"loadstart: "+this._t.sID);this._t._onbufferchange(1)}),play:k(function(){c._wD(h+"play: "+this._t.sID+", "+this._t.url); +this._t._onbufferchange(0)}),playing:k(function(){c._wD(h+"playing: "+this._t.sID+", "+this._t.url);this._t._onbufferchange(0)}),progress:k(function(b){if(this._t.loaded)return false;var a,e,f;f=0;var d=b.type==="progress";e=b.target.buffered;var g=b.loaded||0,xa=b.total||1;if(e&&e.length){for(a=e.length;a--;)f=e.end(a)-e.start(a);g=f/b.target.duration;if(d&&e.length>1){f=[];e=e.length;for(a=0;a1&&b.stream)l("as2loop"),b.stream=false;return b};ba=function(b,a){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))c._wD((a||"")+n("policy")),b.usePolicyFile=true;return b};pa=function(b){typeof console!=="undefined"&&typeof console.warn!=="undefined"?console.warn(b):c._wD(b)};ga=function(){return false}; +Ba=function(b){for(var a in b)b.hasOwnProperty(a)&&typeof b[a]==="function"&&(b[a]=ga)};$=function(b){typeof b==="undefined"&&(b=false);if(v||b)l("smFail",2),c.disable(b)};Ca=function(b){var a=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(a=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&b.lastIndexOf("/")!==-1?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+(new Date).getTime());return b};ka=function(){j=parseInt(c.flashVersion, +10);if(j!==8&&j!==9)c._wD(n("badFV",j,8)),c.flashVersion=j=8;var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";if(c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&j<9)c._wD(n("needfl9")),c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":j===9?" (AS3/Flash 9)":" (AS2/Flash 8)");j>8?(c.defaultOptions=s(c.defaultOptions,c.flash9Options),c.features.buffering=true,c.defaultOptions=s(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+Pa.join("|")+ +")(\\?.*)?$","i"),c.features.movieStar=true):c.features.movieStar=false;c.filePattern=c.filePatterns[j!==8?"flash9":"flash8"];c.movieURL=(j===8?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=j>8};Aa=function(b,a){if(!c.o)return false;c.o._setPolling(b,a)};ma=function(){if(c.debugURLParam.test(K))c.debugMode=true;if(u(c.debugID))return false;var b,a,e,f;if(c.debugMode&&!u(c.debugID)&&(!va||!c.useConsole||c.useConsole&& +va&&!c.consoleOnly)){b=g.createElement("div");b.id=c.debugID+"-toggle";a={position:"fixed",bottom:"0px",right:"0px",width:"1.2em",height:"1.2em",lineHeight:"1.2em",margin:"2px",textAlign:"center",border:"1px solid #999",cursor:"pointer",background:"#fff",color:"#333",zIndex:10001};b.appendChild(g.createTextNode("-"));b.onclick=Da;b.title="Toggle SM2 debug console";if(q.match(/msie 6/i))b.style.position="absolute",b.style.cursor="hand";for(f in a)a.hasOwnProperty(f)&&(b.style[f]=a[f]);a=g.createElement("div"); +a.id=c.debugID;a.style.display=c.debugMode?"block":"none";if(c.debugMode&&!u(b.id)){try{e=Y(),e.appendChild(b)}catch(d){throw Error(n("domError")+" \n"+d.toString());}e.appendChild(a)}}};o=this.getSoundById;l=function(b,a){return b?c._wD(n(b),a):""};if(K.indexOf("sm2-debug=alert")+1&&c.debugMode)c._wD=function(b){S.alert(b)};Da=function(){var b=u(c.debugID),a=u(c.debugID+"-toggle");if(!b)return false;ha?(a.innerHTML="+",b.style.display="none"):(a.innerHTML="-",b.style.display="block");ha=!ha};r=function(b, +a,c){if(typeof sm2Debugger!=="undefined")try{sm2Debugger.handleEvent(b,a,c)}catch(f){}return true};G=function(){var b=[];c.debugMode&&b.push(c.swfCSS.sm2Debug);c.debugFlash&&b.push(c.swfCSS.flashDebug);c.useHighPerformance&&b.push(c.swfCSS.highPerf);return b.join(" ")};oa=function(){var b=n("fbHandler"),a=c.getMoviePercent(),e=c.swfCSS,f={type:"FLASHBLOCK"};if(c.html5Only)return false;if(c.ok()){if(c.didFlashBlock&&c._wD(b+": Unblocked"),c.oMC)c.oMC.className=[G(),e.swfDefault,e.swfLoaded+(c.didFlashBlock? +" "+e.swfUnblocked:"")].join(" ")}else{if(w)c.oMC.className=G()+" "+e.swfDefault+" "+(a===null?e.swfTimedout:e.swfError),c._wD(b+": "+n("fbTimeout")+(a?" ("+n("fbLoaded")+")":""));c.didFlashBlock=true;C({type:"ontimeout",ignoreInit:true,error:f});F(f)}};ja=function(b,a,c){typeof y[b]==="undefined"&&(y[b]=[]);y[b].push({method:a,scope:c||null,fired:false})};C=function(b){b||(b={type:"onready"});if(!m&&b&&!b.ignoreInit)return false;if(b.type==="ontimeout"&&c.ok())return false;var a={success:b&&b.ignoreInit? +c.ok():!v},e=b&&b.type?y[b.type]||[]:[],f=[],d,g=[a],j=w&&c.useFlashBlock&&!c.ok();if(b.error)g[0].error=b.error;for(a=0,d=e.length;a'}if(L&&M)return false;if(c.html5Only)return ka(),e(),c.oMC= +u(c.movieID),U(),M=L=true,false;var d=a||c.url,j=c.altURL||d,h;h=Y();var i,o,k=G(),m,p=null,p=(p=g.getElementsByTagName("html")[0])&&p.dir&&p.dir.match(/rtl/i),b=typeof b==="undefined"?c.id:b;ka();c.url=Ca(I?d:j);a=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(c.wmode!==null&&(q.match(/msie 8/i)||!A&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.specialWmodeCase=true,l("spcWmode"),c.wmode=null;h={name:b,id:b,src:a,width:"auto",height:"auto",quality:"high", +allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Na+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)h.FlashVars="debug=1";c.wmode||delete h.wmode;if(A)d=g.createElement("div"),o=['',f("movie",a),f("AllowScriptAccess",c.allowScriptAccess),f("quality",h.quality),c.wmode?f("wmode",c.wmode):"",f("bgcolor",c.bgColor),f("hasPriority","true"),c.debugFlash?f("FlashVars",h.FlashVars):"",""].join("");else for(i in d=g.createElement("embed"),h)h.hasOwnProperty(i)&&d.setAttribute(i,h[i]);ma();k=G();if(h=Y())if(c.oMC=u(c.movieID)||g.createElement("div"),c.oMC.id){m=c.oMC.className;c.oMC.className=(m?m+" ":c.swfCSS.swfDefault)+(k?" "+k:"");c.oMC.appendChild(d); +if(A)i=c.oMC.appendChild(g.createElement("div")),i.className=c.swfCSS.swfBox,i.innerHTML=o;M=true}else{c.oMC.id=c.movieID;c.oMC.className=c.swfCSS.swfDefault+" "+k;i=k=null;if(!c.useFlashBlock)if(c.useHighPerformance)k={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(k={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},p)k.left=Math.abs(parseInt(k.left,10))+"px";if(Ua)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(m in k)k.hasOwnProperty(m)&& +(c.oMC.style[m]=k[m]);try{A||c.oMC.appendChild(d);h.appendChild(c.oMC);if(A)i=c.oMC.appendChild(g.createElement("div")),i.className=c.swfCSS.swfBox,i.innerHTML=o;M=true}catch(r){throw Error(n("domError")+" \n"+r.toString());}}L=true;e();c._wD("soundManager::createMovie(): Trying to load "+a+(!I&&c.altURL?" (alternate URL)":""),1);return true};X=function(){if(c.html5Only)return Z(),false;if(c.o)return false;c.o=c.getMovie(c.id);if(!c.o)O?(A?c.oMC.innerHTML=na:c.oMC.appendChild(O),O=null,L=true):Z(c.id, +c.url),c.o=c.getMovie(c.id);c.o&&l("waitEI");c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return true};V=function(){setTimeout(za,1E3)};za=function(){if(ca)return false;ca=true;p.remove(i,"load",V);if(H&&!wa)return l("waitFocus"),false;var b;m||(b=c.getMoviePercent(),c._wD(n("waitImpatient",b===100?" (SWF loaded)":b>0?" (SWF "+b+"% loaded)":"")));setTimeout(function(){b=c.getMoviePercent();m||(c._wD("soundManager: No Flash response within expected time.\nLikely causes: "+(b===0? +"Loading "+c.movieURL+" may have failed (and/or Flash "+j+"+ not present?), ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+n("checkSWF"):""),2),!I&&b&&(l("localFail",2),c.debugFlash||l("tryDebug",2)),b===0&&c._wD(n("swf404",c.url)),r("flashtojs",false,": Timed out"+I?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));!m&&La&&(b===null?c.useFlashBlock||c.flashLoadTimeout===0?(c.useFlashBlock&&oa(),l("waitForever")):$(true):c.flashLoadTimeout===0?l("waitForever"): +$(true))},c.flashLoadTimeout)};B=function(){function b(){p.remove(i,"focus",B);p.remove(i,"load",B)}if(wa||!H)return b(),true;wa=La=true;c._wD("soundManager::handleFocus()");R&&H&&p.remove(i,"mousemove",B);ca=false;b();return true};Ka=function(){var b,a=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&a.push(b+": "+c.html5[b]+(!c.html5[b]&&t&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&t?" (preferring flash)":!c.html5[b]?" ("+(c.audioFormats[b].required? +"required, ":"")+"and no flash support)":""));c._wD("-- SoundManager 2: HTML5 support tests ("+c.html5Test+"): "+a.join(", ")+" --",1)}};N=function(b){if(m)return false;if(c.html5Only)return c._wD("-- SoundManager 2: loaded --"),m=true,D(),r("onload",true),true;var a;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())m=true,v&&(a={type:!t&&w?"NO_FLASH":"INIT_TIMEOUT"});c._wD("-- SoundManager 2 "+(v?"failed to load":"loaded")+" ("+(v?"security/load error":"OK")+") --",1);if(v||b){if(c.useFlashBlock&& +c.oMC)c.oMC.className=G()+" "+(c.getMoviePercent()===null?c.swfCSS.swfTimedout:c.swfCSS.swfError);C({type:"ontimeout",error:a});r("onload",false);F(a);return false}else r("onload",true);if(c.waitForWindowLoad&&!ia)return l("waitOnload"),p.add(i,"load",D),false;else c.waitForWindowLoad&&ia&&l("docLoaded"),D();return true};U=function(){l("init");if(m)return l("didInit"),false;if(c.html5Only){if(!m)p.remove(i,"load",c.beginDelayedInit),c.enabled=true,N();return true}X();try{l("flashJS"),c.o._externalInterfaceTest(false), +Aa(true,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||c.o._disableDebug(),c.enabled=true,r("jstoflash",true),c.html5Only||p.add(i,"unload",ga)}catch(b){return c._wD("js/flash exception: "+b.toString()),r("jstoflash",false),F({type:"JS_TO_FLASH_EXCEPTION",fatal:true}),$(true),N(),false}N();p.remove(i,"load",c.beginDelayedInit);return true};E=function(){if(la)return false;la=true;ma();var b=K.toLowerCase(),a=null,a=null,e=typeof console!=="undefined"&&typeof console.log!=="undefined"; +if(b.indexOf("sm2-usehtml5audio=")!==-1)a=b.charAt(b.indexOf("sm2-usehtml5audio=")+18)==="1",e&&console.log((a?"Enabling ":"Disabling ")+"useHTML5Audio via URL parameter"),c.useHTML5Audio=a;if(b.indexOf("sm2-preferflash=")!==-1)a=b.charAt(b.indexOf("sm2-preferflash=")+16)==="1",e&&console.log((a?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.preferFlash=a;if(!t&&c.hasHTML5)c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode.")),c.useHTML5Audio= +true,c.preferFlash=false;Ha();c.html5.usingFlash=Ga();w=c.html5.usingFlash;Ka();if(!t&&w)c._wD("SoundManager: Fatal error: Flash is needed to play some required formats, but is not available."),c.flashLoadTimeout=1;g.removeEventListener&&g.removeEventListener("DOMContentLoaded",E,false);X();return true};sa=function(){g.readyState==="complete"&&(E(),g.detachEvent("onreadystatechange",sa));return true};ea();p.add(i,"focus",B);p.add(i,"load",B);p.add(i,"load",V);R&&H&&p.add(i,"mousemove",B);g.addEventListener? +g.addEventListener("DOMContentLoaded",E,false):g.attachEvent?g.attachEvent("onreadystatechange",sa):(r("onload",false),F({type:"NO_DOM2_EVENTS",fatal:true}));g.readyState==="complete"&&setTimeout(E,100)}var fa=null;if(typeof SM2_DEFER==="undefined"||!SM2_DEFER)fa=new T;S.SoundManager=T;S.soundManager=fa})(window); \ No newline at end of file diff --git a/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js b/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js index dcf1b361..6bc09204 100755 --- a/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js +++ b/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js @@ -1,75 +1,76 @@ -/** @license - - SoundManager 2: JavaScript Sound for the Web - ---------------------------------------------- - http://schillmania.com/projects/soundmanager2/ - - Copyright (c) 2007, Scott Schiller. All rights reserved. - Code provided under the BSD License: - http://schillmania.com/projects/soundmanager2/license.txt - - V2.97a.20110424 -*/ -(function(Y){function M(M,X){function i(c){return function(a){return!this._t||!this._t._a?null:c.call(this,a)}}function pa(){if(c.debugURLParam.test(N))c.debugMode=!0}this.flashVersion=8;this.debugFlash=this.debugMode=!1;this.useConsole=!0;this.waitForWindowLoad=this.consoleOnly=!1;this.nullURL="about:blank";this.allowPolling=!0;this.useFastPolling=!1;this.useMovieStar=!0;this.bgColor="#ffffff";this.useHighPerformance=!1;this.flashPollingInterval=null;this.flashLoadTimeout=1E3;this.wmode=null;this.allowScriptAccess= -"always";this.useHTML5Audio=this.useFlashBlock=!1;this.html5Test=/^probably$/i;this.useGlobalHTML5Audio=!0;this.requireFlash=!1;this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!0},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave", -"audio/x-wav"],required:!1}};this.defaultOptions={autoLoad:!1,stream:!0,autoPlay:!1,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfailure:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5E3,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:!0,multiShotEvents:!1,position:null,pan:0,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1, -useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.version=null;this.versionNumber="V2.97a.20110424";this.movieURL=null;this.url=M||null;this.altURL=null;this.enabled=this.swfLoaded=!1;this.o=null;this.movieID="sm2-container";this.id=X||"sm2movie";this.swfCSS={swfBox:"sm2-object-box",swfDefault:"movieContainer",swfError:"swf_error",swfTimedout:"swf_timedout",swfLoaded:"swf_loaded",swfUnblocked:"swf_unblocked",sm2Debug:"sm2_debug", -highPerf:"high_performance",flashDebug:"flash_debug"};this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=!1;this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.didFlashBlock=this.specialWmodeCase=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.baseMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamMimeTypes=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.netStreamTypes=["aac","flv","mov","mp4","m4v", -"f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.mimePattern=this.baseMimeTypes;this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={};this.hasHTML5=null;this.html5={usingFlash:null};this.ignoreFlash=!1;var Z,c=this,y,n=navigator.userAgent,h=Y,N=h.location.href.toString(),k=this.flashVersion,g=document,$,O,r=[],E=!1,F=!1,m=!1,t=!1,qa=!1,G,o,aa,u,z,ba,P,ra,ca,v,sa,H,A,da,ea,Q,fa,ta,ua,R, -va,I=null,ga=null,w,ha,B,S,T,ia,j,U=!1,ja=!1,wa,xa,x=null,ya,V,p=!1,J,s,ka,za,l,Da=Array.prototype.slice,K=!1,la,C,Aa,Ba=n.match(/pre\//i),Ea=n.match(/(ipad|iphone|ipod)/i);n.match(/mobile/i);var q=n.match(/msie/i),Fa=n.match(/webkit/i),L=n.match(/safari/i)&&!n.match(/chrome/i),Ga=n.match(/opera/i),ma=!N.match(/usehtml5audio/i)&&!N.match(/sm2\-ignorebadua/i)&&L&&n.match(/OS X 10_6_([3-9])/i),na=typeof g.hasFocus!=="undefined"?g.hasFocus():null,D=typeof g.hasFocus==="undefined"&&L,Ca=!D;this._use_maybe= -N.match(/sm2\-useHTML5Maybe\=1/i);this._overHTTP=g.location?g.location.protocol.match(/http/i):null;this._http=!this._overHTTP?"http:":"";this.useAltURL=!this._overHTTP;this._global_a=null;if(Ea||Ba)c.useHTML5Audio=!0,c.ignoreFlash=!0,c.useGlobalHTML5Audio&&(K=!0);if(Ba||this._use_maybe)c.html5Test=/^(probably|maybe)$/i;this.supported=this.ok=function(){return x?m&&!t:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return q?h[c]:L?y(c)||g[c]:y(c)};this.createSound=function(b){function a(){e= -S(e);c.sounds[d.id]=new Z(d);c.soundIDs.push(d.id);return c.sounds[d.id]}var e=null,f=null,d=null;if(!m||!c.ok())return ia("soundManager.createSound(): "+w(!m?"notReady":"notOK")),!1;arguments.length===2&&(b={id:arguments[0],url:arguments[1]});d=e=o(b);if(j(d.id,!0))return c.sounds[d.id];if(V(d))f=a(),f._setup_html5(d);else{if(k>8&&c.useMovieStar){if(d.isMovieStar===null)d.isMovieStar=d.serverURL||d.type&&d.type.match(c.netStreamPattern)||d.url.match(c.netStreamPattern)?!0:!1;if(d.isMovieStar&&d.usePeakData)d.usePeakData= -!1}d=T(d,"soundManager.createSound(): ");f=a();if(k===8)c.o._createSound(d.id,d.onjustbeforefinishtime,d.loops||1,d.usePolicyFile);else if(c.o._createSound(d.id,d.url,d.onjustbeforefinishtime,d.usePeakData,d.useWaveformData,d.useEQData,d.isMovieStar,d.isMovieStar?d.bufferTime:!1,d.loops||1,d.serverURL,d.duration||null,d.autoPlay,!0,d.autoLoad,d.usePolicyFile),!d.serverURL)f.connected=!0,d.onconnect&&d.onconnect.apply(f);(d.autoLoad||d.autoPlay)&&!d.serverURL&&f.load(d)}d.autoPlay&&!d.serverURL&&f.play(); -return f};this.destroySound=function(b,a){if(!j(b))return!1;var e=c.sounds[b],f;e._iO={};e.stop();e.unload();for(f=0;f0)a.resume();else{a.playState=1;a.paused=!1;(!a.instanceCount||a._iO.multiShotEvents||k>8&&!a.isHTML5&&!a.getAutoPlay())&&a.instanceCount++;a.position=typeof a._iO.position!=="undefined"&&!isNaN(a._iO.position)?a._iO.position:0;if(!a.isHTML5)a._iO=T(S(a._iO));if(a._iO.onplay&& -W)a._iO.onplay.apply(a),a._onplay_called=!0;a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?(d(),a._setup_html5().play()):c.o._start(a.sID,a._iO.loops||1,k===9?a.position:a.position/1E3)}return a};this.stop=function(b){if(a.playState===1){a._onbufferchange(0);a.resetOnPosition(0);if(!a.isHTML5)a.playState=0;a.paused=!1;a._iO.onstop&&a._iO.onstop.apply(a);if(a.isHTML5){if(a._a)a.setPosition(0),a._a.pause(),a.playState=0,a._onTimer(),f(),a.unload()}else c.o._stop(a.sID,b),a._iO.serverURL&& -a.unload();a.instanceCount=0;a._iO={}}return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5?a._a&&b&&a.play():c.o._setAutoPlay(a.sID,b);b&&!a.instanceCount&&a.readyState===1&&a.instanceCount++};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===void 0&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a.resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a&&a._html5_canplay&& -a._a.currentTime!==b)try{a._a.currentTime=b}catch(e){}}else b=k===9?a.position:b,a.readyState&&a.readyState!==2&&c.o._setPosition(a.sID,b,a.paused||!a.playState);a.isHTML5&&a.paused&&a._onTimer(!0);return a};this.pause=function(b){if(a.paused||a.playState===0&&a.readyState!==1)return a;a.paused=!0;a.isHTML5?(a._setup_html5().pause(),f()):(b||b===void 0)&&c.o._pause(a.sID);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5? -(a._setup_html5().play(),d()):(a._iO.isMovieStar&&a.setPosition(a.position),c.o._pause(a.sID));!a._onplay_called&&a._iO.onplay?(a._iO.onplay.apply(a),a._onplay_called=!0):a._iO.onresume&&a._iO.onresume.apply(a);return a};this.togglePause=function(){if(a.playState===0)return a.play({position:k===9&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,d){typeof b==="undefined"&&(b=0);typeof d==="undefined"&&(d=!1);a.isHTML5||c.o._setPan(a.sID,b);a._iO.pan= -b;if(!d)a.pan=b,a.options.pan=b;return a};this.setVolume=function(b,d){typeof b==="undefined"&&(b=100);typeof d==="undefined"&&(d=!1);if(a.isHTML5){if(a._a)a._a.volume=Math.max(0,Math.min(1,b/100))}else c.o._setVolume(a.sID,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;if(!d)a.volume=b,a.options.volume=b;return a};this.mute=function(){a.muted=!0;if(a.isHTML5){if(a._a)a._a.muted=!0}else c.o._setVolume(a.sID,0);return a};this.unmute=function(){a.muted=!1;var b=typeof a._iO.volume!=="undefined";if(a.isHTML5){if(a._a)a._a.muted= -!1}else c.o._setVolume(a.sID,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=function(c,b,d){a._onPositionItems.push({position:c,method:b,scope:typeof d!=="undefined"?d:a,fired:!1});return a};this.processOnPosition=function(){var b,d;b=a._onPositionItems.length;if(!b||!a.playState||a._onPositionFired>=b)return!1;for(;b--;)if(d=a._onPositionItems[b],!d.fired&&a.position>=d.position)d.method.apply(d.scope,[d.position]),d.fired= -!0,c._onPositionFired++;return!0};this.resetOnPosition=function(b){var d,e;d=a._onPositionItems.length;if(!d)return!1;for(;d--;)if(e=a._onPositionItems[d],e.fired&&b<=e.position)e.fired=!1,c._onPositionFired--;return!0};this._onTimer=function(c){var b={};if(a._hasTimer||c)return a._a&&(c||(a.playState>0||a.readyState===1)&&!a.paused)?(a.duration=a._get_html5_duration(),a.durationEstimate=a.duration,c=a._a.currentTime?a._a.currentTime*1E3:0,a._whileplaying(c,b,b,b,b),!0):!1};this._get_html5_duration= -function(){var c=a._a?a._a.duration*1E3:a._iO?a._iO.duration:void 0;return c&&!isNaN(c)&&c!==Infinity?c:a._iO?a._iO.duration:null};d=function(){a.isHTML5&&wa(a)};f=function(){a.isHTML5&&xa(a)};e=function(){a._onPositionItems=[];a._onPositionFired=0;a._hasTimer=null;a._onplay_called=!1;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.position=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.failures=0;a.loaded=!1;a.playState=0;a.paused=!1;a.readyState= -0;a.muted=!1;a.didBeforeFinish=!1;a.didJustBeforeFinish=!1;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.eqData=[];a.eqData.left=[];a.eqData.right=[]};e();this._setup_html5=function(b){var b=o(a._iO,b),d=K?c._global_a:a._a;decodeURI(b.url);var f=d&&d._t?d._t.instanceOptions:null;if(d){if(d._t&&f.url===b.url&&(!a._lastURL||a._lastURL===f.url))return d;K&&d._t&&d._t.playState&&b.url!==f.url&&d._t.stop();e();d.src=b.url;a.url= -b.url;a._lastURL=b.url;d._called_load=!1}else if(d=new Audio(b.url),d._called_load=!1,K)c._global_a=d;a.isHTML5=!0;a._a=d;d._t=a;a._add_html5_events();d.loop=b.loops>1?"loop":"";b.autoLoad||b.autoPlay?(d.autobuffer="auto",d.preload="auto",a.load(),d._called_load=!0):(d.autobuffer=!1,d.preload="none");d.loop=b.loops>1?"loop":"";return d};this._add_html5_events=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b, -c._html5_events[b],!1);return!0};this._remove_html5_events=function(){a._a._added_events=!1;for(var b in c._html5_events)c._html5_events.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,c._html5_events[b],!1)};this._whileloading=function(c,b,d,e){a.bytesLoaded=c;a.bytesTotal=b;a.duration=Math.floor(d);a.bufferLength=e;if(a._iO.isMovieStar)a.durationEstimate=a.duration;else if(a.durationEstimate=a._iO.duration?a.duration>a._iO.duration?a.duration:a._iO.duration:parseInt(a.bytesTotal/a.bytesLoaded* -a.duration,10),a.durationEstimate===void 0)a.durationEstimate=a.duration;a.readyState!==3&&a._iO.whileloading&&a._iO.whileloading.apply(a)};this._onid3=function(c,b){var d=[],e,f;e=0;for(f=c.length;e0&&(b=0);a.position=b;a.processOnPosition();if(k>8&&!a.isHTML5){if(a._iO.usePeakData&&typeof d!=="undefined"&&d)a.peakData={left:d.leftPeak,right:d.rightPeak}; -if(a._iO.useWaveformData&&typeof e!=="undefined"&&e)a.waveformData={left:e.split(","),right:f.split(",")};if(a._iO.useEQData&&typeof g!=="undefined"&&g&&g.leftEQ&&(b=g.leftEQ.split(","),a.eqData=b,a.eqData.left=b,typeof g.rightEQ!=="undefined"&&g.rightEQ))a.eqData.right=g.rightEQ.split(",")}a.playState===1&&(!a.isHTML5&&c.flashVersion===8&&!a.position&&a.isBuffering&&a._onbufferchange(0),a._iO.whileplaying&&a._iO.whileplaying.apply(a),(a.loaded||!a.loaded&&a._iO.isMovieStar)&&a._iO.onbeforefinish&& -a._iO.onbeforefinishtime&&!a.didBeforeFinish&&a.duration-a.position<=a._iO.onbeforefinishtime&&a._onbeforefinish());return!0};this._onconnect=function(b){b=b===1;if(a.connected=b)a.failures=0,j(a.sID)&&(a.getAutoPlay()?a.play(void 0,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._onload=function(b){b=b?!0:!1;a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0);a._iO.onload&&a._iO.onload.apply(a,[b]);return!0};this._onfailure=function(b,c,d){a.failures++; -if(a._iO.onfailure&&a.failures===1)a._iO.onfailure(a,b,c,d)};this._onbeforefinish=function(){if(!a.didBeforeFinish)a.didBeforeFinish=!0,a._iO.onbeforefinish&&a._iO.onbeforefinish.apply(a)};this._onjustbeforefinish=function(){if(!a.didJustBeforeFinish)a.didJustBeforeFinish=!0,a._iO.onjustbeforefinish&&a._iO.onjustbeforefinish.apply(a)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a.resetOnPosition(0);a._iO.onbeforefinishcomplete&&a._iO.onbeforefinishcomplete.apply(a);a.didBeforeFinish= -!1;a.didJustBeforeFinish=!1;if(a.instanceCount){a.instanceCount--;if(!a.instanceCount)a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},f();(!a.instanceCount||a._iO.multiShotEvents)&&b&&b.apply(a)}};this._onbufferchange=function(b){if(a.playState===0)return!1;if(b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=b===1;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return!0};this._ondataerror=function(){a.playState>0&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}}; -ea=function(){return g.body?g.body:g._docElement?g.documentElement:g.getElementsByTagName("div")[0]};y=function(b){return g.getElementById(b)};o=function(b,a){var e={},f,d;for(f in b)b.hasOwnProperty(f)&&(e[f]=b[f]);f=typeof a==="undefined"?c.defaultOptions:a;for(d in f)f.hasOwnProperty(d)&&typeof e[d]==="undefined"&&(e[d]=f[d]);return e};l=function(){function b(a){var a=Da.call(a),b=a.length;c?(a[1]="on"+a[1],b>3&&a.pop()):b===3&&a.push(!1);return a}function a(a,b){var g=a.shift(),h=[f[b]];if(c)g[h](a[0], -a[1]);else g[h].apply(g,a)}var c=h.attachEvent,f={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){a(b(arguments),"add")},remove:function(){a(b(arguments),"remove")}}}();V=function(b){return!b.serverURL&&(b.type?J({type:b.type}):J(b.url)||p)};J=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var a,e=c.audioFormats;if(!s){s=[];for(a in e)e.hasOwnProperty(a)&&(s.push(a),e[a].related&&(s=s.concat(e[a].related)));s=RegExp("\\.("+s.join("|")+ -")","i")}a=typeof b.type!=="undefined"?b.type:null;b=typeof b==="string"?b.toLowerCase().match(s):null;if(!b||!b.length)if(a)b=a.indexOf(";"),b=(b!==-1?a.substr(0,b):a).substr(6);else return!1;else b=b[0].substr(1);if(b&&typeof c.html5[b]!=="undefined")return c.html5[b];else{if(!a)if(b&&c.html5[b])return c.html5[b];else a="audio/"+b;a=c.html5.canPlayType(a);return c.html5[b]=a}};za=function(){function b(b){var d,e,f=!1;if(!a||typeof a.canPlayType!=="function")return!1;if(b instanceof Array){d=0;for(e= -b.length;d1&&b.stream)b.stream=!1;return b};T=function(b){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))b.usePolicyFile=!0;return b};ia=function(b){typeof console!=="undefined"&&typeof console.warn!=="undefined"&&console.warn(b)};$=function(){return!1};ua=function(b){for(var a in b)b.hasOwnProperty(a)&&typeof b[a]==="function"&&(b[a]=$)};R=function(b){typeof b==="undefined"&& -(b=!1);(t||b)&&c.disable(b)};va=function(b){var a=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(a=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");return(b&&b.lastIndexOf("/")!==-1?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL};ca=function(){if(k!==8&&k!==9)c.flashVersion=8;var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";if(c.useHTML5Audio&&!p&&c.audioFormats.mp4.required&&c.flashVersion<9)c.flashVersion=9;k=c.flashVersion;c.version=c.versionNumber+ -(p?" (HTML5-only mode)":k===9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(k>8)c.defaultOptions=o(c.defaultOptions,c.flash9Options),c.features.buffering=!0;k>8&&c.useMovieStar?(c.defaultOptions=o(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+c.netStreamTypes.join("|")+")(\\?.*)?$","i"),c.mimePattern=c.netStreamMimeTypes,c.features.movieStar=!0):(c.useMovieStar=!1,c.features.movieStar=!1);c.filePattern=c.filePatterns[k!==8?"flash9":"flash8"];c.movieURL=(k===8?"soundmanager2.swf": -"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=k>8};ta=function(b,a){if(!c.o||!c.allowPolling)return!1;c.o._setPolling(b,a)};Q=function(b,a){var e=a?a:c.url,f=c.altURL?c.altURL:e,d;d=ea();var h,k,i=B(),j,l=null,l=(l=g.getElementsByTagName("html")[0])&&l.dir&&l.dir.match(/rtl/i),b=typeof b==="undefined"?c.id:b;if(E&&F)return!1;if(p)return ca(),c.oMC=y(c.movieID),O(),F=E=!0,!1;E=!0;ca();c.url=va(c._overHTTP?e:f);a=c.url;c.wmode=!c.wmode&& -c.useHighPerformance&&!c.useMovieStar?"transparent":c.wmode;if(c.wmode!==null&&(n.match(/msie 8/i)||!q&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.specialWmodeCase=!0,c.wmode=null;d={name:b,id:b,src:a,width:"100%",height:"100%",quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:c._http+"//www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)d.FlashVars="debug=1";c.wmode|| -delete d.wmode;if(q)e=g.createElement("div"),k=''+(c.wmode?' ':"")+ -''+(c.debugFlash?'':"")+"";else for(h in e=g.createElement("embed"),d)d.hasOwnProperty(h)&&e.setAttribute(h,d[h]);pa();i=B();if(d=ea())if(c.oMC=y(c.movieID)?y(c.movieID):g.createElement("div"),c.oMC.id){j=c.oMC.className;c.oMC.className=(j?j+" ":c.swfCSS.swfDefault)+(i?" "+i:"");c.oMC.appendChild(e);if(q)h=c.oMC.appendChild(g.createElement("div")),h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}else{c.oMC.id= -c.movieID;c.oMC.className=c.swfCSS.swfDefault+" "+i;h=i=null;if(!c.useFlashBlock)if(c.useHighPerformance)i={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(i={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},l)i.left=Math.abs(parseInt(i.left,10))+"px";if(Fa)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(j in i)i.hasOwnProperty(j)&&(c.oMC.style[j]=i[j]);try{q||c.oMC.appendChild(e);d.appendChild(c.oMC);if(q)h=c.oMC.appendChild(g.createElement("div")), -h.className=c.swfCSS.swfBox,h.innerHTML=k;F=!0}catch(m){throw Error(w("appXHTML"));}}return!0};j=this.getSoundById;H=function(){if(p)return Q(),!1;if(c.o)return!1;c.o=c.getMovie(c.id);if(!c.o)I?(q?c.oMC.innerHTML=ga:c.oMC.appendChild(I),I=null,E=!0):Q(c.id,c.url),c.o=c.getMovie(c.id);c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return!0};ba=function(b){if(b)c.url=b;H()};P=function(){setTimeout(ra,500)};ra=function(){if(U)return!1;U=!0;l.remove(h,"load",P);if(D&&!na)return!1;var b; -m||(b=c.getMoviePercent());setTimeout(function(){b=c.getMoviePercent();!m&&Ca&&(b===null?c.useFlashBlock||c.flashLoadTimeout===0?c.useFlashBlock&&ha():R(!0):c.flashLoadTimeout!==0&&R(!0))},c.flashLoadTimeout)};ba=function(b){if(b)c.url=b;H()};B=function(){var b=[];c.debugMode&&b.push(c.swfCSS.sm2Debug);c.debugFlash&&b.push(c.swfCSS.flashDebug);c.useHighPerformance&&b.push(c.swfCSS.highPerf);return b.join(" ")};ha=function(){w("fbHandler");var b=c.getMoviePercent(),a=c.swfCSS;if(c.ok()){if(c.oMC)c.oMC.className= -[B(),a.swfDefault,a.swfLoaded+(c.didFlashBlock?" "+a.swfUnblocked:"")].join(" ")}else{if(x)c.oMC.className=B()+" "+a.swfDefault+" "+(b===null?a.swfTimedout:a.swfError);c.didFlashBlock=!0;u({type:"ontimeout",ignoreInit:!0});c.onerror instanceof Function&&c.onerror.apply(h)}};v=function(){function b(){l.remove(h,"focus",v);l.remove(h,"load",v)}if(na||!D)return b(),!0;na=Ca=!0;L&&D&&l.remove(h,"mousemove",v);U=!1;b();return!0};G=function(b){if(m)return!1;if(p)return m=!0,u(),z(),!0;c.useFlashBlock&& -c.flashLoadTimeout&&!c.getMoviePercent()||(m=!0);if(t||b){if(c.useFlashBlock)c.oMC.className=B()+" "+(c.getMoviePercent()===null?c.swfCSS.swfTimedout:c.swfCSS.swfError);u({type:"ontimeout"});c.onerror instanceof Function&&c.onerror.apply(h);return!1}l.add(h,"unload",$);if(c.waitForWindowLoad&&!qa)return l.add(h,"load",z),!1;else z();return!0};aa=function(b,a,c){typeof r[b]==="undefined"&&(r[b]=[]);r[b].push({method:a,scope:c||null,fired:!1})};u=function(b){b||(b={type:"onready"});if(!m&&b&&!b.ignoreInit)return!1; -var a={success:b&&b.ignoreInit?c.ok():!t},e=b&&b.type?r[b.type]||[]:[],b=[],f,d=x&&c.useFlashBlock&&!c.ok();for(f=0;f8){if(d.isMovieStar===null)d.isMovieStar=d.serverURL||(d.type?d.type.match(Ga):false)||d.url.match(Na);if(d.isMovieStar&&d.usePeakData)d.usePeakData=false}d=V(d,"soundManager.createSound(): ");f=a();if(g===8)c.o._createSound(d.id,d.loops||1,d.usePolicyFile);else if(c.o._createSound(d.id,d.url,d.usePeakData,d.useWaveformData,d.useEQData,d.isMovieStar,d.isMovieStar?d.bufferTime:false,d.loops|| +1,d.serverURL,d.duration||null,d.autoPlay,true,d.autoLoad,d.usePolicyFile),!d.serverURL)f.connected=true,d.onconnect&&d.onconnect.apply(f);!d.serverURL&&(d.autoLoad||d.autoPlay)&&f.load(d)}!d.serverURL&&d.autoPlay&&f.play();return f};this.destroySound=function(b,a){if(!l(b))return false;var e=c.sounds[b],f;e._iO={};e.stop();e.unload();for(f=0;f +8&&b.match(Ga)||b.match(c.mimePattern)):null};this.canPlayURL=function(b){var a;c.hasHTML5&&(a=K({url:b}));return!q||a?a:b?!!b.match(c.filePattern):null};this.canPlayLink=function(b){return typeof b.type!=="undefined"&&b.type&&c.canPlayMIME(b.type)?true:c.canPlayURL(b.href)};this.getSoundById=function(b){if(!b)throw Error("soundManager.getSoundById(): sID is null/undefined");return c.sounds[b]};this.onready=function(c,a){if(c&&c instanceof Function)return a||(a=i),ca("onready",c,a),z(),true;else throw y("needFunction", +"onready");};this.ontimeout=function(c,a){if(c&&c instanceof Function)return a||(a=i),ca("ontimeout",c,a),z({type:"ontimeout"}),true;else throw y("needFunction","ontimeout");};this._wD=this._writeDebug=function(){return true};this._debug=function(){};this.reboot=function(){var b,a;for(b=c.soundIDs.length;b--;)c.sounds[c.soundIDs[b]].destruct();try{if(v)ha=c.o.innerHTML;J=c.o.parentNode.removeChild(c.o)}catch(e){}ha=J=q=null;c.enabled=ea=m=W=ka=G=H=t=c.swfLoaded=false;c.soundIDs=c.sounds=[];c.o=null; +for(b in s)if(s.hasOwnProperty(b))for(a=s[b].length;a--;)s[b][a].fired=false;i.setTimeout(c.beginDelayedInit,20)};this.getMoviePercent=function(){return c.o&&typeof c.o.PercentLoaded!=="undefined"?c.o.PercentLoaded():null};this.beginDelayedInit=function(){sa=true;B();setTimeout(function(){if(ka)return false;S();R();return ka=true},20);Q()};this.destruct=function(){c.disable(true)};ra=function(b){var a=this,e,f,d;this.sID=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=n(b);this.pan= +this.options.pan;this.volume=this.options.volume;this._lastURL=null;this.isHTML5=false;this._a=null;this.id3={};this._debug=function(){};this.load=function(b){var d=null;if(typeof b!=="undefined")a._iO=n(b,a.options),a.instanceOptions=a._iO;else if(b=a.options,a._iO=b,a.instanceOptions=a._iO,a._lastURL&&a._lastURL!==a.url)a._iO.url=a.url,a.url=null;if(!a._iO.url)a._iO.url=a.url;if(a._iO.url===a.url&&a.readyState!==0&&a.readyState!==2)return a;a._lastURL=a.url;a.loaded=false;a.readyState=1;a.playState= +0;if(X(a._iO)){if(d=a._setup_html5(a._iO),!d._called_load)a._html5_canplay=false,d.load(),d._called_load=true,a._iO.autoPlay&&a.play()}else try{a.isHTML5=false,a._iO=V(U(a._iO)),g===8?c.o._load(a.sID,a._iO.url,a._iO.stream,a._iO.autoPlay,a._iO.whileloading?1:0,a._iO.loops||1,a._iO.usePolicyFile):c.o._load(a.sID,a._iO.url,!!a._iO.stream,!!a._iO.autoPlay,a._iO.loops||1,!!a._iO.autoLoad,a._iO.usePolicyFile)}catch(e){C({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:true})}return a};this.unload=function(){a.readyState!== +0&&(a.isHTML5?(f(),a._a&&(a._a.pause(),la(a._a))):g===8?c.o._unload(a.sID,"about:blank"):c.o._unload(a.sID),e());return a};this.destruct=function(b){if(a.isHTML5){if(f(),a._a)a._a.pause(),la(a._a),L||a._remove_html5_events(),a._a._t=null,a._a=null}else a._iO.onfailure=null,c.o._destroySound(a.sID);b||c.destroySound(a.sID,true)};this.start=this.play=function(b,w){var e,w=w===void 0?true:w;b||(b={});a._iO=n(b,a._iO);a._iO=n(a._iO,a.options);a.instanceOptions=a._iO;if(a._iO.serverURL&&!a.connected)return a.getAutoPlay()|| +a.setAutoPlay(true),a;X(a._iO)&&(a._setup_html5(a._iO),d());if(a.playState===1&&!a.paused&&(e=a._iO.multiShot,!e))return a;if(!a.loaded)if(a.readyState===0){if(!a.isHTML5)a._iO.autoPlay=true;a.load(a._iO)}else if(a.readyState===2)return a;if(!a.isHTML5&&g===9&&a.position>0&&a.position===a.duration)a._iO.position=0;if(a.paused&&a.position&&a.position>0)a.resume();else{a.playState=1;a.paused=false;(!a.instanceCount||a._iO.multiShotEvents||!a.isHTML5&&g>8&&!a.getAutoPlay())&&a.instanceCount++;a.position= +typeof a._iO.position!=="undefined"&&!isNaN(a._iO.position)?a._iO.position:0;if(!a.isHTML5)a._iO=V(U(a._iO));if(a._iO.onplay&&w)a._iO.onplay.apply(a),a._onplay_called=true;a.setVolume(a._iO.volume,true);a.setPan(a._iO.pan,true);a.isHTML5?(d(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):c.o._start(a.sID,a._iO.loops||1,g===9?a._iO.position:a._iO.position/1E3)}return a};this.stop=function(b){if(a.playState===1){a._onbufferchange(0);a.resetOnPosition(0);a.paused=false;if(!a.isHTML5)a.playState= +0;a._iO.onstop&&a._iO.onstop.apply(a);if(a.isHTML5){if(a._a)a.setPosition(0),a._a.pause(),a.playState=0,a._onTimer(),f()}else c.o._stop(a.sID,b),a._iO.serverURL&&a.unload();a.instanceCount=0;a._iO={}}return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5||(c.o._setAutoPlay(a.sID,b),b&&!a.instanceCount&&a.readyState===1&&a.instanceCount++)};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===void 0&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration|| +a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a.resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a&&a._html5_canplay&&a._a.currentTime!==b)try{a._a.currentTime=b,(a.playState===0||a.paused)&&a._a.pause()}catch(e){}}else b=g===9?a.position:b,a.readyState&&a.readyState!==2&&c.o._setPosition(a.sID,b,a.paused||!a.playState);a.isHTML5&&a.paused&&a._onTimer(true);return a};this.pause=function(b){if(a.paused||a.playState===0&&a.readyState!==1)return a;a.paused=true;a.isHTML5? +(a._setup_html5().pause(),f()):(b||b===void 0)&&c.o._pause(a.sID);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){if(!a.paused)return a;a.paused=false;a.playState=1;a.isHTML5?(a._setup_html5().play(),d()):(a._iO.isMovieStar&&a.setPosition(a.position),c.o._pause(a.sID));!a._onplay_called&&a._iO.onplay?(a._iO.onplay.apply(a),a._onplay_called=true):a._iO.onresume&&a._iO.onresume.apply(a);return a};this.togglePause=function(){if(a.playState===0)return a.play({position:g===9&&!a.isHTML5? +a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,d){typeof b==="undefined"&&(b=0);typeof d==="undefined"&&(d=false);a.isHTML5||c.o._setPan(a.sID,b);a._iO.pan=b;if(!d)a.pan=b,a.options.pan=b;return a};this.setVolume=function(b,d){typeof b==="undefined"&&(b=100);typeof d==="undefined"&&(d=false);if(a.isHTML5){if(a._a)a._a.volume=Math.max(0,Math.min(1,b/100))}else c.o._setVolume(a.sID,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;if(!d)a.volume=b,a.options.volume= +b;return a};this.mute=function(){a.muted=true;if(a.isHTML5){if(a._a)a._a.muted=true}else c.o._setVolume(a.sID,0);return a};this.unmute=function(){a.muted=false;var b=typeof a._iO.volume!=="undefined";if(a.isHTML5){if(a._a)a._a.muted=false}else c.o._setVolume(a.sID,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=function(b,c,d){a._onPositionItems.push({position:b,method:c,scope:typeof d!=="undefined"?d:a,fired:false});return a}; +this.processOnPosition=function(){var b,d;b=a._onPositionItems.length;if(!b||!a.playState||a._onPositionFired>=b)return false;for(;b--;)if(d=a._onPositionItems[b],!d.fired&&a.position>=d.position)d.fired=true,c._onPositionFired++,d.method.apply(d.scope,[d.position]);return true};this.resetOnPosition=function(b){var d,e;d=a._onPositionItems.length;if(!d)return false;for(;d--;)if(e=a._onPositionItems[d],e.fired&&b<=e.position)e.fired=false,c._onPositionFired--;return true};d=function(){a.isHTML5&&xa(a)}; +f=function(){a.isHTML5&&ya(a)};e=function(){a._onPositionItems=[];a._onPositionFired=0;a._hasTimer=null;a._onplay_called=false;a._a=null;a._html5_canplay=false;a.bytesLoaded=null;a.bytesTotal=null;a.position=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.failures=0;a.loaded=false;a.playState=0;a.paused=false;a.readyState=0;a.muted=false;a.isBuffering=false;a.instanceOptions={};a.instanceCount=0;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.eqData= +[];a.eqData.left=[];a.eqData.right=[]};e();this._onTimer=function(b){var c={};if(a._hasTimer||b)return a._a&&(b||(a.playState>0||a.readyState===1)&&!a.paused)?(a.duration=a._get_html5_duration(),a.durationEstimate=a.duration,b=a._a.currentTime?a._a.currentTime*1E3:0,a._whileplaying(b,c,c,c,c),true):false};this._get_html5_duration=function(){var b=a._a?a._a.duration*1E3:a._iO?a._iO.duration:void 0;return b&&!isNaN(b)&&b!==Infinity?b:a._iO?a._iO.duration:null};this._setup_html5=function(b){var b=n(a._iO, +b),d=L?c._global_a:a._a;decodeURI(b.url);var f=d&&d._t?d._t.instanceOptions:null;if(d){if(d._t&&f.url===b.url&&(!a._lastURL||a._lastURL===f.url))return d;L&&d._t&&d._t.playState&&b.url!==f.url&&d._t.stop();e();d.src=b.url;a.url=b.url;a._lastURL=b.url;d._called_load=false}else{d=new Audio(b.url);d._called_load=false;if(Ka)d._called_load=true;if(L)c._global_a=d}a.isHTML5=true;a._a=d;d._t=a;a._add_html5_events();d.loop=b.loops>1?"loop":"";b.autoLoad||b.autoPlay?(d.autobuffer="auto",d.preload="auto", +a.load(),d._called_load=true):(d.autobuffer=false,d.preload="none");d.loop=b.loops>1?"loop":"";return d};this._add_html5_events=function(){if(a._a._added_events)return false;var b;a._a._added_events=true;for(b in r)r.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,r[b],false);return true};this._remove_html5_events=function(){var b;a._a._added_events=false;for(b in r)r.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,r[b],false)};this._onload=function(b){b=!!b;a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0); +a._iO.onload&&a._iO.onload.apply(a,[b]);return true};this._onbufferchange=function(b){if(a.playState===0)return false;if(b&&a.isBuffering||!b&&!a.isBuffering)return false;a.isBuffering=b===1;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return true};this._onsuspend=function(){a._iO.onsuspend&&a._iO.onsuspend.apply(a);return true};this._onfailure=function(b,c,d){a.failures++;if(a._iO.onfailure&&a.failures===1)a._iO.onfailure(a,b,c,d)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0); +a.resetOnPosition(0);if(a.instanceCount){a.instanceCount--;if(!a.instanceCount)a.playState=0,a.paused=false,a.instanceCount=0,a.instanceOptions={},a._iO={},f();(!a.instanceCount||a._iO.multiShotEvents)&&b&&b.apply(a)}};this._whileloading=function(b,c,d,e){a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);a.bufferLength=e;if(a._iO.isMovieStar)a.durationEstimate=a.duration;else if(a.durationEstimate=a._iO.duration?a.duration>a._iO.duration?a.duration:a._iO.duration:parseInt(a.bytesTotal/a.bytesLoaded* +a.duration,10),a.durationEstimate===void 0)a.durationEstimate=a.duration;a.readyState!==3&&a._iO.whileloading&&a._iO.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){if(isNaN(b)||b===null)return false;a.position=b;a.processOnPosition();if(!a.isHTML5&&g>8){if(a._iO.usePeakData&&typeof c!=="undefined"&&c)a.peakData={left:c.leftPeak,right:c.rightPeak};if(a._iO.useWaveformData&&typeof d!=="undefined"&&d)a.waveformData={left:d.split(","),right:e.split(",")};if(a._iO.useEQData&&typeof f!== +"undefined"&&f&&f.leftEQ&&(b=f.leftEQ.split(","),a.eqData=b,a.eqData.left=b,typeof f.rightEQ!=="undefined"&&f.rightEQ))a.eqData.right=f.rightEQ.split(",")}a.playState===1&&(!a.isHTML5&&g===8&&!a.position&&a.isBuffering&&a._onbufferchange(0),a._iO.whileplaying&&a._iO.whileplaying.apply(a));return true};this._onid3=function(b,c){var d=[],e,f;for(e=0,f=b.length;e0&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}};fa=function(){return h.body||h._docElement||h.getElementsByTagName("div")[0]};O=function(b){return h.getElementById(b)};n=function(b,a){var e={},f,d;for(f in b)b.hasOwnProperty(f)&&(e[f]=b[f]);f=typeof a==="undefined"?c.defaultOptions:a;for(d in f)f.hasOwnProperty(d)&&typeof e[d]==="undefined"&& +(e[d]=f[d]);return e};k=function(){function b(a){var a=Ia.call(a),b=a.length;c?(a[1]="on"+a[1],b>3&&a.pop()):b===3&&a.push(false);return a}function a(a,b){var w=a.shift(),h=[f[b]];if(c)w[h](a[0],a[1]);else w[h].apply(w,a)}var c=i.attachEvent,f={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){a(b(arguments),"add")},remove:function(){a(b(arguments),"remove")}}}();r={abort:j(function(){}),canplay:j(function(){if(this._t._html5_canplay)return true; +this._t._html5_canplay=true;this._t._onbufferchange(0);var b=!isNaN(this._t.position)?this._t.position/1E3:null;if(this._t.position&&this.currentTime!==b)try{this.currentTime=b}catch(a){}}),load:j(function(){this._t.loaded||(this._t._onbufferchange(0),this._t._whileloading(this._t.bytesTotal,this._t.bytesTotal,this._t._get_html5_duration()),this._t._onload(true))}),emptied:j(function(){}),ended:j(function(){this._t._onfinish()}),error:j(function(){this._t._onload(false)}),loadeddata:j(function(){var b= +this._t,a=b.bytesTotal||1;if(!b._loaded&&!M)b.duration=b._get_html5_duration(),b._whileloading(a,a,b._get_html5_duration()),b._onload(true)}),loadedmetadata:j(function(){}),loadstart:j(function(){this._t._onbufferchange(1)}),play:j(function(){this._t._onbufferchange(0)}),playing:j(function(){this._t._onbufferchange(0)}),progress:j(function(b){if(this._t.loaded)return false;var a,c=0,f=b.target.buffered;a=b.loaded||0;var d=b.total||1;if(f&&f.length){for(a=f.length;a--;)c=f.end(a)-f.start(a);a=c/b.target.duration}isNaN(a)|| +(this._t._onbufferchange(0),this._t._whileloading(a,d,this._t._get_html5_duration()),a&&d&&a===d&&r.load.call(this,b))}),ratechange:j(function(){}),suspend:j(function(b){r.progress.call(this,b);this._t._onsuspend()}),stalled:j(function(){}),timeupdate:j(function(){this._t._onTimer()}),waiting:j(function(){this._t._onbufferchange(1)})};X=function(b){return!b.serverURL&&(b.type?K({type:b.type}):K({url:b.url})||c.html5Only)};la=function(b){if(b)b.src=Ja?"":"about:blank"};K=function(b){function a(a){return c.preferFlash&& +p&&!c.ignoreFlash&&typeof c.flash[a]!=="undefined"&&c.flash[a]}if(!c.useHTML5Audio||!c.hasHTML5)return false;var e=b.url||null,b=b.type||null,f=c.audioFormats,d;if(b&&c.html5[b]!=="undefined")return c.html5[b]&&!a(b);if(!u){u=[];for(d in f)f.hasOwnProperty(d)&&(u.push(d),f[d].related&&(u=u.concat(f[d].related)));u=RegExp("\\.("+u.join("|")+")(\\?.*)?$","i")}d=e?e.toLowerCase().match(u):null;if(!d||!d.length)if(b)e=b.indexOf(";"),d=(e!==-1?b.substr(0,e):b).substr(6);else return false;else d=d[1];return d&& +typeof c.html5[d]!=="undefined"?c.html5[d]&&!a(d):(b="audio/"+d,e=c.html5.canPlayType({type:b}),(c.html5[d]=e)&&c.html5[b]&&!a(b))};Aa=function(){function b(b){var d,e,f=false;if(!a||typeof a.canPlayType!=="function")return false;if(b instanceof Array){for(d=0,e=b.length;d1&&b.stream)b.stream=false;return b};V=function(b){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))b.usePolicyFile=true;return b};ja=function(){};ba=function(){return false};va=function(b){for(var a in b)b.hasOwnProperty(a)&&typeof b[a]==="function"&&(b[a]=ba)};T=function(b){typeof b==="undefined"&&(b=false);(t||b)&&c.disable(b)};wa=function(b){var a=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(a=b.substr(b.toLowerCase().lastIndexOf(".swf?")+ +4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&b.lastIndexOf("/")!==-1?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+(new Date).getTime());return b};da=function(){g=parseInt(c.flashVersion,10);if(g!==8&&g!==9)c.flashVersion=g=8;var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";if(c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&g<9)c.flashVersion=g=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":g===9?" (AS3/Flash 9)":" (AS2/Flash 8)"); +g>8?(c.defaultOptions=n(c.defaultOptions,c.flash9Options),c.features.buffering=true,c.defaultOptions=n(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+Ha.join("|")+")(\\?.*)?$","i"),c.features.movieStar=true):c.features.movieStar=false;c.filePattern=c.filePatterns[g!==8?"flash9":"flash8"];c.movieURL=(g===8?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=g>8};ua=function(b,a){if(!c.o)return false; +c.o._setPolling(b,a)};ga=function(){if(c.debugURLParam.test(aa))c.debugMode=true};l=this.getSoundById;D=function(){var b=[];c.debugMode&&b.push(c.swfCSS.sm2Debug);c.debugFlash&&b.push(c.swfCSS.flashDebug);c.useHighPerformance&&b.push(c.swfCSS.highPerf);return b.join(" ")};ia=function(){y("fbHandler");var b=c.getMoviePercent(),a=c.swfCSS,e={type:"FLASHBLOCK"};if(c.html5Only)return false;if(c.ok()){if(c.oMC)c.oMC.className=[D(),a.swfDefault,a.swfLoaded+(c.didFlashBlock?" "+a.swfUnblocked:"")].join(" ")}else{if(q)c.oMC.className= +D()+" "+a.swfDefault+" "+(b===null?a.swfTimedout:a.swfError);c.didFlashBlock=true;z({type:"ontimeout",ignoreInit:true,error:e});C(e)}};ca=function(b,a,c){typeof s[b]==="undefined"&&(s[b]=[]);s[b].push({method:a,scope:c||null,fired:false})};z=function(b){b||(b={type:"onready"});if(!m&&b&&!b.ignoreInit)return false;if(b.type==="ontimeout"&&c.ok())return false;var a={success:b&&b.ignoreInit?c.ok():!t},e=b&&b.type?s[b.type]||[]:[],f=[],d,a=[a],h=q&&c.useFlashBlock&&!c.ok();if(b.error)a[0].error=b.error; +for(b=0,d=e.length;b'}if(G&&H)return false;if(c.html5Only)return da(),c.oMC=O(c.movieID),P(),H=G=true,false;var f=a||c.url,d=c.altURL||f,g;g=fa();var i,l,j=D(),k,m=null,m=(m=h.getElementsByTagName("html")[0])&&m.dir&&m.dir.match(/rtl/i),b=typeof b==="undefined"?c.id:b;da();c.url=wa(qa?f:d);a=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(c.wmode!==null&&(o.match(/msie 8/i)||!v&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.specialWmodeCase=true,c.wmode= +null;g={name:b,id:b,src:a,width:"auto",height:"auto",quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Fa+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)g.FlashVars="debug=1";c.wmode||delete g.wmode;if(v)f=h.createElement("div"),l=['',e("movie",a),e("AllowScriptAccess",c.allowScriptAccess),e("quality",g.quality),c.wmode?e("wmode",c.wmode):"",e("bgcolor",c.bgColor),e("hasPriority","true"),c.debugFlash?e("FlashVars",g.FlashVars):"",""].join("");else for(i in f=h.createElement("embed"),g)g.hasOwnProperty(i)&&f.setAttribute(i,g[i]);ga();j=D();if(g=fa())if(c.oMC=O(c.movieID)||h.createElement("div"), +c.oMC.id){k=c.oMC.className;c.oMC.className=(k?k+" ":c.swfCSS.swfDefault)+(j?" "+j:"");c.oMC.appendChild(f);if(v)i=c.oMC.appendChild(h.createElement("div")),i.className=c.swfCSS.swfBox,i.innerHTML=l;H=true}else{c.oMC.id=c.movieID;c.oMC.className=c.swfCSS.swfDefault+" "+j;i=j=null;if(!c.useFlashBlock)if(c.useHighPerformance)j={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(j={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},m)j.left= +Math.abs(parseInt(j.left,10))+"px";if(La)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(k in j)j.hasOwnProperty(k)&&(c.oMC.style[k]=j[k]);try{v||c.oMC.appendChild(f);g.appendChild(c.oMC);if(v)i=c.oMC.appendChild(h.createElement("div")),i.className=c.swfCSS.swfBox,i.innerHTML=l;H=true}catch(n){throw Error(y("domError")+" \n"+n.toString());}}return G=true};R=function(){if(c.html5Only)return S(),false;if(c.o)return false;c.o=c.getMovie(c.id);if(!c.o)J?(v?c.oMC.innerHTML=ha:c.oMC.appendChild(J),J=null,G= +true):S(c.id,c.url),c.o=c.getMovie(c.id);c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return true};Q=function(){setTimeout(ta,1E3)};ta=function(){if(W)return false;W=true;k.remove(i,"load",Q);if(E&&!pa)return false;var b;m||(b=c.getMoviePercent());setTimeout(function(){b=c.getMoviePercent();!m&&Da&&(b===null?c.useFlashBlock||c.flashLoadTimeout===0?c.useFlashBlock&&ia():T(true):c.flashLoadTimeout!==0&&T(true))},c.flashLoadTimeout)};x=function(){function b(){k.remove(i,"focus",x); +k.remove(i,"load",x)}if(pa||!E)return b(),true;pa=Da=true;M&&E&&k.remove(i,"mousemove",x);W=false;b();return true};Ca=function(){var b,a=[];if(c.useHTML5Audio&&c.hasHTML5)for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&a.push(b+": "+c.html5[b]+(!c.html5[b]&&p&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&p?" (preferring flash)":!c.html5[b]?" ("+(c.audioFormats[b].required?"required, ":"")+"and no flash support)":""))};I=function(b){if(m)return false;if(c.html5Only)return m=true, +A(),true;var a;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())m=true,t&&(a={type:!p&&q?"NO_FLASH":"INIT_TIMEOUT"});if(t||b){if(c.useFlashBlock&&c.oMC)c.oMC.className=D()+" "+(c.getMoviePercent()===null?c.swfCSS.swfTimedout:c.swfCSS.swfError);z({type:"ontimeout",error:a});C(a);return false}if(c.waitForWindowLoad&&!sa)return k.add(i,"load",A),false;else A();return true};P=function(){if(m)return false;if(c.html5Only){if(!m)k.remove(i,"load",c.beginDelayedInit),c.enabled=true,I();return true}R(); +try{c.o._externalInterfaceTest(false),ua(true,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||c.o._disableDebug(),c.enabled=true,c.html5Only||k.add(i,"unload",ba)}catch(b){return C({type:"JS_TO_FLASH_EXCEPTION",fatal:true}),T(true),I(),false}I();k.remove(i,"load",c.beginDelayedInit);return true};B=function(){if(ea)return false;ea=true;ga();if(!p&&c.hasHTML5)c.useHTML5Audio=true,c.preferFlash=false;Aa();c.html5.usingFlash=za();q=c.html5.usingFlash;Ca();if(!p&&q)c.flashLoadTimeout= +1;h.removeEventListener&&h.removeEventListener("DOMContentLoaded",B,false);R();return true};ma=function(){h.readyState==="complete"&&(B(),h.detachEvent("onreadystatechange",ma));return true};Y();k.add(i,"focus",x);k.add(i,"load",x);k.add(i,"load",Q);M&&E&&k.add(i,"mousemove",x);h.addEventListener?h.addEventListener("DOMContentLoaded",B,false):h.attachEvent?h.attachEvent("onreadystatechange",ma):C({type:"NO_DOM2_EVENTS",fatal:true});h.readyState==="complete"&&setTimeout(B,100)}var Z=null;if(typeof SM2_DEFER=== +"undefined"||!SM2_DEFER)Z=new N;$.SoundManager=N;$.soundManager=Z})(window); \ No newline at end of file diff --git a/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug.js b/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug.js new file mode 100755 index 00000000..09de509e --- /dev/null +++ b/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug.js @@ -0,0 +1,2184 @@ +/** @license + * + * SoundManager 2: JavaScript Sound for the Web + * ---------------------------------------------- + * http://schillmania.com/projects/soundmanager2/ + * + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License: + * http://schillmania.com/projects/soundmanager2/license.txt + * + * V2.97a.20111030 + */ + +/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ +/* jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ + +(function(window) { +var soundManager = null; +function SoundManager(smURL, smID) { + this.flashVersion = 8; + this.debugMode = false; + this.debugFlash = false; + this.useConsole = true; + this.consoleOnly = false; + this.waitForWindowLoad = false; + this.bgColor = '#ffffff'; + this.useHighPerformance = false; + this.flashPollingInterval = null; + this.flashLoadTimeout = 1000; + this.wmode = null; + this.allowScriptAccess = 'always'; + this.useFlashBlock = false; + this.useHTML5Audio = true; + this.html5Test = /^(probably|maybe)$/i; + this.preferFlash = true; + this.noSWFCache = false; + this.audioFormats = { + 'mp3': { + 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], + 'required': true + }, + 'mp4': { + 'related': ['aac','m4a'], + 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], + 'required': false + }, + 'ogg': { + 'type': ['audio/ogg; codecs=vorbis'], + 'required': false + }, + 'wav': { + 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], + 'required': false + } + }; + this.defaultOptions = { + 'autoLoad': false, + 'stream': true, + 'autoPlay': false, + 'loops': 1, + 'onid3': null, + 'onload': null, + 'whileloading': null, + 'onplay': null, + 'onpause': null, + 'onresume': null, + 'whileplaying': null, + 'onstop': null, + 'onfailure': null, + 'onfinish': null, + 'multiShot': true, + 'multiShotEvents': false, + 'position': null, + 'pan': 0, + 'type': null, + 'usePolicyFile': false, + 'volume': 100 + }; + this.flash9Options = { + 'isMovieStar': null, + 'usePeakData': false, + 'useWaveformData': false, + 'useEQData': false, + 'onbufferchange': null, + 'ondataerror': null + }; + this.movieStarOptions = { + 'bufferTime': 3, + 'serverURL': null, + 'onconnect': null, + 'duration': null + }; + this.movieID = 'sm2-container'; + this.id = (smID || 'sm2movie'); + this.swfCSS = { + 'swfBox': 'sm2-object-box', + 'swfDefault': 'movieContainer', + 'swfError': 'swf_error', + 'swfTimedout': 'swf_timedout', + 'swfLoaded': 'swf_loaded', + 'swfUnblocked': 'swf_unblocked', + 'sm2Debug': 'sm2_debug', + 'highPerf': 'high_performance', + 'flashDebug': 'flash_debug' + }; + this.debugID = 'soundmanager-debug'; + this.debugURLParam = /([#?&])debug=1/i; + this.versionNumber = 'V2.97a.20111030'; + this.version = null; + this.movieURL = null; + this.url = (smURL || null); + this.altURL = null; + this.swfLoaded = false; + this.enabled = false; + this.o = null; + this.oMC = null; + this.sounds = {}; + this.soundIDs = []; + this.muted = false; + this.specialWmodeCase = false; + this.didFlashBlock = false; + this.filePattern = null; + this.filePatterns = { + 'flash8': /\.mp3(\?.*)?$/i, + 'flash9': /\.mp3(\?.*)?$/i + }; + this.features = { + 'buffering': false, + 'peakData': false, + 'waveformData': false, + 'eqData': false, + 'movieStar': false + }; + this.sandbox = { + }; + this.hasHTML5 = (function() { + try { + return (typeof Audio !== 'undefined' && typeof new Audio().canPlayType !== 'undefined'); + } catch(e) { + return false; + } + }()); + this.html5 = { + 'usingFlash': null + }; + this.flash = {}; + this.html5Only = false; + this.ignoreFlash = false; + var SMSound, + _s = this, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _smTimer, _onTimer, _startTimer, _stopTimer, _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, + _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _is_firefox = _ua.match(/firefox/i), _is_android = _ua.match(/droid/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), + _likesHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), + _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && _ua.match(/OS X 10_6_([3-7])/i)), + _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && typeof _doc.hasFocus === 'undefined'), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa)/i, + _emptyURL = 'about:blank', + _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), + _http = (!_overHTTP ? 'http:/'+'/' : ''), + _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|mp4v|3gp|3g2)\s*(?:$|;)/i, + _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2'], + _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; + this.useAltURL = !_overHTTP; + this._global_a = null; + if (_likesHTML5) { + _s.useHTML5Audio = true; + _s.preferFlash = false; + if (_is_iDevice) { + _s.ignoreFlash = true; + _useGlobalHTML5Audio = true; + } + } + this.ok = function() { + return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); + }; + this.supported = this.ok; + this.getMovie = function(smID) { + return _id(smID) || _doc[smID] || _win[smID]; + }; + this.createSound = function(oOptions) { + var _cs = _sm+'.createSound(): ', + thisOptions = null, oSound = null, _tO = null; + if (!_didInit || !_s.ok()) { + _complain(_cs + _str(!_didInit?'notReady':'notOK')); + return false; + } + if (arguments.length === 2) { + oOptions = { + 'id': arguments[0], + 'url': arguments[1] + }; + } + thisOptions = _mixin(oOptions); + _tO = thisOptions; + if (_idCheck(_tO.id, true)) { + return _s.sounds[_tO.id]; + } + function make() { + thisOptions = _loopFix(thisOptions); + _s.sounds[_tO.id] = new SMSound(_tO); + _s.soundIDs.push(_tO.id); + return _s.sounds[_tO.id]; + } + if (_html5OK(_tO)) { + oSound = make(); + oSound._setup_html5(_tO); + } else { + if (_fV > 8) { + if (_tO.isMovieStar === null) { + _tO.isMovieStar = (_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); + } + if (_tO.isMovieStar) { + if (_tO.usePeakData) { + _tO.usePeakData = false; + } + } + } + _tO = _policyFix(_tO, _cs); + oSound = make(); + if (_fV === 8) { + _s.o._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); + } else { + _s.o._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); + if (!_tO.serverURL) { + oSound.connected = true; + if (_tO.onconnect) { + _tO.onconnect.apply(oSound); + } + } + } + if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { + oSound.load(_tO); + } + } + if (!_tO.serverURL && _tO.autoPlay) { + oSound.play(); + } + return oSound; + }; + this.destroySound = function(sID, _bFromSound) { + if (!_idCheck(sID)) { + return false; + } + var oS = _s.sounds[sID], i; + oS._iO = {}; + oS.stop(); + oS.unload(); + for (i = 0; i < _s.soundIDs.length; i++) { + if (_s.soundIDs[i] === sID) { + _s.soundIDs.splice(i, 1); + break; + } + } + if (!_bFromSound) { + oS.destruct(true); + } + oS = null; + delete _s.sounds[sID]; + return true; + }; + this.load = function(sID, oOptions) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].load(oOptions); + }; + this.unload = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].unload(); + }; + this.onposition = function(sID, nPosition, oMethod, oScope) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].onposition(nPosition, oMethod, oScope); + }; + this.play = function(sID, oOptions) { + var fN = _sm+'.play(): '; + if (!_didInit || !_s.ok()) { + _complain(fN + _str(!_didInit?'notReady':'notOK')); + return false; + } + if (!_idCheck(sID)) { + if (!(oOptions instanceof Object)) { + oOptions = { + url: oOptions + }; + } + if (oOptions && oOptions.url) { + oOptions.id = sID; + return _s.createSound(oOptions).play(); + } else { + return false; + } + } + return _s.sounds[sID].play(oOptions); + }; + this.start = this.play; + this.setPosition = function(sID, nMsecOffset) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPosition(nMsecOffset); + }; + this.stop = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].stop(); + }; + this.stopAll = function() { + var oSound; + for (oSound in _s.sounds) { + if (_s.sounds.hasOwnProperty(oSound)) { + _s.sounds[oSound].stop(); + } + } + }; + this.pause = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].pause(); + }; + this.pauseAll = function() { + var i; + for (i = _s.soundIDs.length; i--;) { + _s.sounds[_s.soundIDs[i]].pause(); + } + }; + this.resume = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].resume(); + }; + this.resumeAll = function() { + var i; + for (i = _s.soundIDs.length; i--;) { + _s.sounds[_s.soundIDs[i]].resume(); + } + }; + this.togglePause = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].togglePause(); + }; + this.setPan = function(sID, nPan) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPan(nPan); + }; + this.setVolume = function(sID, nVol) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setVolume(nVol); + }; + this.mute = function(sID) { + var fN = _sm+'.mute(): ', + i = 0; + if (typeof sID !== 'string') { + sID = null; + } + if (!sID) { + for (i = _s.soundIDs.length; i--;) { + _s.sounds[_s.soundIDs[i]].mute(); + } + _s.muted = true; + } else { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].mute(); + } + return true; + }; + this.muteAll = function() { + _s.mute(); + }; + this.unmute = function(sID) { + var fN = _sm+'.unmute(): ', i; + if (typeof sID !== 'string') { + sID = null; + } + if (!sID) { + for (i = _s.soundIDs.length; i--;) { + _s.sounds[_s.soundIDs[i]].unmute(); + } + _s.muted = false; + } else { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].unmute(); + } + return true; + }; + this.unmuteAll = function() { + _s.unmute(); + }; + this.toggleMute = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].toggleMute(); + }; + this.getMemoryUse = function() { + var ram = 0; + if (_s.o && _fV !== 8) { + ram = parseInt(_s.o._getMemoryUse(), 10); + } + return ram; + }; + this.disable = function(bNoDisable) { + var i; + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + if (_disabled) { + return false; + } + _disabled = true; + for (i = _s.soundIDs.length; i--;) { + _disableObject(_s.sounds[_s.soundIDs[i]]); + } + _initComplete(bNoDisable); + _event.remove(_win, 'load', _initUserOnload); + return true; + }; + this.canPlayMIME = function(sMIME) { + var result; + if (_s.hasHTML5) { + result = _html5CanPlay({type:sMIME}); + } + if (!_needsFlash || result) { + return result; + } else { + return (sMIME ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); + } + }; + this.canPlayURL = function(sURL) { + var result; + if (_s.hasHTML5) { + result = _html5CanPlay({url: sURL}); + } + if (!_needsFlash || result) { + return result; + } else { + return (sURL ? !!(sURL.match(_s.filePattern)) : null); + } + }; + this.canPlayLink = function(oLink) { + if (typeof oLink.type !== 'undefined' && oLink.type) { + if (_s.canPlayMIME(oLink.type)) { + return true; + } + } + return _s.canPlayURL(oLink.href); + }; + this.getSoundById = function(sID, _suppressDebug) { + if (!sID) { + throw new Error(_sm+'.getSoundById(): sID is null/undefined'); + } + var result = _s.sounds[sID]; + return result; + }; + this.onready = function(oMethod, oScope) { + var sType = 'onready'; + if (oMethod && oMethod instanceof Function) { + if (!oScope) { + oScope = _win; + } + _addOnEvent(sType, oMethod, oScope); + _processOnEvents(); + return true; + } else { + throw _str('needFunction', sType); + } + }; + this.ontimeout = function(oMethod, oScope) { + var sType = 'ontimeout'; + if (oMethod && oMethod instanceof Function) { + if (!oScope) { + oScope = _win; + } + _addOnEvent(sType, oMethod, oScope); + _processOnEvents({type:sType}); + return true; + } else { + throw _str('needFunction', sType); + } + }; + this._writeDebug = function(sText, sType, _bTimestamp) { + return true; + }; + this._wD = this._writeDebug; + this._debug = function() { + }; + this.reboot = function() { + var i, j; + for (i = _s.soundIDs.length; i--;) { + _s.sounds[_s.soundIDs[i]].destruct(); + } + try { + if (_isIE) { + _oRemovedHTML = _s.o.innerHTML; + } + _oRemoved = _s.o.parentNode.removeChild(_s.o); + } catch(e) { + } + _oRemovedHTML = _oRemoved = _needsFlash = null; + _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; + _s.soundIDs = _s.sounds = []; + _s.o = null; + for (i in _on_queue) { + if (_on_queue.hasOwnProperty(i)) { + for (j = _on_queue[i].length; j--;) { + _on_queue[i][j].fired = false; + } + } + } + _win.setTimeout(_s.beginDelayedInit, 20); + }; + this.getMoviePercent = function() { + return (_s.o && typeof _s.o.PercentLoaded !== 'undefined' ? _s.o.PercentLoaded() : null); + }; + this.beginDelayedInit = function() { + _windowLoaded = true; + _domContentLoaded(); + setTimeout(function() { + if (_initPending) { + return false; + } + _createMovie(); + _initMovie(); + _initPending = true; + return true; + }, 20); + _delayWaitForEI(); + }; + this.destruct = function() { + _s.disable(true); + }; + SMSound = function(oOptions) { + var _t = this, _resetProperties, _stop_html5_timer, _start_html5_timer; + this.sID = oOptions.id; + this.url = oOptions.url; + this.options = _mixin(oOptions); + this.instanceOptions = this.options; + this._iO = this.instanceOptions; + this.pan = this.options.pan; + this.volume = this.options.volume; + this._lastURL = null; + this.isHTML5 = false; + this._a = null; + this.id3 = {}; + this._debug = function() { + }; + this.load = function(oOptions) { + var oS = null; + if (typeof oOptions !== 'undefined') { + _t._iO = _mixin(oOptions, _t.options); + _t.instanceOptions = _t._iO; + } else { + oOptions = _t.options; + _t._iO = oOptions; + _t.instanceOptions = _t._iO; + if (_t._lastURL && _t._lastURL !== _t.url) { + _t._iO.url = _t.url; + _t.url = null; + } + } + if (!_t._iO.url) { + _t._iO.url = _t.url; + } + if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { + return _t; + } + _t._lastURL = _t.url; + _t.loaded = false; + _t.readyState = 1; + _t.playState = 0; + if (_html5OK(_t._iO)) { + oS = _t._setup_html5(_t._iO); + if (!oS._called_load) { + _t._html5_canplay = false; + oS.load(); + oS._called_load = true; + if (_t._iO.autoPlay) { + _t.play(); + } + } else { + } + } else { + try { + _t.isHTML5 = false; + _t._iO = _policyFix(_loopFix(_t._iO)); + if (_fV === 8) { + _s.o._load(_t.sID, _t._iO.url, _t._iO.stream, _t._iO.autoPlay, (_t._iO.whileloading?1:0), _t._iO.loops||1, _t._iO.usePolicyFile); + } else { + _s.o._load(_t.sID, _t._iO.url, !!(_t._iO.stream), !!(_t._iO.autoPlay), _t._iO.loops||1, !!(_t._iO.autoLoad), _t._iO.usePolicyFile); + } + } catch(e) { + _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); + } + } + return _t; + }; + this.unload = function() { + if (_t.readyState !== 0) { + if (!_t.isHTML5) { + if (_fV === 8) { + _s.o._unload(_t.sID, _emptyURL); + } else { + _s.o._unload(_t.sID); + } + } else { + _stop_html5_timer(); + if (_t._a) { + _t._a.pause(); + _html5Unload(_t._a); + } + } + _resetProperties(); + } + return _t; + }; + this.destruct = function(_bFromSM) { + if (!_t.isHTML5) { + _t._iO.onfailure = null; + _s.o._destroySound(_t.sID); + } else { + _stop_html5_timer(); + if (_t._a) { + _t._a.pause(); + _html5Unload(_t._a); + if (!_useGlobalHTML5Audio) { + _t._remove_html5_events(); + } + _t._a._t = null; + _t._a = null; + } + } + if (!_bFromSM) { + _s.destroySound(_t.sID, true); + } + }; + this.play = function(oOptions, _updatePlayState) { + var fN = 'SMSound.play(): ', allowMulti, a; + _updatePlayState = _updatePlayState === undefined ? true : _updatePlayState; + if (!oOptions) { + oOptions = {}; + } + _t._iO = _mixin(oOptions, _t._iO); + _t._iO = _mixin(_t._iO, _t.options); + _t.instanceOptions = _t._iO; + if (_t._iO.serverURL && !_t.connected) { + if (!_t.getAutoPlay()) { + _t.setAutoPlay(true); + } + return _t; + } + if (_html5OK(_t._iO)) { + _t._setup_html5(_t._iO); + _start_html5_timer(); + } + if (_t.playState === 1 && !_t.paused) { + allowMulti = _t._iO.multiShot; + if (!allowMulti) { + return _t; + } else { + } + } + if (!_t.loaded) { + if (_t.readyState === 0) { + if (!_t.isHTML5) { + _t._iO.autoPlay = true; + } + _t.load(_t._iO); + } else if (_t.readyState === 2) { + return _t; + } else { + } + } else { + } + if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { + _t._iO.position = 0; + } + if (_t.paused && _t.position && _t.position > 0) { + _t.resume(); + } else { + _t.playState = 1; + _t.paused = false; + if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { + _t.instanceCount++; + } + _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0); + if (!_t.isHTML5) { + _t._iO = _policyFix(_loopFix(_t._iO)); + } + if (_t._iO.onplay && _updatePlayState) { + _t._iO.onplay.apply(_t); + _t._onplay_called = true; + } + _t.setVolume(_t._iO.volume, true); + _t.setPan(_t._iO.pan, true); + if (!_t.isHTML5) { + _s.o._start(_t.sID, _t._iO.loops || 1, (_fV === 9?_t._iO.position:_t._iO.position / 1000)); + } else { + _start_html5_timer(); + a = _t._setup_html5(); + _t.setPosition(_t._iO.position); + a.play(); + } + } + return _t; + }; + this.start = this.play; + this.stop = function(bAll) { + if (_t.playState === 1) { + _t._onbufferchange(0); + _t.resetOnPosition(0); + _t.paused = false; + if (!_t.isHTML5) { + _t.playState = 0; + } + if (_t._iO.onstop) { + _t._iO.onstop.apply(_t); + } + if (!_t.isHTML5) { + _s.o._stop(_t.sID, bAll); + if (_t._iO.serverURL) { + _t.unload(); + } + } else { + if (_t._a) { + _t.setPosition(0); + _t._a.pause(); + _t.playState = 0; + _t._onTimer(); + _stop_html5_timer(); + } + } + _t.instanceCount = 0; + _t._iO = {}; + } + return _t; + }; + this.setAutoPlay = function(autoPlay) { + _t._iO.autoPlay = autoPlay; + if (!_t.isHTML5) { + _s.o._setAutoPlay(_t.sID, autoPlay); + if (autoPlay) { + if (!_t.instanceCount && _t.readyState === 1) { + _t.instanceCount++; + } + } + } + }; + this.getAutoPlay = function() { + return _t._iO.autoPlay; + }; + this.setPosition = function(nMsecOffset) { + if (nMsecOffset === undefined) { + nMsecOffset = 0; + } + var original_pos, + position, position1K, + offset = (_t.isHTML5 ? Math.max(nMsecOffset,0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); + original_pos = _t.position; + _t.position = offset; + position1K = _t.position/1000; + _t.resetOnPosition(_t.position); + _t._iO.position = offset; + if (!_t.isHTML5) { + position = (_fV === 9 ? _t.position : position1K); + if (_t.readyState && _t.readyState !== 2) { + _s.o._setPosition(_t.sID, position, (_t.paused || !_t.playState)); + } + } else if (_t._a) { + if (_t._html5_canplay) { + if (_t._a.currentTime !== position1K) { + try { + _t._a.currentTime = position1K; + if (_t.playState === 0 || _t.paused) { + _t._a.pause(); + } + } catch(e) { + } + } + } else { + } + } + if (_t.isHTML5) { + if (_t.paused) { + _t._onTimer(true); + } + } + return _t; + }; + this.pause = function(_bCallFlash) { + if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { + return _t; + } + _t.paused = true; + if (!_t.isHTML5) { + if (_bCallFlash || _bCallFlash === undefined) { + _s.o._pause(_t.sID); + } + } else { + _t._setup_html5().pause(); + _stop_html5_timer(); + } + if (_t._iO.onpause) { + _t._iO.onpause.apply(_t); + } + return _t; + }; + this.resume = function() { + if (!_t.paused) { + return _t; + } + _t.paused = false; + _t.playState = 1; + if (!_t.isHTML5) { + if (_t._iO.isMovieStar) { + _t.setPosition(_t.position); + } + _s.o._pause(_t.sID); + } else { + _t._setup_html5().play(); + _start_html5_timer(); + } + if (!_t._onplay_called && _t._iO.onplay) { + _t._iO.onplay.apply(_t); + _t._onplay_called = true; + } else if (_t._iO.onresume) { + _t._iO.onresume.apply(_t); + } + return _t; + }; + this.togglePause = function() { + if (_t.playState === 0) { + _t.play({ + position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) + }); + return _t; + } + if (_t.paused) { + _t.resume(); + } else { + _t.pause(); + } + return _t; + }; + this.setPan = function(nPan, bInstanceOnly) { + if (typeof nPan === 'undefined') { + nPan = 0; + } + if (typeof bInstanceOnly === 'undefined') { + bInstanceOnly = false; + } + if (!_t.isHTML5) { + _s.o._setPan(_t.sID, nPan); + } + _t._iO.pan = nPan; + if (!bInstanceOnly) { + _t.pan = nPan; + _t.options.pan = nPan; + } + return _t; + }; + this.setVolume = function(nVol, _bInstanceOnly) { + if (typeof nVol === 'undefined') { + nVol = 100; + } + if (typeof _bInstanceOnly === 'undefined') { + _bInstanceOnly = false; + } + if (!_t.isHTML5) { + _s.o._setVolume(_t.sID, (_s.muted && !_t.muted) || _t.muted?0:nVol); + } else if (_t._a) { + _t._a.volume = Math.max(0, Math.min(1, nVol/100)); + } + _t._iO.volume = nVol; + if (!_bInstanceOnly) { + _t.volume = nVol; + _t.options.volume = nVol; + } + return _t; + }; + this.mute = function() { + _t.muted = true; + if (!_t.isHTML5) { + _s.o._setVolume(_t.sID, 0); + } else if (_t._a) { + _t._a.muted = true; + } + return _t; + }; + this.unmute = function() { + _t.muted = false; + var hasIO = typeof _t._iO.volume !== 'undefined'; + if (!_t.isHTML5) { + _s.o._setVolume(_t.sID, hasIO?_t._iO.volume:_t.options.volume); + } else if (_t._a) { + _t._a.muted = false; + } + return _t; + }; + this.toggleMute = function() { + return (_t.muted?_t.unmute():_t.mute()); + }; + this.onposition = function(nPosition, oMethod, oScope) { + _t._onPositionItems.push({ + position: nPosition, + method: oMethod, + scope: (typeof oScope !== 'undefined'?oScope:_t), + fired: false + }); + return _t; + }; + this.processOnPosition = function() { + var i, item, j = _t._onPositionItems.length; + if (!j || !_t.playState || _t._onPositionFired >= j) { + return false; + } + for (i=j; i--;) { + item = _t._onPositionItems[i]; + if (!item.fired && _t.position >= item.position) { + item.fired = true; + _s._onPositionFired++; + item.method.apply(item.scope,[item.position]); + } + } + return true; + }; + this.resetOnPosition = function(nPosition) { + var i, item, j = _t._onPositionItems.length; + if (!j) { + return false; + } + for (i=j; i--;) { + item = _t._onPositionItems[i]; + if (item.fired && nPosition <= item.position) { + item.fired = false; + _s._onPositionFired--; + } + } + return true; + }; + _start_html5_timer = function() { + if (_t.isHTML5) { + _startTimer(_t); + } + }; + _stop_html5_timer = function() { + if (_t.isHTML5) { + _stopTimer(_t); + } + }; + _resetProperties = function() { + _t._onPositionItems = []; + _t._onPositionFired = 0; + _t._hasTimer = null; + _t._onplay_called = false; + _t._a = null; + _t._html5_canplay = false; + _t.bytesLoaded = null; + _t.bytesTotal = null; + _t.position = null; + _t.duration = (_t._iO && _t._iO.duration?_t._iO.duration:null); + _t.durationEstimate = null; + _t.failures = 0; + _t.loaded = false; + _t.playState = 0; + _t.paused = false; + _t.readyState = 0; + _t.muted = false; + _t.isBuffering = false; + _t.instanceOptions = {}; + _t.instanceCount = 0; + _t.peakData = { + left: 0, + right: 0 + }; + _t.waveformData = { + left: [], + right: [] + }; + _t.eqData = []; + _t.eqData.left = []; + _t.eqData.right = []; + }; + _resetProperties(); + this._onTimer = function(bForce) { + var time, x = {}; + if (_t._hasTimer || bForce) { + if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { + _t.duration = _t._get_html5_duration(); + _t.durationEstimate = _t.duration; + time = _t._a.currentTime?_t._a.currentTime*1000:0; + _t._whileplaying(time,x,x,x,x); + return true; + } else { + return false; + } + } + }; + this._get_html5_duration = function() { + var d = (_t._a ? _t._a.duration*1000 : (_t._iO ? _t._iO.duration : undefined)), + result = (d && !isNaN(d) && d !== Infinity ? d : (_t._iO ? _t._iO.duration : null)); + return result; + }; + this._setup_html5 = function(oOptions) { + var _iO = _mixin(_t._iO, oOptions), d = decodeURI, + _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, + _dURL = d(_iO.url), + _oldIO = (_a && _a._t ? _a._t.instanceOptions : null); + if (_a) { + if (_a._t && _oldIO.url === _iO.url && (!_t._lastURL || (_t._lastURL === _oldIO.url))) { + return _a; + } + if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { + _a._t.stop(); + } + _resetProperties(); + _a.src = _iO.url; + _t.url = _iO.url; + _t._lastURL = _iO.url; + _a._called_load = false; + } else { + _a = new Audio(_iO.url); + _a._called_load = false; + if (_is_android) { + _a._called_load = true; + } + if (_useGlobalHTML5Audio) { + _s._global_a = _a; + } + } + _t.isHTML5 = true; + _t._a = _a; + _a._t = _t; + _t._add_html5_events(); + _a.loop = (_iO.loops>1?'loop':''); + if (_iO.autoLoad || _iO.autoPlay) { + _a.autobuffer = 'auto'; + _a.preload = 'auto'; + _t.load(); + _a._called_load = true; + } else { + _a.autobuffer = false; + _a.preload = 'none'; + } + _a.loop = (_iO.loops>1?'loop':''); + return _a; + }; + this._add_html5_events = function() { + if (_t._a._added_events) { + return false; + } + var f; + function add(oEvt, oFn, bCapture) { + return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null; + } + _t._a._added_events = true; + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + add(f, _html5_events[f]); + } + } + return true; + }; + this._remove_html5_events = function() { + var f; + function remove(oEvt, oFn, bCapture) { + return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); + } + _t._a._added_events = false; + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + remove(f, _html5_events[f]); + } + } + }; + this._onload = function(nSuccess) { + var fN = 'SMSound._onload(): ', loadOK = !!(nSuccess); + _t.loaded = loadOK; + _t.readyState = loadOK?3:2; + _t._onbufferchange(0); + if (_t._iO.onload) { + _t._iO.onload.apply(_t, [loadOK]); + } + return true; + }; + this._onbufferchange = function(nIsBuffering) { + var fN = 'SMSound._onbufferchange()'; + if (_t.playState === 0) { + return false; + } + if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { + return false; + } + _t.isBuffering = (nIsBuffering === 1); + if (_t._iO.onbufferchange) { + _t._iO.onbufferchange.apply(_t); + } + return true; + }; + this._onsuspend = function () { + if (_t._iO.onsuspend) { + _t._iO.onsuspend.apply(_t); + } + return true; + }; + this._onfailure = function(msg, level, code) { + _t.failures++; + if (_t._iO.onfailure && _t.failures === 1) { + _t._iO.onfailure(_t, msg, level, code); + } else { + } + }; + this._onfinish = function() { + var _io_onfinish = _t._iO.onfinish; + _t._onbufferchange(0); + _t.resetOnPosition(0); + if (_t.instanceCount) { + _t.instanceCount--; + if (!_t.instanceCount) { + _t.playState = 0; + _t.paused = false; + _t.instanceCount = 0; + _t.instanceOptions = {}; + _t._iO = {}; + _stop_html5_timer(); + } + if (!_t.instanceCount || _t._iO.multiShotEvents) { + if (_io_onfinish) { + _io_onfinish.apply(_t); + } + } + } + }; + this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { + _t.bytesLoaded = nBytesLoaded; + _t.bytesTotal = nBytesTotal; + _t.duration = Math.floor(nDuration); + _t.bufferLength = nBufferLength; + if (!_t._iO.isMovieStar) { + if (_t._iO.duration) { + _t.durationEstimate = (_t.duration > _t._iO.duration) ? _t.duration : _t._iO.duration; + } else { + _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); + } + if (_t.durationEstimate === undefined) { + _t.durationEstimate = _t.duration; + } + if (_t.readyState !== 3 && _t._iO.whileloading) { + _t._iO.whileloading.apply(_t); + } + } else { + _t.durationEstimate = _t.duration; + if (_t.readyState !== 3 && _t._iO.whileloading) { + _t._iO.whileloading.apply(_t); + } + } + }; + this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { + if (isNaN(nPosition) || nPosition === null) { + return false; + } + _t.position = nPosition; + _t.processOnPosition(); + if (!_t.isHTML5 && _fV > 8) { + if (_t._iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { + _t.peakData = { + left: oPeakData.leftPeak, + right: oPeakData.rightPeak + }; + } + if (_t._iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { + _t.waveformData = { + left: oWaveformDataLeft.split(','), + right: oWaveformDataRight.split(',') + }; + } + if (_t._iO.useEQData) { + if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { + var eqLeft = oEQData.leftEQ.split(','); + _t.eqData = eqLeft; + _t.eqData.left = eqLeft; + if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) { + _t.eqData.right = oEQData.rightEQ.split(','); + } + } + } + } + if (_t.playState === 1) { + if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { + _t._onbufferchange(0); + } + if (_t._iO.whileplaying) { + _t._iO.whileplaying.apply(_t); + } + } + return true; + }; + this._onid3 = function(oID3PropNames, oID3Data) { + var oData = [], i, j; + for (i = 0, j = oID3PropNames.length; i < j; i++) { + oData[oID3PropNames[i]] = oID3Data[i]; + } + _t.id3 = _mixin(_t.id3, oData); + if (_t._iO.onid3) { + _t._iO.onid3.apply(_t); + } + }; + this._onconnect = function(bSuccess) { + var fN = 'SMSound._onconnect(): '; + bSuccess = (bSuccess === 1); + _t.connected = bSuccess; + if (bSuccess) { + _t.failures = 0; + if (_idCheck(_t.sID)) { + if (_t.getAutoPlay()) { + _t.play(undefined, _t.getAutoPlay()); + } else if (_t._iO.autoLoad) { + _t.load(); + } + } + if (_t._iO.onconnect) { + _t._iO.onconnect.apply(_t,[bSuccess]); + } + } + }; + this._ondataerror = function(sError) { + if (_t.playState > 0) { + if (_t._iO.ondataerror) { + _t._iO.ondataerror.apply(_t); + } + } + }; + }; + _getDocument = function() { + return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); + }; + _id = function(sID) { + return _doc.getElementById(sID); + }; + _mixin = function(oMain, oAdd) { + var o1 = {}, i, o2, o; + for (i in oMain) { + if (oMain.hasOwnProperty(i)) { + o1[i] = oMain[i]; + } + } + o2 = (typeof oAdd === 'undefined'?_s.defaultOptions:oAdd); + for (o in o2) { + if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { + o1[o] = o2[o]; + } + } + return o1; + }; + _event = (function() { + var old = (_win.attachEvent), + evt = { + add: (old?'attachEvent':'addEventListener'), + remove: (old?'detachEvent':'removeEventListener') + }; + function getArgs(oArgs) { + var args = _slice.call(oArgs), len = args.length; + if (old) { + args[1] = 'on' + args[1]; + if (len > 3) { + args.pop(); + } + } else if (len === 3) { + args.push(false); + } + return args; + } + function apply(args, sType) { + var element = args.shift(), + method = [evt[sType]]; + if (old) { + element[method](args[0], args[1]); + } else { + element[method].apply(element, args); + } + } + function add() { + apply(getArgs(arguments), 'add'); + } + function remove() { + apply(getArgs(arguments), 'remove'); + } + return { + 'add': add, + 'remove': remove + }; + }()); + function _html5_event(oFn) { + return function(e) { + if (!this._t || !this._t._a) { + return null; + } else { + return oFn.call(this, e); + } + }; + } + _html5_events = { + abort: _html5_event(function(e) { + }), + canplay: _html5_event(function(e) { + if (this._t._html5_canplay) { + return true; + } + this._t._html5_canplay = true; + this._t._onbufferchange(0); + var position1K = (!isNaN(this._t.position)?this._t.position/1000:null); + if (this._t.position && this.currentTime !== position1K) { + try { + this.currentTime = position1K; + } catch(ee) { + } + } + }), + load: _html5_event(function(e) { + if (!this._t.loaded) { + this._t._onbufferchange(0); + this._t._whileloading(this._t.bytesTotal, this._t.bytesTotal, this._t._get_html5_duration()); + this._t._onload(true); + } + }), + emptied: _html5_event(function(e) { + }), + ended: _html5_event(function(e) { + this._t._onfinish(); + }), + error: _html5_event(function(e) { + this._t._onload(false); + }), + loadeddata: _html5_event(function(e) { + var t = this._t, + bytesTotal = t.bytesTotal || 1; + if (!t._loaded && !_isSafari) { + t.duration = t._get_html5_duration(); + t._whileloading(bytesTotal, bytesTotal, t._get_html5_duration()); + t._onload(true); + } + }), + loadedmetadata: _html5_event(function(e) { + }), + loadstart: _html5_event(function(e) { + this._t._onbufferchange(1); + }), + play: _html5_event(function(e) { + this._t._onbufferchange(0); + }), + playing: _html5_event(function(e) { + this._t._onbufferchange(0); + }), + progress: _html5_event(function(e) { + if (this._t.loaded) { + return false; + } + var i, j, str, buffered = 0, + isProgress = (e.type === 'progress'), + ranges = e.target.buffered, + loaded = (e.loaded||0), + total = (e.total||1); + if (ranges && ranges.length) { + for (i=ranges.length; i--;) { + buffered = (ranges.end(i) - ranges.start(i)); + } + loaded = buffered/e.target.duration; + } + if (!isNaN(loaded)) { + this._t._onbufferchange(0); + this._t._whileloading(loaded, total, this._t._get_html5_duration()); + if (loaded && total && loaded === total) { + _html5_events.load.call(this, e); + } + } + }), + ratechange: _html5_event(function(e) { + }), + suspend: _html5_event(function(e) { + _html5_events.progress.call(this, e); + this._t._onsuspend(); + }), + stalled: _html5_event(function(e) { + }), + timeupdate: _html5_event(function(e) { + this._t._onTimer(); + }), + waiting: _html5_event(function(e) { + this._t._onbufferchange(1); + }) + }; + _html5OK = function(iO) { + return (!iO.serverURL && (iO.type?_html5CanPlay({type:iO.type}):_html5CanPlay({url:iO.url})||_s.html5Only)); + }; + _html5Unload = function(oAudio) { + if (oAudio) { + oAudio.src = (_is_firefox ? '' : _emptyURL); + } + }; + _html5CanPlay = function(o) { + if (!_s.useHTML5Audio || !_s.hasHTML5) { + return false; + } + var url = (o.url || null), + mime = (o.type || null), + aF = _s.audioFormats, + result, + offset, + fileExt, + item; + function preferFlashCheck(kind) { + return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); + } + if (mime && _s.html5[mime] !== 'undefined') { + return (_s.html5[mime] && !preferFlashCheck(mime)); + } + if (!_html5Ext) { + _html5Ext = []; + for (item in aF) { + if (aF.hasOwnProperty(item)) { + _html5Ext.push(item); + if (aF[item].related) { + _html5Ext = _html5Ext.concat(aF[item].related); + } + } + } + _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')(\\?.*)?$','i'); + } + fileExt = (url ? url.toLowerCase().match(_html5Ext) : null); + if (!fileExt || !fileExt.length) { + if (!mime) { + return false; + } else { + offset = mime.indexOf(';'); + fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); + } + } else { + fileExt = fileExt[1]; + } + if (fileExt && typeof _s.html5[fileExt] !== 'undefined') { + return (_s.html5[fileExt] && !preferFlashCheck(fileExt)); + } else { + mime = 'audio/'+fileExt; + result = _s.html5.canPlayType({type:mime}); + _s.html5[fileExt] = result; + return (result && _s.html5[mime] && !preferFlashCheck(mime)); + } + }; + _testHTML5 = function() { + if (!_s.useHTML5Audio || typeof Audio === 'undefined') { + return false; + } + var a = (typeof Audio !== 'undefined' ? (_isOpera ? new Audio(null) : new Audio()) : null), + item, support = {}, aF, i; + function _cp(m) { + var canPlay, i, j, isOK = false; + if (!a || typeof a.canPlayType !== 'function') { + return false; + } + if (m instanceof Array) { + for (i=0, j=m.length; i 1 && sOpt.stream) { + sOpt.stream = false; + } + return sOpt; + }; + _policyFix = function(sOpt, sPre) { + if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { + sOpt.usePolicyFile = true; + } + return sOpt; + }; + _complain = function(sMsg) { + }; + _doNothing = function() { + return false; + }; + _disableObject = function(o) { + var oProp; + for (oProp in o) { + if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { + o[oProp] = _doNothing; + } + } + oProp = null; + }; + _failSafely = function(bNoDisable) { + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + if (_disabled || bNoDisable) { + _s.disable(bNoDisable); + } + }; + _normalizeMovieURL = function(smURL) { + var urlParams = null, url; + if (smURL) { + if (smURL.match(/\.swf(\?.*)?$/i)) { + urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); + if (urlParams) { + return smURL; + } + } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { + smURL += '/'; + } + } + url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; + if (_s.noSWFCache) { + url += ('?ts=' + new Date().getTime()); + } + return url; + }; + _setVersionInfo = function() { + _fV = parseInt(_s.flashVersion, 10); + if (_fV !== 8 && _fV !== 9) { + _s.flashVersion = _fV = _defaultFlashVersion; + } + var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); + if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { + _s.flashVersion = _fV = 9; + } + _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); + if (_fV > 8) { + _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); + _s.features.buffering = true; + _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); + _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + _s.features.movieStar = true; + } else { + _s.features.movieStar = false; + } + _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; + _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); + _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); + }; + _setPolling = function(bPolling, bHighPerformance) { + if (!_s.o) { + return false; + } + _s.o._setPolling(bPolling, bHighPerformance); + }; + _initDebug = function() { + if (_s.debugURLParam.test(_wl)) { + _s.debugMode = true; + } + }; + _idCheck = this.getSoundById; + _getSWFCSS = function() { + var css = []; + if (_s.debugMode) { + css.push(_s.swfCSS.sm2Debug); + } + if (_s.debugFlash) { + css.push(_s.swfCSS.flashDebug); + } + if (_s.useHighPerformance) { + css.push(_s.swfCSS.highPerf); + } + return css.join(' '); + }; + _flashBlockHandler = function() { + var name = _str('fbHandler'), + p = _s.getMoviePercent(), + css = _s.swfCSS, + error = {type:'FLASHBLOCK'}; + if (_s.html5Only) { + return false; + } + if (!_s.ok()) { + if (_needsFlash) { + _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); + } + _s.didFlashBlock = true; + _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); + _catchError(error); + } else { + if (_s.didFlashBlock) { + } + if (_s.oMC) { + _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); + } + } + }; + _addOnEvent = function(sType, oMethod, oScope) { + if (typeof _on_queue[sType] === 'undefined') { + _on_queue[sType] = []; + } + _on_queue[sType].push({ + 'method': oMethod, + 'scope': (oScope || null), + 'fired': false + }); + }; + _processOnEvents = function(oOptions) { + if (!oOptions) { + oOptions = { + type: 'onready' + }; + } + if (!_didInit && oOptions && !oOptions.ignoreInit) { + return false; + } + if (oOptions.type === 'ontimeout' && _s.ok()) { + return false; + } + var status = { + success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) + }, + srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), + queue = [], i, j, + args = [status], + canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); + if (oOptions.error) { + args[0].error = oOptions.error; + } + for (i = 0, j = srcQueue.length; i < j; i++) { + if (srcQueue[i].fired !== true) { + queue.push(srcQueue[i]); + } + } + if (queue.length) { + for (i = 0, j = queue.length; i < j; i++) { + if (queue[i].scope) { + queue[i].method.apply(queue[i].scope, args); + } else { + queue[i].method.apply(this, args); + } + if (!canRetry) { + queue[i].fired = true; + } + } + } + return true; + }; + _initUserOnload = function() { + _win.setTimeout(function() { + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + _processOnEvents(); + if (_s.onload instanceof Function) { + _s.onload.apply(_win); + } + if (_s.waitForWindowLoad) { + _event.add(_win, 'load', _initUserOnload); + } + },1); + }; + _detectFlash = function() { + if (_hasFlash !== undefined) { + return _hasFlash; + } + var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; + if (nP && nP.length) { + type = 'application/x-shockwave-flash'; + types = n.mimeTypes; + if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { + hasPlugin = true; + } + } else if (typeof AX !== 'undefined') { + try { + obj = new AX('ShockwaveFlash.ShockwaveFlash'); + } catch(e) { + } + hasPlugin = (!!obj); + } + _hasFlash = hasPlugin; + return hasPlugin; + }; + _featureCheck = function() { + var needsFlash, item, + isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); + if (isSpecial) { + _s.hasHTML5 = false; + _s.html5Only = true; + if (_s.oMC) { + _s.oMC.style.display = 'none'; + } + return false; + } + if (_s.useHTML5Audio) { + if (!_s.html5 || !_s.html5.canPlayType) { + _s.hasHTML5 = false; + return true; + } else { + _s.hasHTML5 = true; + } + if (_isBadSafari) { + if (_detectFlash()) { + return true; + } + } + } else { + return true; + } + for (item in _s.audioFormats) { + if (_s.audioFormats.hasOwnProperty(item)) { + if ((_s.audioFormats[item].required && !_s.html5.canPlayType(_s.audioFormats[item].type)) || _s.flash[item] || _s.flash[_s.audioFormats[item].type]) { + needsFlash = true; + } + } + } + if (_s.ignoreFlash) { + needsFlash = false; + } + _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); + return (!_s.html5Only); + }; + _startTimer = function(oSound) { + if (!oSound._hasTimer) { + oSound._hasTimer = true; + } + }; + _stopTimer = function(oSound) { + if (oSound._hasTimer) { + oSound._hasTimer = false; + } + }; + _catchError = function(options) { + options = (typeof options !== 'undefined' ? options : {}); + if (_s.onerror instanceof Function) { + _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); + } + if (typeof options.fatal !== 'undefined' && options.fatal) { + _s.disable(); + } + }; + _badSafariFix = function() { + if (!_isBadSafari || !_detectFlash()) { + return false; + } + var aF = _s.audioFormats, i, item; + for (item in aF) { + if (aF.hasOwnProperty(item)) { + if (item === 'mp3' || item === 'mp4') { + _s.html5[item] = false; + if (aF[item] && aF[item].related) { + for (i = aF[item].related.length; i--;) { + _s.html5[aF[item].related[i]] = false; + } + } + } + } + } + }; + this._setSandboxType = function(sandboxType) { + }; + this._externalInterfaceOK = function(flashDate) { + if (_s.swfLoaded) { + return false; + } + var eiTime = new Date().getTime(); + _s.swfLoaded = true; + _tryInitOnFocus = false; + if (_isBadSafari) { + _badSafariFix(); + } + if (_isIE) { + setTimeout(_init, 100); + } else { + _init(); + } + }; + _createMovie = function(smID, smURL) { + if (_didAppend && _appendSuccess) { + return false; + } + function _initMsg() { + } + if (_s.html5Only) { + _setVersionInfo(); + _initMsg(); + _s.oMC = _id(_s.movieID); + _init(); + _didAppend = true; + _appendSuccess = true; + return false; + } + var remoteURL = (smURL || _s.url), + localURL = (_s.altURL || remoteURL), + swfTitle = 'JS/Flash audio component (SoundManager 2)', + oEmbed, oMovie, oTarget = _getDocument(), tmp, movieHTML, oEl, extraClass = _getSWFCSS(), + s, x, sClass, side = 'auto', isRTL = null, + html = _doc.getElementsByTagName('html')[0]; + isRTL = (html && html.dir && html.dir.match(/rtl/i)); + smID = (typeof smID === 'undefined'?_s.id:smID); + function param(name, value) { + return ''; + } + _setVersionInfo(); + _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); + smURL = _s.url; + _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); + if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { + _s.specialWmodeCase = true; + _s.wmode = null; + } + oEmbed = { + 'name': smID, + 'id': smID, + 'src': smURL, + 'width': side, + 'height': side, + 'quality': 'high', + 'allowScriptAccess': _s.allowScriptAccess, + 'bgcolor': _s.bgColor, + 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', + 'title': swfTitle, + 'type': 'application/x-shockwave-flash', + 'wmode': _s.wmode, + 'hasPriority': 'true' + }; + if (_s.debugFlash) { + oEmbed.FlashVars = 'debug=1'; + } + if (!_s.wmode) { + delete oEmbed.wmode; + } + if (_isIE) { + oMovie = _doc.createElement('div'); + movieHTML = [ + '', + param('movie', smURL), + param('AllowScriptAccess', _s.allowScriptAccess), + param('quality', oEmbed.quality), + (_s.wmode? param('wmode', _s.wmode): ''), + param('bgcolor', _s.bgColor), + param('hasPriority', 'true'), + (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), + '' + ].join(''); + } else { + oMovie = _doc.createElement('embed'); + for (tmp in oEmbed) { + if (oEmbed.hasOwnProperty(tmp)) { + oMovie.setAttribute(tmp, oEmbed[tmp]); + } + } + } + _initDebug(); + extraClass = _getSWFCSS(); + oTarget = _getDocument(); + if (oTarget) { + _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); + if (!_s.oMC.id) { + _s.oMC.id = _s.movieID; + _s.oMC.className = _s.swfCSS.swfDefault + ' ' + extraClass; + s = null; + oEl = null; + if (!_s.useFlashBlock) { + if (_s.useHighPerformance) { + s = { + 'position': 'fixed', + 'width': '8px', + 'height': '8px', + 'bottom': '0px', + 'left': '0px', + 'overflow': 'hidden' + }; + } else { + s = { + 'position': 'absolute', + 'width': '6px', + 'height': '6px', + 'top': '-9999px', + 'left': '-9999px' + }; + if (isRTL) { + s.left = Math.abs(parseInt(s.left,10))+'px'; + } + } + } + if (_isWebkit) { + _s.oMC.style.zIndex = 10000; + } + if (!_s.debugFlash) { + for (x in s) { + if (s.hasOwnProperty(x)) { + _s.oMC.style[x] = s[x]; + } + } + } + try { + if (!_isIE) { + _s.oMC.appendChild(oMovie); + } + oTarget.appendChild(_s.oMC); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _s.swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + } catch(e) { + throw new Error(_str('domError')+' \n'+e.toString()); + } + } else { + sClass = _s.oMC.className; + _s.oMC.className = (sClass?sClass+' ':_s.swfCSS.swfDefault) + (extraClass?' '+extraClass:''); + _s.oMC.appendChild(oMovie); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _s.swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + } + } + _didAppend = true; + _initMsg(); + return true; + }; + _initMovie = function() { + if (_s.html5Only) { + _createMovie(); + return false; + } + if (_s.o) { + return false; + } + _s.o = _s.getMovie(_s.id); + if (!_s.o) { + if (!_oRemoved) { + _createMovie(_s.id, _s.url); + } else { + if (!_isIE) { + _s.oMC.appendChild(_oRemoved); + } else { + _s.oMC.innerHTML = _oRemovedHTML; + } + _oRemoved = null; + _didAppend = true; + } + _s.o = _s.getMovie(_s.id); + } + if (_s.oninitmovie instanceof Function) { + setTimeout(_s.oninitmovie, 1); + } + return true; + }; + _delayWaitForEI = function() { + setTimeout(_waitForEI, 1000); + }; + _waitForEI = function() { + if (_waitingForEI) { + return false; + } + _waitingForEI = true; + _event.remove(_win, 'load', _delayWaitForEI); + if (_tryInitOnFocus && !_isFocused) { + return false; + } + var p; + if (!_didInit) { + p = _s.getMoviePercent(); + } + setTimeout(function() { + p = _s.getMoviePercent(); + if (!_didInit && _okToDisable) { + if (p === null) { + if (_s.useFlashBlock || _s.flashLoadTimeout === 0) { + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + } else { + _failSafely(true); + } + } else { + if (_s.flashLoadTimeout === 0) { + } else { + _failSafely(true); + } + } + } + }, _s.flashLoadTimeout); + }; + _handleFocus = function() { + function cleanup() { + _event.remove(_win, 'focus', _handleFocus); + _event.remove(_win, 'load', _handleFocus); + } + if (_isFocused || !_tryInitOnFocus) { + cleanup(); + return true; + } + _okToDisable = true; + _isFocused = true; + if (_isSafari && _tryInitOnFocus) { + _event.remove(_win, 'mousemove', _handleFocus); + } + _waitingForEI = false; + cleanup(); + return true; + }; + _showSupport = function() { + var item, tests = []; + if (_s.useHTML5Audio && _s.hasHTML5) { + for (item in _s.audioFormats) { + if (_s.audioFormats.hasOwnProperty(item)) { + tests.push(item + ': ' + _s.html5[item] + (!_s.html5[item] && _hasFlash && _s.flash[item] ? ' (using flash)' : (_s.preferFlash && _s.flash[item] && _hasFlash ? ' (preferring flash)': (!_s.html5[item] ? ' (' + (_s.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : '')))); + } + } + } + }; + _initComplete = function(bNoDisable) { + if (_didInit) { + return false; + } + if (_s.html5Only) { + _didInit = true; + _initUserOnload(); + return true; + } + var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), + error; + if (!wasTimeout) { + _didInit = true; + if (_disabled) { + error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; + } + } + if (_disabled || bNoDisable) { + if (_s.useFlashBlock && _s.oMC) { + _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_s.swfCSS.swfTimedout:_s.swfCSS.swfError); + } + _processOnEvents({type:'ontimeout', error:error}); + _catchError(error); + return false; + } else { + } + if (_s.waitForWindowLoad && !_windowLoaded) { + _event.add(_win, 'load', _initUserOnload); + return false; + } else { + _initUserOnload(); + } + return true; + }; + _init = function() { + if (_didInit) { + return false; + } + function _cleanup() { + _event.remove(_win, 'load', _s.beginDelayedInit); + } + if (_s.html5Only) { + if (!_didInit) { + _cleanup(); + _s.enabled = true; + _initComplete(); + } + return true; + } + _initMovie(); + try { + _s.o._externalInterfaceTest(false); + _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); + if (!_s.debugMode) { + _s.o._disableDebug(); + } + _s.enabled = true; + if (!_s.html5Only) { + _event.add(_win, 'unload', _doNothing); + } + } catch(e) { + _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); + _failSafely(true); + _initComplete(); + return false; + } + _initComplete(); + _cleanup(); + return true; + }; + _domContentLoaded = function() { + if (_didDCLoaded) { + return false; + } + _didDCLoaded = true; + _initDebug(); + if (!_hasFlash && _s.hasHTML5) { + _s.useHTML5Audio = true; + _s.preferFlash = false; + } + _testHTML5(); + _s.html5.usingFlash = _featureCheck(); + _needsFlash = _s.html5.usingFlash; + _showSupport(); + if (!_hasFlash && _needsFlash) { + _s.flashLoadTimeout = 1; + } + if (_doc.removeEventListener) { + _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); + } + _initMovie(); + return true; + }; + _domContentLoadedIE = function() { + if (_doc.readyState === 'complete') { + _domContentLoaded(); + _doc.detachEvent('onreadystatechange', _domContentLoadedIE); + } + return true; + }; + _detectFlash(); + _event.add(_win, 'focus', _handleFocus); + _event.add(_win, 'load', _handleFocus); + _event.add(_win, 'load', _delayWaitForEI); + if (_isSafari && _tryInitOnFocus) { + _event.add(_win, 'mousemove', _handleFocus); + } + if (_doc.addEventListener) { + _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); + } else if (_doc.attachEvent) { + _doc.attachEvent('onreadystatechange', _domContentLoadedIE); + } else { + _catchError({type:'NO_DOM2_EVENTS', fatal:true}); + } + if (_doc.readyState === 'complete') { + setTimeout(_domContentLoaded,100); + } +} +// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading +if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { + soundManager = new SoundManager(); +} +window.SoundManager = SoundManager; +window.soundManager = soundManager; +}(window)); \ No newline at end of file diff --git a/telemeta/htdocs/timeside/js/libs/soundmanager2.js b/telemeta/htdocs/timeside/js/libs/soundmanager2.js index b64aa62c..6e4cb4f9 100755 --- a/telemeta/htdocs/timeside/js/libs/soundmanager2.js +++ b/telemeta/htdocs/timeside/js/libs/soundmanager2.js @@ -1,4 +1,5 @@ /** @license + * * SoundManager 2: JavaScript Sound for the Web * ---------------------------------------------- * http://schillmania.com/projects/soundmanager2/ @@ -7,119 +8,163 @@ * Code provided under the BSD License: * http://schillmania.com/projects/soundmanager2/license.txt * - * V2.97a.20110424 + * V2.97a.20111030 */ -/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */ /*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ +/* jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ + +/** + * About this file + * --------------- + * This is the fully-commented source version of the SoundManager 2 API, + * recommended for use during development and testing. + * + * See soundmanager2-nodebug-jsmin.js for an optimized build (~10KB with gzip.) + * http://schillmania.com/projects/soundmanager2/doc/getstarted/#basic-inclusion + * Alternately, serve this file with gzip for 75% compression savings (~30KB over HTTP.) + * + * You may notice and comments in this source; these are delimiters for + * debug blocks which are removed in the -nodebug builds, further optimizing code size. + */ (function(window) { var soundManager = null; +/** + * The SoundManager constructor. + * + * @constructor + * @param {string} smURL Optional: Path to SWF files + * @param {string} smID Optional: The ID to use for the SWF container element + * @this {SoundManager} + * @return {SoundManager} The new SoundManager instance + */ + function SoundManager(smURL, smID) { + // Top-level configuration options + this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9. this.debugMode = true; // enable debugging output (div#soundmanager-debug, OR console if available+configured) this.debugFlash = false; // enable debugging output inside SWF, troubleshoot Flash/browser issues this.useConsole = true; // use firebug/safari console.log()-type debug console if available this.consoleOnly = false; // if console is being used, do not create/write to #soundmanager-debug this.waitForWindowLoad = false; // force SM2 to wait for window.onload() before trying to call soundManager.onload() - this.nullURL = 'about:blank'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only) - this.allowPolling = true; // allow flash to poll for status update (required for whileplaying() events, peak, sound spectrum functions to work.) - this.useFastPolling = false; // uses lower flash timer interval for higher callback frequency, best combined with useHighPerformance - this.useMovieStar = true; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio formats (AAC, M4V, FLV, MOV etc.) this.bgColor = '#ffffff'; // movie (.swf) background color, eg. '#000000' this.useHighPerformance = false; // position:fixed flash movie can help increase js/flash speed, minimize lag - this.flashPollingInterval = null; // msec for polling interval. Defaults to 50 unless useFastPolling = true. + this.flashPollingInterval = null; // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used. this.flashLoadTimeout = 1000; // msec to wait for flash movie to load before failing (0 = infinity) this.wmode = null; // string: flash rendering mode - null, transparent, opaque (last two allow layering of HTML on top) this.allowScriptAccess = 'always'; // for scripting the SWF (object/embed property), either 'always' or 'sameDomain' this.useFlashBlock = false; // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable. - this.useHTML5Audio = false; // Beta feature: Use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible. - this.html5Test = /^probably$/i; // HTML5 Audio().canPlayType() test. /^(probably|maybe)$/i if you want to be more liberal/risky. - this.useGlobalHTML5Audio = true; // (experimental) if true, re-use single HTML5 audio object across all sounds. Enabled by default on mobile devices/iOS. - this.requireFlash = false; // (experimental) if true, prevents "HTML5-only" mode when flash present. Allows flash to handle RTMP/serverURL, but HTML5 for other cases + this.useHTML5Audio = true; // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible. + this.html5Test = /^(probably|maybe)$/i; // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative. + this.preferFlash = true; // overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed since HTML5 audio support is still quirky in browsers. + this.noSWFCache = false; // if true, appends ?ts={date} to break aggressive SWF caching. this.audioFormats = { - // determines HTML5 support, flash requirements - // eg. if MP3 or MP4 required, Flash fallback is used if HTML5 can't play it - // shotgun approach to MIME testing due to browser variance + + /** + * determines HTML5 support + flash requirements. + * if no support (via flash and/or HTML5) for a "required" format, SM2 will fail to start. + * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true) + * multiple MIME types may be tested while trying to get a positive canPlayType() response. + */ + 'mp3': { - 'type': ['audio/mpeg; codecs="mp3"','audio/mpeg','audio/mp3','audio/MPA','audio/mpa-robust'], + 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], 'required': true }, + 'mp4': { 'related': ['aac','m4a'], // additional formats under the MP4 container - 'type': ['audio/mp4; codecs="mp4a.40.2"','audio/aac','audio/x-m4a','audio/MP4A-LATM','audio/mpeg4-generic'], - 'required': true + 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], + 'required': false + }, + 'ogg': { 'type': ['audio/ogg; codecs=vorbis'], 'required': false }, + 'wav': { - 'type': ['audio/wav; codecs="1"','audio/wav','audio/wave','audio/x-wav'], + 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], 'required': false } + }; this.defaultOptions = { - 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can) - 'stream': true, // allows playing before entire file has loaded (recommended) - 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true) - 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0) - 'onid3': null, // callback function for "ID3 data is added/available" - 'onload': null, // callback function for "load finished" - 'whileloading': null, // callback function for "download progress update" (X of Y bytes received) - 'onplay': null, // callback for "play" start - 'onpause': null, // callback for "pause" - 'onresume': null, // callback for "resume" (pause toggle) - 'whileplaying': null, // callback during play (position update) - 'onstop': null, // callback for "user stop" - 'onfailure': null, // callback function for when playing fails - 'onfinish': null, // callback function for "sound finished playing" - 'onbeforefinish': null, // callback for "before sound finished playing (at [time])" - 'onbeforefinishtime': 5000, // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second) - 'onbeforefinishcomplete': null,// function to call when said sound finishes playing - 'onjustbeforefinish': null, // callback for [n] msec before end of current sound - 'onjustbeforefinishtime': 200, // [n] - if not using, set to 0 (or null handler) and event will not fire. - 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time - 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled - 'position': null, // offset (milliseconds) to seek to within loaded sound data. - 'pan': 0, // "pan" settings, left-to-right, -100 to 100 - 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3 - 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access) - 'volume': 100 // self-explanatory. 0-100, the latter being the max. - }; - - this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used + + /** + * the default configuration for sound objects made with createSound() and related methods + * eg., volume, auto-load behaviour and so forth + */ + + 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can) + 'stream': true, // allows playing before entire file has loaded (recommended) + 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true) + 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0) + 'onid3': null, // callback function for "ID3 data is added/available" + 'onload': null, // callback function for "load finished" + 'whileloading': null, // callback function for "download progress update" (X of Y bytes received) + 'onplay': null, // callback for "play" start + 'onpause': null, // callback for "pause" + 'onresume': null, // callback for "resume" (pause toggle) + 'whileplaying': null, // callback during play (position update) + 'onstop': null, // callback for "user stop" + 'onfailure': null, // callback function for when playing fails + 'onfinish': null, // callback function for "sound finished playing" + 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time + 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled + 'position': null, // offset (milliseconds) to seek to within loaded sound data. + 'pan': 0, // "pan" settings, left-to-right, -100 to 100 + 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3 + 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access) + 'volume': 100 // self-explanatory. 0-100, the latter being the max. + + }; + + this.flash9Options = { + + /** + * flash 9-only options, + * merged into defaultOptions if flash 9 is being used + */ + 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL 'usePeakData': false, // enable left/right channel peak (level) data - 'useWaveformData': false, // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire. - 'useEQData': false, // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive. + 'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load. + 'useEQData': false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load. 'onbufferchange': null, // callback for "isBuffering" property change 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains) + }; - this.movieStarOptions = { // flash 9.0r115+ MPEG4 audio options, merged into defaultOptions if flash 9+movieStar mode is enabled - 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.) - 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants - 'onconnect': null, // rtmp: callback for connection to flash media server - 'duration': null // rtmp: song duration (msec) + this.movieStarOptions = { + + /** + * flash 9.0r115+ MPEG4 audio options, + * merged into defaultOptions if flash 9+movieStar mode is enabled + */ + + 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.) + 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants + 'onconnect': null, // rtmp: callback for connection to flash media server + 'duration': null // rtmp: song duration (msec) + }; - this.version = null; - this.versionNumber = 'V2.97a.20110424'; - this.movieURL = null; - this.url = (smURL || null); - this.altURL = null; - this.swfLoaded = false; - this.enabled = false; - this.o = null; + // HTML attributes (id + class names) for the SWF container + this.movieID = 'sm2-container'; this.id = (smID || 'sm2movie'); + this.swfCSS = { + 'swfBox': 'sm2-object-box', 'swfDefault': 'movieContainer', 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error) @@ -129,37 +174,53 @@ function SoundManager(smURL, smID) { 'sm2Debug': 'sm2_debug', 'highPerf': 'high_performance', 'flashDebug': 'flash_debug' + }; + + this.debugID = 'soundmanager-debug'; + this.debugURLParam = /([#?&])debug=1/i; + + // dynamic attributes + + this.versionNumber = 'V2.97a.20111030'; + this.version = null; + this.movieURL = null; + this.url = (smURL || null); + this.altURL = null; + this.swfLoaded = false; + this.enabled = false; + this.o = null; this.oMC = null; this.sounds = {}; this.soundIDs = []; this.muted = false; - this.debugID = 'soundmanager-debug'; - this.debugURLParam = /([#?&])debug=1/i; this.specialWmodeCase = false; this.didFlashBlock = false; - this.filePattern = null; + this.filePatterns = { + 'flash8': /\.mp3(\?.*)?$/i, 'flash9': /\.mp3(\?.*)?$/i + }; - this.baseMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3 - this.netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // mp3, mp4, aac etc. - this.netStreamTypes = ['aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2']; // Flash v9.0r115+ "moviestar" formats - this.netStreamPattern = new RegExp('\\.(' + this.netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - this.mimePattern = this.baseMimeTypes; + // support indicators, set at init this.features = { + 'buffering': false, 'peakData': false, 'waveformData': false, 'eqData': false, 'movieStar': false + }; + // flash sandbox info, used primarily in troubleshooting + this.sandbox = { + // 'type': null, 'types': { @@ -172,77 +233,114 @@ function SoundManager(smURL, smID) { 'noRemote': null, 'noLocal': null // + }; - this.hasHTML5 = null; // switch for handling logic - this.html5 = { // stores canPlayType() results, etc. treat as read-only. - // mp3: boolean - // mp4: boolean + /** + * basic HTML5 Audio() support test + * try...catch because of IE 9 "not implemented" nonsense + * https://github.com/Modernizr/Modernizr/issues/224 + */ + + this.hasHTML5 = (function() { + try { + return (typeof Audio !== 'undefined' && typeof new Audio().canPlayType !== 'undefined'); + } catch(e) { + return false; + } + }()); + + /** + * format support (html5/flash) + * stores canPlayType() results based on audioFormats. + * eg. { mp3: boolean, mp4: boolean } + * treat as read-only. + */ + + this.html5 = { 'usingFlash': null // set if/when flash fallback is needed }; + + this.flash = {}; + + this.html5Only = false; // determined at init time this.ignoreFlash = false; // used for special cases (eg. iPad/iPhone/palm OS?) - // --- private SM2 internals --- + /** + * a few private internals (OK, a lot. :D) + */ var SMSound, - _s = this, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _fV = this.flashVersion, _doc = document, _doNothing, _init, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _addOnEvent, _processOnEvents, _initUserOnload, _go, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _beginInit, _strings, _initMovie, _dcLoaded, _didDCLoaded, _getDocument, _createMovie, _die, _setPolling, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _smTimer, _onTimer, _startTimer, _stopTimer, _needsFlash = null, _featureCheck, _html5OK, _html5Only = false, _html5CanPlay, _html5Ext, _dcIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, - _is_pre = _ua.match(/pre\//i), _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isMobile = (_ua.match(/mobile/i) || _is_pre || _is_iDevice), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), - _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && _ua.match(/OS X 10_6_([3-9])/i)), // Safari 4 and 5 occasionally fail to load/play HTML5 audio on Snow Leopard due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Known Apple "radar" bug. https://bugs.webkit.org/show_bug.cgi?id=32159 - _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (typeof _doc.hasFocus === 'undefined' && _isSafari), _okToDisable = !_tryInitOnFocus; - - this._use_maybe = (_wl.match(/sm2\-useHTML5Maybe\=1/i)); // temporary feature: #sm2-useHTML5Maybe=1 forces loose canPlay() check - this._overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null); - this._http = (!this._overHTTP ? 'http:' : ''); - this.useAltURL = !this._overHTTP; // use altURL if not "online" + _s = this, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _smTimer, _onTimer, _startTimer, _stopTimer, _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, + _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _is_firefox = _ua.match(/firefox/i), _is_android = _ua.match(/droid/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), + _likesHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), + _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && _ua.match(/OS X 10_6_([3-7])/i)), // Safari 4 and 5 occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159 + _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && typeof _doc.hasFocus === 'undefined'), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa)/i, + _emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs) + _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), + _http = (!_overHTTP ? 'http:/'+'/' : ''), + // mp3, mp4, aac etc. + _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|mp4v|3gp|3g2)\s*(?:$|;)/i, + // Flash v9.0r115+ "moviestar" formats + _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2'], + _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // default mp3 set + + // use altURL if not "online" + this.useAltURL = !_overHTTP; this._global_a = null; - if (_is_iDevice || _is_pre) { - // during HTML5 beta period (off by default), may as well force it on Apple + Palm, flash support unlikely + if (_likesHTML5) { + + // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point. _s.useHTML5Audio = true; - _s.ignoreFlash = true; - if (_s.useGlobalHTML5Audio) { + _s.preferFlash = false; + + if (_is_iDevice) { + // by default, use global feature. iOS onfinish() -> next may fail otherwise. + _s.ignoreFlash = true; _useGlobalHTML5Audio = true; } - } - if (_is_pre || this._use_maybe) { - // less-strict canPlayType() checking option - _s.html5Test = /^(probably|maybe)$/i; } - // Temporary feature: allow force of HTML5 via URL: #sm2-usehtml5audio=0 or 1 - // - (function(){ - var a = '#sm2-usehtml5audio=', l = _wl, b = null; - if (l.indexOf(a) !== -1) { - b = (l.charAt(l.indexOf(a)+a.length) === '1'); - if (typeof console !== 'undefined' && typeof console.log !== 'undefined') { - console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter'); - } - _s.useHTML5Audio = b; - } - }()); - // - - // --- public API methods --- + /** + * Public SoundManager API + * ----------------------- + */ this.ok = function() { + return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); + }; this.supported = this.ok; // legacy this.getMovie = function(smID) { - return _isIE?_win[smID]:(_isSafari?_id(smID) || _doc[smID]:_id(smID)); + + // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version + return _id(smID) || _doc[smID] || _win[smID]; + }; + /** + * Creates a SMSound sound object instance. + * + * @param {object} oOptions Sound options (at minimum, id and url are required.) + * @return {object} SMSound The new SMSound object. + */ + this.createSound = function(oOptions) { + var _cs = _sm+'.createSound(): ', thisOptions = null, oSound = null, _tO = null; + if (!_didInit || !_s.ok()) { _complain(_cs + _str(!_didInit?'notReady':'notOK')); return false; } + if (arguments.length === 2) { // function overloading in JS! :) ..assume simple createSound(id,url) use case oOptions = { @@ -250,54 +348,73 @@ function SoundManager(smURL, smID) { 'url': arguments[1] }; } - thisOptions = _mixin(oOptions); // inherit from defaultOptions - _tO = thisOptions; // alias + + // inherit from defaultOptions + thisOptions = _mixin(oOptions); + + // alias + _tO = thisOptions; + // if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) { _s._wD(_cs + _str('badID', _tO.id), 2); } + _s._wD(_cs + _tO.id + ' (' + _tO.url + ')', 1); // + if (_idCheck(_tO.id, true)) { _s._wD(_cs + _tO.id + ' exists', 1); return _s.sounds[_tO.id]; } function make() { + thisOptions = _loopFix(thisOptions); _s.sounds[_tO.id] = new SMSound(_tO); _s.soundIDs.push(_tO.id); return _s.sounds[_tO.id]; + } if (_html5OK(_tO)) { + oSound = make(); _s._wD('Loading sound '+_tO.id+' via HTML5'); oSound._setup_html5(_tO); + } else { - if (_fV > 8 && _s.useMovieStar) { + + if (_fV > 8) { if (_tO.isMovieStar === null) { - _tO.isMovieStar = ((_tO.serverURL || (_tO.type?_tO.type.match(_s.netStreamPattern):false)||_tO.url.match(_s.netStreamPattern))?true:false); + // attempt to detect MPEG-4 formats + _tO.isMovieStar = (_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); } + // if (_tO.isMovieStar) { _s._wD(_cs + 'using MovieStar handling'); } + // if (_tO.isMovieStar) { if (_tO.usePeakData) { _wDS('noPeak'); _tO.usePeakData = false; } + // if (_tO.loops > 1) { _wDS('noNSLoop'); } + // } } + _tO = _policyFix(_tO, _cs); oSound = make(); + if (_fV === 8) { - _s.o._createSound(_tO.id, _tO.onjustbeforefinishtime, _tO.loops||1, _tO.usePolicyFile); + _s.o._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); } else { - _s.o._createSound(_tO.id, _tO.url, _tO.onjustbeforefinishtime, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); + _s.o._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); if (!_tO.serverURL) { // We are connected immediately oSound.connected = true; @@ -307,61 +424,131 @@ function SoundManager(smURL, smID) { } } - if ((_tO.autoLoad || _tO.autoPlay) && !_tO.serverURL) { - oSound.load(_tO); // call load for non-rtmp streams + if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { + // call load for non-rtmp streams + oSound.load(_tO); } + } - if (_tO.autoPlay && !_tO.serverURL) { // rtmp will play in onconnect + // rtmp will play in onconnect + if (!_tO.serverURL && _tO.autoPlay) { oSound.play(); } + return oSound; + }; + /** + * Destroys a SMSound sound object instance. + * + * @param {string} sID The ID of the sound to destroy + */ + this.destroySound = function(sID, _bFromSound) { + // explicitly destroy a sound before normal page unload, etc. + if (!_idCheck(sID)) { return false; } + var oS = _s.sounds[sID], i; - oS._iO = {}; // Disable all callbacks while the sound is being destroyed + + // Disable all callbacks while the sound is being destroyed + oS._iO = {}; + oS.stop(); oS.unload(); + for (i = 0; i < _s.soundIDs.length; i++) { if (_s.soundIDs[i] === sID) { _s.soundIDs.splice(i, 1); break; } } + if (!_bFromSound) { // ignore if being called from SMSound instance oS.destruct(true); } + oS = null; delete _s.sounds[sID]; + return true; + }; + /** + * Calls the load() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {object} oOptions Optional: Sound options + */ + this.load = function(sID, oOptions) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].load(oOptions); + }; + /** + * Calls the unload() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + */ + this.unload = function(sID) { + if (!_idCheck(sID)) { return false; } + return _s.sounds[sID].unload(); + + }; + + /** + * Calls the onposition() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nPosition The position to watch for + * @param {function} oMethod The relevant callback to fire + * @param {object} oScope Optional: The scope to apply the callback to + * @return {SMSound} The SMSound object + */ + + this.onposition = function(sID, nPosition, oMethod, oScope) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].onposition(nPosition, oMethod, oScope); + }; + /** + * Calls the play() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ + this.play = function(sID, oOptions) { + var fN = _sm+'.play(): '; + if (!_didInit || !_s.ok()) { _complain(fN + _str(!_didInit?'notReady':'notOK')); return false; } + if (!_idCheck(sID)) { if (!(oOptions instanceof Object)) { oOptions = { @@ -377,88 +564,189 @@ function SoundManager(smURL, smID) { return false; } } + return _s.sounds[sID].play(oOptions); + }; this.start = this.play; // just for convenience + /** + * Calls the setPosition() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nMsecOffset Position (milliseconds) + * @return {SMSound} The SMSound object + */ + this.setPosition = function(sID, nMsecOffset) { + if (!_idCheck(sID)) { return false; + } return _s.sounds[sID].setPosition(nMsecOffset); + }; + /** + * Calls the stop() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + this.stop = function(sID) { + if (!_idCheck(sID)) { return false; } _s._wD(_sm+'.stop(' + sID + ')', 1); return _s.sounds[sID].stop(); + }; + /** + * Stops all currently-playing sounds. + */ + this.stopAll = function() { + + var oSound; _s._wD(_sm+'.stopAll()', 1); - for (var oSound in _s.sounds) { - if (_s.sounds[oSound] instanceof SMSound) { - _s.sounds[oSound].stop(); // apply only to sound objects + + for (oSound in _s.sounds) { + if (_s.sounds.hasOwnProperty(oSound)) { + // apply only to sound objects + _s.sounds[oSound].stop(); } } + }; + /** + * Calls the pause() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + this.pause = function(sID) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].pause(); + }; + /** + * Pauses all currently-playing sounds. + */ + this.pauseAll = function() { - for (var i = _s.soundIDs.length; i--;) { + + var i; + for (i = _s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].pause(); } + }; + /** + * Calls the resume() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + this.resume = function(sID) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].resume(); + }; + /** + * Resumes all currently-paused sounds. + */ + this.resumeAll = function() { - for (var i = _s.soundIDs.length; i--;) { + + var i; + for (i = _s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].resume(); } + }; + /** + * Calls the togglePause() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + this.togglePause = function(sID) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].togglePause(); + }; + /** + * Calls the setPan() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nPan The pan value (-100 to 100) + * @return {SMSound} The SMSound object + */ + this.setPan = function(sID, nPan) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].setPan(nPan); + }; + /** + * Calls the setVolume() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nVol The volume value (0 to 100) + * @return {SMSound} The SMSound object + */ + this.setVolume = function(sID, nVol) { + if (!_idCheck(sID)) { return false; } return _s.sounds[sID].setVolume(nVol); + }; + /** + * Calls the mute() method of either a single SMSound object by ID, or all sound objects. + * + * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) + */ + this.mute = function(sID) { + var fN = _sm+'.mute(): ', i = 0; + if (typeof sID !== 'string') { sID = null; } + if (!sID) { _s._wD(fN + 'Muting all sounds'); for (i = _s.soundIDs.length; i--;) { @@ -472,166 +760,321 @@ function SoundManager(smURL, smID) { _s._wD(fN + 'Muting "' + sID + '"'); return _s.sounds[sID].mute(); } + return true; + }; + /** + * Mutes all sounds. + */ + this.muteAll = function() { + _s.mute(); + }; + /** + * Calls the unmute() method of either a single SMSound object by ID, or all sound objects. + * + * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) + */ + this.unmute = function(sID) { + var fN = _sm+'.unmute(): ', i; + if (typeof sID !== 'string') { sID = null; } + if (!sID) { + _s._wD(fN + 'Unmuting all sounds'); for (i = _s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].unmute(); } _s.muted = false; + } else { + if (!_idCheck(sID)) { return false; } _s._wD(fN + 'Unmuting "' + sID + '"'); return _s.sounds[sID].unmute(); + } + return true; + }; + /** + * Unmutes all sounds. + */ + this.unmuteAll = function() { + _s.unmute(); + }; + /** + * Calls the toggleMute() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + this.toggleMute = function(sID) { + if (!_idCheck(sID)) { return false; } + return _s.sounds[sID].toggleMute(); + }; + /** + * Retrieves the memory used by the flash plugin. + * + * @return {number} The amount of memory in use + */ + this.getMemoryUse = function() { - if (_fV === 8) { - return 0; - } - if (_s.o) { - return parseInt(_s.o._getMemoryUse(), 10); + + // flash-only + var ram = 0; + + if (_s.o && _fV !== 8) { + ram = parseInt(_s.o._getMemoryUse(), 10); } + + return ram; + }; + /** + * Undocumented: NOPs soundManager and all SMSound objects. + */ + this.disable = function(bNoDisable) { + // destroy all functions + var i; + if (typeof bNoDisable === 'undefined') { bNoDisable = false; } + if (_disabled) { return false; } + _disabled = true; _wDS('shutdown', 1); - for (var i = _s.soundIDs.length; i--;) { + + for (i = _s.soundIDs.length; i--;) { _disableObject(_s.sounds[_s.soundIDs[i]]); } - _initComplete(bNoDisable); // fire "complete", despite fail + + // fire "complete", despite fail + _initComplete(bNoDisable); _event.remove(_win, 'load', _initUserOnload); + return true; + }; + /** + * Determines playability of a MIME type, eg. 'audio/mp3'. + */ + this.canPlayMIME = function(sMIME) { + var result; + if (_s.hasHTML5) { result = _html5CanPlay({type:sMIME}); } + if (!_needsFlash || result) { // no flash, or OK return result; } else { - return (sMIME?(sMIME.match(_s.mimePattern)?true:false):null); + // if flash 9, test netStream (movieStar) types as well. + return (sMIME ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); } + }; + /** + * Determines playability of a URL based on audio support. + * + * @param {string} sURL The URL to test + * @return {boolean} URL playability + */ + this.canPlayURL = function(sURL) { + var result; + if (_s.hasHTML5) { - result = _html5CanPlay(sURL); + result = _html5CanPlay({url: sURL}); } + if (!_needsFlash || result) { // no flash, or OK return result; } else { - return (sURL?(sURL.match(_s.filePattern)?true:false):null); + return (sURL ? !!(sURL.match(_s.filePattern)) : null); } + }; + /** + * Determines playability of an HTML DOM <a> object (or similar object literal) based on audio support. + * + * @param {object} oLink an HTML DOM <a> object or object literal including href and/or type attributes + * @return {boolean} URL playability + */ + this.canPlayLink = function(oLink) { + if (typeof oLink.type !== 'undefined' && oLink.type) { if (_s.canPlayMIME(oLink.type)) { return true; } } + return _s.canPlayURL(oLink.href); + }; - this.getSoundById = function(sID, suppressDebug) { + /** + * Retrieves a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.getSoundById = function(sID, _suppressDebug) { + if (!sID) { throw new Error(_sm+'.getSoundById(): sID is null/undefined'); } + var result = _s.sounds[sID]; - if (!result && !suppressDebug) { + + // + if (!result && !_suppressDebug) { _s._wD('"' + sID + '" is an invalid sound ID.', 2); } + // + return result; + }; + /** + * Queues a callback for execution when SoundManager has successfully initialized. + * + * @param {function} oMethod The callback method to fire + * @param {object} oScope Optional: The scope to apply to the callback + */ + this.onready = function(oMethod, oScope) { + var sType = 'onready'; + if (oMethod && oMethod instanceof Function) { + + // if (_didInit) { - _wDS('queue', sType); + _s._wD(_str('queue', sType)); } + // + if (!oScope) { oScope = _win; } + _addOnEvent(sType, oMethod, oScope); _processOnEvents(); + return true; + } else { + throw _str('needFunction', sType); + } + }; + /** + * Queues a callback for execution when SoundManager has failed to initialize. + * + * @param {function} oMethod The callback method to fire + * @param {object} oScope Optional: The scope to apply to the callback + */ + this.ontimeout = function(oMethod, oScope) { + var sType = 'ontimeout'; + if (oMethod && oMethod instanceof Function) { + + // if (_didInit) { - _wDS('queue'); + _s._wD(_str('queue', sType)); } - if (!oScope) { + // + + if (!oScope) { oScope = _win; } + _addOnEvent(sType, oMethod, oScope); _processOnEvents({type:sType}); + return true; + } else { + throw _str('needFunction', sType); + } - }; - this.getMoviePercent = function() { - return (_s.o && typeof _s.o.PercentLoaded !== 'undefined'?_s.o.PercentLoaded():null); }; - this._writeDebug = function(sText, sType, bTimestamp) { + /** + * Writes console.log()-style debug output to a console or in-browser element. + * Applies when SoundManager.debugMode = true + * + * @param {string} sText The console message + * @param {string} sType Optional: Log type of 'info', 'warn' or 'error' + * @param {object} Optional: The scope to apply to the callback + */ + + this._writeDebug = function(sText, sType, _bTimestamp) { + // pseudo-private console.log()-style output // + var sDID = 'soundmanager-debug', o, oItem, sMethod; + if (!_s.debugMode) { return false; } - if (typeof bTimestamp !== 'undefined' && bTimestamp) { + + if (typeof _bTimestamp !== 'undefined' && _bTimestamp) { sText = sText + ' | ' + new Date().getTime(); } + if (_hasConsole && _s.useConsole) { sMethod = _debugLevels[sType]; if (typeof console[sMethod] !== 'undefined') { @@ -643,21 +1086,29 @@ function SoundManager(smURL, smID) { return true; } } + try { + o = _id(sDID); + if (!o) { return false; } + oItem = _doc.createElement('div'); + if (++_wdCount % 2 === 0) { oItem.className = 'sm2-alt'; } + if (typeof sType === 'undefined') { sType = 0; } else { sType = parseInt(sType, 10); } + oItem.appendChild(_doc.createTextNode(sText)); + if (sType) { if (sType >= 2) { oItem.style.fontWeight = 'bold'; @@ -666,37 +1117,67 @@ function SoundManager(smURL, smID) { oItem.style.color = '#ff3333'; } } - // o.appendChild(oItem); // top-to-bottom - o.insertBefore(oItem, o.firstChild); // bottom-to-top + + // top-to-bottom + // o.appendChild(oItem); + + // bottom-to-top + o.insertBefore(oItem, o.firstChild); + } catch(e) { // oh well } + o = null; // + return true; + }; - this._wD = this._writeDebug; // alias + + // alias + this._wD = this._writeDebug; + + /** + * Provides debug / state information on all SMSound objects. + */ this._debug = function() { + // + var i, j; _wDS('currentObj', 1); - for (var i = 0, j = _s.soundIDs.length; i < j; i++) { + + for (i = 0, j = _s.soundIDs.length; i < j; i++) { _s.sounds[_s.soundIDs[i]]._debug(); } // + }; + /** + * Restarts and re-initializes the SoundManager instance. + */ + this.reboot = function() { + // attempt to reset and init SM2 _s._wD(_sm+'.reboot()'); + + // if (_s.soundIDs.length) { _s._wD('Destroying ' + _s.soundIDs.length + ' SMSound objects...'); } + // + var i, j; + for (i = _s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].destruct(); } + // trash ze flash + try { if (_isIE) { _oRemovedHTML = _s.o.innerHTML; @@ -707,11 +1188,14 @@ function SoundManager(smURL, smID) { // uh-oh. _wDS('badRemove', 2); } + // actually, force recreate of movie. - _oRemovedHTML = _oRemoved = null; - _s.enabled = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; + _oRemovedHTML = _oRemoved = _needsFlash = null; + + _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; _s.soundIDs = _s.sounds = []; _s.o = null; + for (i in _on_queue) { if (_on_queue.hasOwnProperty(i)) { for (j = _on_queue[i].length; j--;) { @@ -719,206 +1203,83 @@ function SoundManager(smURL, smID) { } } } - _s._wD(_sm + ': Rebooting...'); - _win.setTimeout(function() { - _s.beginDelayedInit(); - }, 20); - }; - this.destruct = function() { - _s._wD(_sm+'.destruct()'); - _s.disable(true); - }; + _s._wD(_sm + ': Rebooting...'); + _win.setTimeout(_s.beginDelayedInit, 20); - this.beginDelayedInit = function() { - // _s._wD(_sm+'.beginDelayedInit()'); - _windowLoaded = true; - _dcLoaded(); - setTimeout(_beginInit, 20); - _delayWaitForEI(); }; + /** + * Undocumented: Determines the SM2 flash movie's load progress. + * + * @return {number or null} Percent loaded, or if invalid/unsupported, null. + */ - // Wrap html5 event handlers so we don't call them on destroyed sounds - function _html5_event(oFn) { - return function(e) { - if (!this._t || !this._t._a) { - if (this._t && this._t.sID) { - _s._wD(_h5+'ignoring '+e.type+': '+this._t.sID); - } else { - _s._wD(_h5+'ignoring '+e.type); - } - return null; - } else { - return oFn.call(this, e); - } - }; - } - - this._html5_events = { - - // HTML5 event-name-to-handler map - abort: _html5_event(function(e) { - _s._wD(_h5+'abort: '+this._t.sID); - }), - - // enough has loaded to play - canplay: _html5_event(function(e) { - _s._wD(_h5+'canplay: '+this._t.sID+', '+this._t.url); - this._t._onbufferchange(0); - var position1K = (!isNaN(this._t.position)?this._t.position/1000:null); - // set the position if position was set before the sound loaded - this._t._html5_canplay = true; - if (this._t.position && this.currentTime !== position1K) { - _s._wD(_h5+'canplay: setting position to '+position1K+''); - try { - this.currentTime = position1K; - } catch(ee) { - _s._wD(_h5+'setting position failed: '+ee.message, 2); - } - } - }), - - load: _html5_event(function(e) { - if (!this._t.loaded) { - this._t._onbufferchange(0); - // should be 1, and the same - this._t._whileloading(this._t.bytesTotal, this._t.bytesTotal, this._t._get_html5_duration()); - this._t._onload(true); - } - }), - - emptied: _html5_event(function(e) { - _s._wD(_h5+'emptied: '+this._t.sID); - }), - - ended: _html5_event(function(e) { - _s._wD(_h5+'ended: '+this._t.sID); - this._t._onfinish(); - }), - - error: _html5_event(function(e) { - _s._wD(_h5+'error: '+this.error.code); - // call load with error state? - this._t._onload(false); - }), + this.getMoviePercent = function() { - loadeddata: _html5_event(function(e) { - _s._wD(_h5+'loadeddata: '+this._t.sID); - }), + return (_s.o && typeof _s.o.PercentLoaded !== 'undefined' ? _s.o.PercentLoaded() : null); - loadedmetadata: _html5_event(function(e) { - _s._wD(_h5+'loadedmetadata: '+this._t.sID); - }), + }; - loadstart: _html5_event(function(e) { - _s._wD(_h5+'loadstart: '+this._t.sID); - // assume buffering at first - this._t._onbufferchange(1); - }), + /** + * Additional helper for manually invoking SM2's init process after DOM Ready / window.onload(). + */ - play: _html5_event(function(e) { - _s._wD(_h5+'play: '+this._t.sID+', '+this._t.url); - // once play starts, no buffering - this._t._onbufferchange(0); - }), + this.beginDelayedInit = function() { - // TODO: verify if this is actually implemented anywhere yet. - playing: _html5_event(function(e) { - _s._wD(_h5+'playing: '+this._t.sID+', '+this._t.url); - // once play starts, no buffering - this._t._onbufferchange(0); - }), + _windowLoaded = true; + _domContentLoaded(); - progress: _html5_event(function(e) { + setTimeout(function() { - if (this._t.loaded) { + if (_initPending) { return false; } - var i, j, str, loadSum = 0, buffered = 0, - isProgress = (e.type === 'progress'), - ranges = e.target.buffered, - loaded = (e.loaded||0), // firefox 3.6 implements e.loaded/total (bytes) - total = (e.total||1); - - if (ranges && ranges.length) { - - // if loaded is 0, try TimeRanges implementation as % of load - // https://developer.mozilla.org/en/DOM/TimeRanges - for (i=ranges.length; i--;) { - buffered = (ranges.end(i) - ranges.start(i)); - } - - // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges - loaded = buffered/e.target.duration; - - // - if (isProgress && ranges.length > 1) { - str = []; - j = ranges.length; - for (i=0; i - - if (isProgress && !isNaN(loaded)) { - _s._wD(_h5+'progress: '+this._t.sID+': ' + Math.floor(loaded*100)+'% loaded'); - } - - } - - if (!isNaN(loaded)) { - - this._t._onbufferchange(0); // if progress, likely not buffering - this._t._whileloading(loaded, total, this._t._get_html5_duration()); - - if (loaded && total && loaded === total) { - // in case "onload" doesn't fire (eg. gecko 1.9.2) - _s._html5_events.load.call(this, e); - } + _createMovie(); + _initMovie(); + _initPending = true; - } + return true; - }), + }, 20); - ratechange: _html5_event(function(e) { - _s._wD(_h5+'ratechange: '+this._t.sID); - }), + _delayWaitForEI(); - suspend: _html5_event(function(e) { - // download paused/stopped, may have finished (eg. onload) - _s._wD(_h5+'suspend: '+this._t.sID); - _s._html5_events.progress.call(this, e); - }), + }; - stalled: _html5_event(function(e) { - _s._wD(_h5+'stalled: '+this._t.sID); - }), + /** + * Destroys the SoundManager instance and all SMSound instances. + */ - timeupdate: _html5_event(function(e) { - this._t._onTimer(); - }), + this.destruct = function() { - waiting: _html5_event(function(e) { // see also: seeking - _s._wD(_h5+'waiting: '+this._t.sID); - // playback faster than download rate, etc. - this._t._onbufferchange(1); - }) + _s._wD(_sm+'.destruct()'); + _s.disable(true); }; - // --- SMSound (sound object) instance --- + /** + * SMSound() (sound object) constructor + * ------------------------------------ + * + * @param {object} oOptions Sound options (id and url are required attributes) + * @return {SMSound} The new SMSound object + */ SMSound = function(oOptions) { + var _t = this, _resetProperties, _stop_html5_timer, _start_html5_timer; this.sID = oOptions.id; this.url = oOptions.url; this.options = _mixin(oOptions); - this.instanceOptions = this.options; // per-play-instance-specific options - this._iO = this.instanceOptions; // short alias + + // per-play-instance-specific options + this.instanceOptions = this.options; + + // short alias + this._iO = this.instanceOptions; + // assign property defaults this.pan = this.options.pan; this.volume = this.options.volume; @@ -926,21 +1287,33 @@ function SoundManager(smURL, smID) { this.isHTML5 = false; this._a = null; - // --- public methods --- + /** + * SMSound() public methods + * ------------------------ + */ this.id3 = {}; + /** + * Writes SMSound object parameters to debug console + */ + this._debug = function() { + // // pseudo-private console.log()-style output + if (_s.debugMode) { + var stuff = null, msg = [], sF, sfBracket, maxLength = 64; + for (stuff in _t.options) { if (_t.options[stuff] !== null) { if (_t.options[stuff] instanceof Function) { // handle functions specially sF = _t.options[stuff].toString(); - sF = sF.replace(/\s\s+/g, ' '); // normalize spaces + // normalize spaces + sF = sF.replace(/\s\s+/g, ' '); sfBracket = sF.indexOf('{'); msg.push(' ' + stuff + ': {' + sF.substr(sfBracket + 1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '') + '... }'); } else { @@ -948,15 +1321,29 @@ function SoundManager(smURL, smID) { } } } + _s._wD('SMSound() merged options: {\n' + msg.join(', \n') + '\n}'); + } // + }; + // this._debug(); + // + + /** + * Begins loading a sound per its *url*. + * + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ this.load = function(oOptions) { + var oS = null; + if (typeof oOptions !== 'undefined') { _t._iO = _mixin(oOptions, _t.options); _t.instanceOptions = _t._iO; @@ -970,120 +1357,178 @@ function SoundManager(smURL, smID) { _t.url = null; } } + if (!_t._iO.url) { _t._iO.url = _t.url; } + _s._wD('SMSound.load(): ' + _t._iO.url, 1); + if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { _wDS('onURL', 1); return _t; } + _t._lastURL = _t.url; _t.loaded = false; _t.readyState = 1; _t.playState = 0; + + // TODO: If switching from HTML5 -> flash (or vice versa), stop currently-playing audio. + if (_html5OK(_t._iO)) { + oS = _t._setup_html5(_t._iO); if (!oS._called_load) { _s._wD(_h5+'load: '+_t.sID); + _t._html5_canplay = false; oS.load(); oS._called_load = true; if (_t._iO.autoPlay) { _t.play(); } } else { - _s._wD('HTML5 ignoring request to load again: '+_t.sID); + _s._wD(_h5+'ignoring request to load again: '+_t.sID); } + } else { + try { _t.isHTML5 = false; _t._iO = _policyFix(_loopFix(_t._iO)); if (_fV === 8) { _s.o._load(_t.sID, _t._iO.url, _t._iO.stream, _t._iO.autoPlay, (_t._iO.whileloading?1:0), _t._iO.loops||1, _t._iO.usePolicyFile); } else { - _s.o._load(_t.sID, _t._iO.url, _t._iO.stream?true:false, _t._iO.autoPlay?true:false, _t._iO.loops||1, _t._iO.autoLoad?true:false, _t._iO.usePolicyFile); + _s.o._load(_t.sID, _t._iO.url, !!(_t._iO.stream), !!(_t._iO.autoPlay), _t._iO.loops||1, !!(_t._iO.autoLoad), _t._iO.usePolicyFile); } } catch(e) { _wDS('smError', 2); _debugTS('onload', false); - _die(); + _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); + } + } + return _t; + }; + /** + * Unloads a sound, canceling any open HTTP requests. + * + * @return {SMSound} The SMSound object + */ + this.unload = function() { - // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3 + + // Flash 8/AS2 can't "close" a stream - fake it by loading an empty URL // Flash 9/AS3: Close stream, preventing further load + // HTML5: Most UAs will use empty URL + if (_t.readyState !== 0) { + _s._wD('SMSound.unload(): "' + _t.sID + '"'); + if (!_t.isHTML5) { if (_fV === 8) { - _s.o._unload(_t.sID, _s.nullURL); + _s.o._unload(_t.sID, _emptyURL); } else { _s.o._unload(_t.sID); } } else { _stop_html5_timer(); if (_t._a) { - // abort()-style method here, stop loading? (doesn't exist?) _t._a.pause(); -// if (!_useGlobalHTML5Audio || (_useGlobalHTML5Audio && _t.playState)) { // if global audio, only unload if actively playing - _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media -// } + _html5Unload(_t._a); } } + // reset load/status flags _resetProperties(); + } + return _t; + }; + /** + * Unloads and destroys a sound. + */ + this.destruct = function(_bFromSM) { + _s._wD('SMSound.destruct(): "' + _t.sID + '"'); + if (!_t.isHTML5) { + // kill sound within Flash // Disable the onfailure handler _t._iO.onfailure = null; _s.o._destroySound(_t.sID); + } else { + _stop_html5_timer(); + if (_t._a) { - // abort()-style method here, stop loading? (doesn't exist?) _t._a.pause(); - _t._a.src = ''; // https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media + _html5Unload(_t._a); if (!_useGlobalHTML5Audio) { _t._remove_html5_events(); } + // break obvious circular reference + _t._a._t = null; + _t._a = null; } + } + if (!_bFromSM) { - _s.destroySound(_t.sID, true); // ensure deletion from controller + // ensure deletion from controller + _s.destroySound(_t.sID, true); + } + }; + /** + * Begins playing a sound. + * + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ + this.play = function(oOptions, _updatePlayState) { - var fN = 'SMSound.play(): ', allowMulti; - _updatePlayState = _updatePlayState === undefined ? true : _updatePlayState; // default true + + var fN = 'SMSound.play(): ', allowMulti, a; + + _updatePlayState = _updatePlayState === undefined ? true : _updatePlayState; // default to true + if (!oOptions) { oOptions = {}; } + _t._iO = _mixin(oOptions, _t._iO); _t._iO = _mixin(_t._iO, _t.options); _t.instanceOptions = _t._iO; - if (_t._iO.serverURL) { - if (!_t.connected) { - if (!_t.getAutoPlay()) { - _s._wD(fN+' Netstream not connected yet - setting autoPlay'); - _t.setAutoPlay(true); - } - return _t; // play will be called in _onconnect() + + // RTMP-only + if (_t._iO.serverURL && !_t.connected) { + if (!_t.getAutoPlay()) { + _s._wD(fN+' Netstream not connected yet - setting autoPlay'); + _t.setAutoPlay(true); } + // play will be called in _onconnect() + return _t; } + if (_html5OK(_t._iO)) { _t._setup_html5(_t._iO); _start_html5_timer(); } + if (_t.playState === 1 && !_t.paused) { allowMulti = _t._iO.multiShot; if (!allowMulti) { @@ -1091,152 +1536,247 @@ function SoundManager(smURL, smID) { return _t; } else { _s._wD(fN + '"' + _t.sID + '" already playing (multi-shot)', 1); - if (_t.isHTML5) { - // TODO: BUG? - _t.setPosition(_t._iO.position); - } } } + if (!_t.loaded) { + if (_t.readyState === 0) { + _s._wD(fN + 'Attempting to load "' + _t.sID + '"', 1); // try to get this sound playing ASAP if (!_t.isHTML5) { - _t._iO.autoPlay = true; // assign directly because setAutoPlay() increments the instanceCount - _t.load(_t._iO); - } else { - _t.load(_t._iO); - // _t.readyState = 1; // redundant + // assign directly because setAutoPlay() increments the instanceCount + _t._iO.autoPlay = true; } + _t.load(_t._iO); + } else if (_t.readyState === 2) { + _s._wD(fN + 'Could not load "' + _t.sID + '" - exiting', 2); return _t; + } else { + _s._wD(fN + '"' + _t.sID + '" is loading - attempting to play..', 1); + } + } else { + _s._wD(fN + '"' + _t.sID + '"'); + } - // Streams will pause when their buffer is full if they are being loaded. - // In this case paused is true, but the song hasn't started playing yet. If - // we just call resume() the onplay() callback will never be called. So - // only call resume() if the position is > 0. - // Another reason is because options like volume won't have been applied yet. - if (_t.paused && _t.position && _t.position > 0) { // https://gist.github.com/37b17df75cc4d7a90bf6 + + if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { + // flash 9 needs a position reset if play() is called while at the end of a sound. + _s._wD(fN + '"' + _t.sID + '": Sound at end, resetting to position:0'); + _t._iO.position = 0; + } + + /** + * Streams will pause when their buffer is full if they are being loaded. + * In this case paused is true, but the song hasn't started playing yet. + * If we just call resume() the onplay() callback will never be called. + * So only call resume() if the position is > 0. + * Another reason is because options like volume won't have been applied yet. + */ + + if (_t.paused && _t.position && _t.position > 0) { + + // https://gist.github.com/37b17df75cc4d7a90bf6 _s._wD(fN + '"' + _t.sID + '" is resuming from paused state',1); _t.resume(); + } else { + _s._wD(fN+'"'+ _t.sID+'" is starting to play'); _t.playState = 1; _t.paused = false; - if (!_t.instanceCount || _t._iO.multiShotEvents || (_fV > 8 && !_t.isHTML5 && !_t.getAutoPlay())) { + + if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { _t.instanceCount++; } + _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0); + if (!_t.isHTML5) { _t._iO = _policyFix(_loopFix(_t._iO)); } + if (_t._iO.onplay && _updatePlayState) { _t._iO.onplay.apply(_t); _t._onplay_called = true; } + _t.setVolume(_t._iO.volume, true); _t.setPan(_t._iO.pan, true); + if (!_t.isHTML5) { - _s.o._start(_t.sID, _t._iO.loops || 1, (_fV === 9?_t.position:_t.position / 1000)); + _s.o._start(_t.sID, _t._iO.loops || 1, (_fV === 9?_t._iO.position:_t._iO.position / 1000)); } else { _start_html5_timer(); - _t._setup_html5().play(); + a = _t._setup_html5(); + _t.setPosition(_t._iO.position); + a.play(); } + } + return _t; + }; - this.start = this.play; // just for convenience + // just for convenience + this.start = this.play; + + /** + * Stops playing a sound (and optionally, all sounds) + * + * @param {boolean} bAll Optional: Whether to stop all sounds + * @return {SMSound} The SMSound object + */ this.stop = function(bAll) { + if (_t.playState === 1) { + _t._onbufferchange(0); _t.resetOnPosition(0); + _t.paused = false; + if (!_t.isHTML5) { _t.playState = 0; } - _t.paused = false; + if (_t._iO.onstop) { _t._iO.onstop.apply(_t); } + if (!_t.isHTML5) { + _s.o._stop(_t.sID, bAll); // hack for netStream: just unload if (_t._iO.serverURL) { _t.unload(); } + } else { + if (_t._a) { - _t.setPosition(0); // act like Flash, though - _t._a.pause(); // html5 has no stop() + + // act like Flash, though + _t.setPosition(0); + + // html5 has no stop() + _t._a.pause(); + _t.playState = 0; - _t._onTimer(); // and update UI + + // and update UI + _t._onTimer(); + _stop_html5_timer(); - _t.unload(); + } + } + _t.instanceCount = 0; _t._iO = {}; + } + return _t; + }; + /** + * Undocumented/internal: Sets autoPlay for RTMP. + * + * @param {boolean} autoPlay state + */ + this.setAutoPlay = function(autoPlay) { + _s._wD('sound '+_t.sID+' turned autoplay ' + (autoPlay ? 'on' : 'off')); _t._iO.autoPlay = autoPlay; - if (_t.isHTML5) { - if (_t._a && autoPlay) { - _t.play(); // HTML5 onload isn't reliable - } - } else { + + if (!_t.isHTML5) { _s.o._setAutoPlay(_t.sID, autoPlay); - } - if (autoPlay) { - // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP) - if (!_t.instanceCount && _t.readyState === 1) { - _t.instanceCount++; - _s._wD('sound '+_t.sID+' incremented instance count to '+_t.instanceCount); + if (autoPlay) { + // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP) + if (!_t.instanceCount && _t.readyState === 1) { + _t.instanceCount++; + _s._wD('sound '+_t.sID+' incremented instance count to '+_t.instanceCount); + } } } + }; + /** + * Undocumented/internal: Returns the autoPlay boolean. + * + * @return {boolean} The current autoPlay value + */ + this.getAutoPlay = function() { + return _t._iO.autoPlay; + }; - this.setPosition = function(nMsecOffset, bNoDebug) { + /** + * Sets the position of a sound. + * + * @param {number} nMsecOffset Position (milliseconds) + * @return {SMSound} The SMSound object + */ + + this.setPosition = function(nMsecOffset) { + if (nMsecOffset === undefined) { nMsecOffset = 0; } - // Use the duration from the instance options, if we don't have a track duration yet. - var original_pos, position, position1K, offset = (_t.isHTML5 ? Math.max(nMsecOffset,0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); // position >= 0 and <= current available (loaded) duration + + var original_pos, + position, position1K, + // Use the duration from the instance options, if we don't have a track duration yet. + // position >= 0 and <= current available (loaded) duration + offset = (_t.isHTML5 ? Math.max(nMsecOffset,0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); + original_pos = _t.position; _t.position = offset; position1K = _t.position/1000; _t.resetOnPosition(_t.position); _t._iO.position = offset; + if (!_t.isHTML5) { - position = _fV === 9 ? _t.position : position1K; + + position = (_fV === 9 ? _t.position : position1K); if (_t.readyState && _t.readyState !== 2) { - _s.o._setPosition(_t.sID, position, (_t.paused || !_t.playState)); // if paused or not playing, will not resume (by playing) + // if paused or not playing, will not resume (by playing) + _s.o._setPosition(_t.sID, position, (_t.paused || !_t.playState)); } + } else if (_t._a) { + // Set the position in the canplay handler if the sound is not ready yet if (_t._html5_canplay) { if (_t._a.currentTime !== position1K) { - // Only set the position if we need to. - // DOM/JS errors/exceptions to watch out for: - // if seek is beyond (loaded?) position, "DOM exception 11" - // "INDEX_SIZE_ERR": DOM exception 1 + /* + * DOM/JS errors/exceptions to watch out for: + * if seek is beyond (loaded?) position, "DOM exception 11" + * "INDEX_SIZE_ERR": DOM exception 1 + */ _s._wD('setPosition('+position1K+'): setting position'); try { _t._a.currentTime = position1K; + if (_t.playState === 0 || _t.paused) { + // allow seek without auto-play/resume + _t._a.pause(); + } } catch(e) { _s._wD('setPosition('+position1K+'): setting position failed: '+e.message, 2); } @@ -1244,179 +1784,304 @@ function SoundManager(smURL, smID) { } else { _s._wD('setPosition('+position1K+'): delaying, sound not ready'); } + } + if (_t.isHTML5) { - if (_t.paused) { // if paused, refresh UI right away - _t._onTimer(true); // force update + if (_t.paused) { + // if paused, refresh UI right away + // force update + _t._onTimer(true); } } + return _t; + }; - this.pause = function(bCallFlash) { + /** + * Pauses sound playback. + * + * @return {SMSound} The SMSound object + */ + + this.pause = function(_bCallFlash) { + if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { return _t; } + _s._wD('SMSound.pause()'); _t.paused = true; + if (!_t.isHTML5) { - if (bCallFlash || bCallFlash === undefined) { + if (_bCallFlash || _bCallFlash === undefined) { _s.o._pause(_t.sID); } } else { _t._setup_html5().pause(); _stop_html5_timer(); } + if (_t._iO.onpause) { _t._iO.onpause.apply(_t); } + return _t; + }; - // When auto-loaded streams pause on buffer full they have a playState of 0. - // We need to make sure that the playState is set to 1 when these streams "resume". - // - // When a paused stream is resumed, we need to trigger the onplay() callback if it - // hasn't been called already. In this case since the sound is being played for the - // first time, I think it's more appropriate to call onplay() rather than onresume(). + /** + * Resumes sound playback. + * + * @return {SMSound} The SMSound object + */ + + /** + * When auto-loaded streams pause on buffer full they have a playState of 0. + * We need to make sure that the playState is set to 1 when these streams "resume". + * When a paused stream is resumed, we need to trigger the onplay() callback if it + * hasn't been called already. In this case since the sound is being played for the + * first time, I think it's more appropriate to call onplay() rather than onresume(). + */ + this.resume = function() { + if (!_t.paused) { return _t; } + _s._wD('SMSound.resume()'); _t.paused = false; _t.playState = 1; + if (!_t.isHTML5) { if (_t._iO.isMovieStar) { // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition. _t.setPosition(_t.position); } - _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume) + // flash method is toggle-based (pause/resume) + _s.o._pause(_t.sID); } else { _t._setup_html5().play(); _start_html5_timer(); } + if (!_t._onplay_called && _t._iO.onplay) { _t._iO.onplay.apply(_t); _t._onplay_called = true; } else if (_t._iO.onresume) { _t._iO.onresume.apply(_t); } + return _t; + }; + /** + * Toggles sound playback. + * + * @return {SMSound} The SMSound object + */ + this.togglePause = function() { + _s._wD('SMSound.togglePause()'); + if (_t.playState === 0) { _t.play({ - position: (_fV === 9 && !_t.isHTML5 ? _t.position:_t.position / 1000) + position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) }); return _t; } + if (_t.paused) { _t.resume(); } else { _t.pause(); } + return _t; + }; + /** + * Sets the panning (L-R) effect. + * + * @param {number} nPan The pan value (-100 to 100) + * @return {SMSound} The SMSound object + */ + this.setPan = function(nPan, bInstanceOnly) { + if (typeof nPan === 'undefined') { nPan = 0; } + if (typeof bInstanceOnly === 'undefined') { bInstanceOnly = false; } + if (!_t.isHTML5) { _s.o._setPan(_t.sID, nPan); } // else { no HTML5 pan? } + _t._iO.pan = nPan; + if (!bInstanceOnly) { _t.pan = nPan; _t.options.pan = nPan; } + return _t; + }; - this.setVolume = function(nVol, bInstanceOnly) { + /** + * Sets the volume. + * + * @param {number} nVol The volume value (0 to 100) + * @return {SMSound} The SMSound object + */ + + this.setVolume = function(nVol, _bInstanceOnly) { + if (typeof nVol === 'undefined') { nVol = 100; } - if (typeof bInstanceOnly === 'undefined') { - bInstanceOnly = false; + + if (typeof _bInstanceOnly === 'undefined') { + _bInstanceOnly = false; } + if (!_t.isHTML5) { _s.o._setVolume(_t.sID, (_s.muted && !_t.muted) || _t.muted?0:nVol); } else if (_t._a) { _t._a.volume = Math.max(0, Math.min(1, nVol/100)); // valid range: 0-1 } + _t._iO.volume = nVol; - if (!bInstanceOnly) { + + if (!_bInstanceOnly) { _t.volume = nVol; _t.options.volume = nVol; } + return _t; + }; + /** + * Mutes the sound. + * + * @return {SMSound} The SMSound object + */ + this.mute = function() { + _t.muted = true; + if (!_t.isHTML5) { _s.o._setVolume(_t.sID, 0); } else if (_t._a) { _t._a.muted = true; } + return _t; + }; + /** + * Unmutes the sound. + * + * @return {SMSound} The SMSound object + */ + this.unmute = function() { + _t.muted = false; var hasIO = typeof _t._iO.volume !== 'undefined'; + if (!_t.isHTML5) { _s.o._setVolume(_t.sID, hasIO?_t._iO.volume:_t.options.volume); } else if (_t._a) { _t._a.muted = false; } + return _t; + }; + /** + * Toggles the muted state of a sound. + * + * @return {SMSound} The SMSound object + */ + this.toggleMute = function() { + return (_t.muted?_t.unmute():_t.mute()); + }; + /** + * Calls the onposition() method of a SMSound object. + * + * @param {number} nPosition The position to watch for + * @param {function} oMethod The relevant callback to fire + * @param {object} oScope Optional: The scope to apply the callback to + * @return {SMSound} The SMSound object + */ + this.onposition = function(nPosition, oMethod, oScope) { + // TODO: allow for ranges, too? eg. (nPosition instanceof Array) + _t._onPositionItems.push({ position: nPosition, method: oMethod, scope: (typeof oScope !== 'undefined'?oScope:_t), fired: false }); + return _t; + }; + /** + * TODO: This should be marked as pseudo-private. + */ + this.processOnPosition = function() { + var i, item, j = _t._onPositionItems.length; + if (!j || !_t.playState || _t._onPositionFired >= j) { return false; } + for (i=j; i--;) { item = _t._onPositionItems[i]; if (!item.fired && _t.position >= item.position) { - item.method.apply(item.scope,[item.position]); item.fired = true; _s._onPositionFired++; + item.method.apply(item.scope,[item.position]); } } + return true; + }; this.resetOnPosition = function(nPosition) { + // reset "fired" for items interested in this position var i, item, j = _t._onPositionItems.length; + if (!j) { return false; } + for (i=j; i--;) { item = _t._onPositionItems[i]; if (item.fired && nPosition <= item.position) { @@ -1424,48 +2089,34 @@ function SoundManager(smURL, smID) { _s._onPositionFired--; } } - return true; - }; - // pseudo-private soundManager reference + return true; - this._onTimer = function(bForce) { - // HTML5-only _whileplaying() etc. - var time, x = {}; - if (_t._hasTimer || bForce) { - if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { // TODO: May not need to track readyState (1 = loading) - _t.duration = _t._get_html5_duration(); - _t.durationEstimate = _t.duration; - time = _t._a.currentTime?_t._a.currentTime*1000:0; - _t._whileplaying(time,x,x,x,x); - return true; - } else { - _s._wD('_onTimer: Warn for "'+_t.sID+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK')); - return false; - } - } }; - // --- private internals --- - - this._get_html5_duration = function() { - var d = (_t._a ? _t._a.duration*1000 : (_t._iO ? _t._iO.duration : undefined)); - return (d && !isNaN(d) && d !== Infinity ? d : (_t._iO ? _t._iO.duration : null)); - }; + /** + * SoundManager() private internals + * -------------------------------- + */ _start_html5_timer = function() { + if (_t.isHTML5) { _startTimer(_t); } + }; _stop_html5_timer = function() { + if (_t.isHTML5) { _stopTimer(_t); } + }; - _resetProperties = function(bLoaded) { + _resetProperties = function() { + _t._onPositionItems = []; _t._onPositionFired = 0; _t._hasTimer = null; @@ -1481,82 +2132,170 @@ function SoundManager(smURL, smID) { _t.loaded = false; _t.playState = 0; _t.paused = false; - _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success + + // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success + _t.readyState = 0; + _t.muted = false; - _t.didBeforeFinish = false; - _t.didJustBeforeFinish = false; _t.isBuffering = false; _t.instanceOptions = {}; _t.instanceCount = 0; + _t.peakData = { left: 0, right: 0 }; + _t.waveformData = { left: [], right: [] }; - _t.eqData = []; // legacy: 1D array + + // legacy: 1D array + _t.eqData = []; + _t.eqData.left = []; _t.eqData.right = []; + }; _resetProperties(); - // pseudo-private methods used by soundManager + /** + * Pseudo-private SMSound internals + * -------------------------------- + */ + + this._onTimer = function(bForce) { + + // HTML5-only _whileplaying() etc. + + var time, x = {}; + + if (_t._hasTimer || bForce) { + + // TODO: May not need to track readyState (1 = loading) + + if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { + + _t.duration = _t._get_html5_duration(); + _t.durationEstimate = _t.duration; + time = _t._a.currentTime?_t._a.currentTime*1000:0; + _t._whileplaying(time,x,x,x,x); + return true; + + } else { + + _s._wD('_onTimer: Warn for "'+_t.sID+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK')); + return false; + + } + + } + + }; + + this._get_html5_duration = function() { + + var d = (_t._a ? _t._a.duration*1000 : (_t._iO ? _t._iO.duration : undefined)), + result = (d && !isNaN(d) && d !== Infinity ? d : (_t._iO ? _t._iO.duration : null)); + + return result; + + }; this._setup_html5 = function(oOptions) { + var _iO = _mixin(_t._iO, oOptions), d = decodeURI, _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, _dURL = d(_iO.url), _oldIO = (_a && _a._t ? _a._t.instanceOptions : null); + if (_a) { + if (_a._t && _oldIO.url === _iO.url && (!_t._lastURL || (_t._lastURL === _oldIO.url))) { - return _a; // same url, ignore request + // same url, ignore request + return _a; } + _s._wD('setting new URL on existing object: ' + _dURL + (_t._lastURL ? ', old URL: ' + _t._lastURL : '')); - /* + + /** * "First things first, I, Poppa.." (reset the previous state of the old sound, if playing) * Fixes case with devices that can only play one sound at a time * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state */ + if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { _a._t.stop(); } - _resetProperties(); // new URL, so reset load/playstate and so on + + // new URL, so reset load/playstate and so on + _resetProperties(); + _a.src = _iO.url; _t.url = _iO.url; _t._lastURL = _iO.url; _a._called_load = false; + } else { + _s._wD('creating HTML5 Audio() element with URL: '+_dURL); _a = new Audio(_iO.url); + _a._called_load = false; + + // android (seen in 2.3/Honeycomb) sometimes fails first .load() -> .play(), results in playback failure and ended() events? + if (_is_android) { + _a._called_load = true; + } + if (_useGlobalHTML5Audio) { _s._global_a = _a; } + } _t.isHTML5 = true; - _t._a = _a; // store a ref on the track - _a._t = _t; // store a ref on the audio + + // store a ref on the track + _t._a = _a; + + // store a ref on the audio + _a._t = _t; + _t._add_html5_events(); _a.loop = (_iO.loops>1?'loop':''); + if (_iO.autoLoad || _iO.autoPlay) { - _a.autobuffer = 'auto'; // early HTML5 implementation (non-standard) - _a.preload = 'auto'; // standard + + // early HTML5 implementation (non-standard) + _a.autobuffer = 'auto'; + + // standard + _a.preload = 'auto'; + _t.load(); _a._called_load = true; + } else { - _a.autobuffer = false; // early HTML5 implementation (non-standard) - _a.preload = 'none'; // standard + + // early HTML5 implementation (non-standard) + _a.autobuffer = false; + + // standard + _a.preload = 'none'; + } - _a.loop = (_iO.loops>1?'loop':''); // boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop + + // boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop + _a.loop = (_iO.loops>1?'loop':''); + return _a; - }; - // related private methods + }; this._add_html5_events = function() { + if (_t._a._added_events) { return false; } @@ -1570,96 +2309,223 @@ function SoundManager(smURL, smID) { _s._wD(_h5+'adding event listeners: '+_t.sID); _t._a._added_events = true; - for (f in _s._html5_events) { - if (_s._html5_events.hasOwnProperty(f)) { - add(f, _s._html5_events[f]); + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + add(f, _html5_events[f]); } } return true; + }; - // Keep this externally accessible this._remove_html5_events = function() { + // Remove event listeners + + var f; + function remove(oEvt, oFn, bCapture) { return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); } + _s._wD(_h5+'removing event listeners: '+_t.sID); _t._a._added_events = false; - for (var f in _s._html5_events) { - if (_s._html5_events.hasOwnProperty(f)) { - remove(f, _s._html5_events[f]); + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + remove(f, _html5_events[f]); + } + } + + }; + + /** + * Pseudo-private event internals + * ------------------------------ + */ + + this._onload = function(nSuccess) { + + + var fN = 'SMSound._onload(): ', loadOK = !!(nSuccess); + _s._wD(fN + '"' + _t.sID + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2)); + // + + if (!loadOK && !_t.isHTML5) { + if (_s.sandbox.noRemote === true) { + _s._wD(fN + _str('noNet'), 1); + } + if (_s.sandbox.noLocal === true) { + _s._wD(fN + _str('noLocal'), 1); } } + // + + _t.loaded = loadOK; + _t.readyState = loadOK?3:2; + _t._onbufferchange(0); + + if (_t._iO.onload) { + _t._iO.onload.apply(_t, [loadOK]); + } + + return true; + + }; + + this._onbufferchange = function(nIsBuffering) { + + var fN = 'SMSound._onbufferchange()'; + + if (_t.playState === 0) { + // ignore if not playing + return false; + } + + if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { + return false; + } + + _t.isBuffering = (nIsBuffering === 1); + if (_t._iO.onbufferchange) { + _s._wD(fN + ': ' + nIsBuffering); + _t._iO.onbufferchange.apply(_t); + } + + return true; + + }; + + /** + * Notify Mobile Safari that user action is required + * to continue playing / loading the audio file. + */ + + this._onsuspend = function () { + + if (_t._iO.onsuspend) { + _s._wD('SMSound._onsuspend()'); + _t._iO.onsuspend.apply(_t); + } + + return true; + + }; + + /** + * flash 9/movieStar + RTMP-only method, should fire only once at most + * at this point we just recreate failed sounds rather than trying to reconnect + */ + + this._onfailure = function(msg, level, code) { + + _t.failures++; + _s._wD('SMSound._onfailure(): "'+_t.sID+'" count '+_t.failures); + + if (_t._iO.onfailure && _t.failures === 1) { + _t._iO.onfailure(_t, msg, level, code); + } else { + _s._wD('SMSound._onfailure(): ignoring'); + } + }; - // --- "private" methods called by Flash --- + this._onfinish = function() { + + // store local copy before it gets trashed.. + var _io_onfinish = _t._iO.onfinish; + _t._onbufferchange(0); + _t.resetOnPosition(0); + + // reset some state items + if (_t.instanceCount) { + + _t.instanceCount--; + if (!_t.instanceCount) { + // reset instance options + _t.playState = 0; + _t.paused = false; + _t.instanceCount = 0; + _t.instanceOptions = {}; + _t._iO = {}; + _stop_html5_timer(); + } + + if (!_t.instanceCount || _t._iO.multiShotEvents) { + // fire onfinish for last, or every instance + if (_io_onfinish) { + _s._wD('SMSound._onfinish(): "' + _t.sID + '"'); + _io_onfinish.apply(_t); + } + } + + } + + }; this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { + _t.bytesLoaded = nBytesLoaded; _t.bytesTotal = nBytesTotal; _t.duration = Math.floor(nDuration); _t.bufferLength = nBufferLength; + if (!_t._iO.isMovieStar) { + if (_t._iO.duration) { // use options, if specified and larger _t.durationEstimate = (_t.duration > _t._iO.duration) ? _t.duration : _t._iO.duration; } else { _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); + } + if (_t.durationEstimate === undefined) { _t.durationEstimate = _t.duration; } + if (_t.readyState !== 3 && _t._iO.whileloading) { _t._iO.whileloading.apply(_t); } + } else { + _t.durationEstimate = _t.duration; if (_t.readyState !== 3 && _t._iO.whileloading) { _t._iO.whileloading.apply(_t); } - } - }; - this._onid3 = function(oID3PropNames, oID3Data) { - // oID3PropNames: string array (names) - // ID3Data: string array (data) - _s._wD('SMSound._onid3(): "' + this.sID + '" ID3 data received.'); - var oData = [], i, j; - for (i = 0, j = oID3PropNames.length; i < j; i++) { - oData[oID3PropNames[i]] = oID3Data[i]; - } - _t.id3 = _mixin(_t.id3, oData); - if (_t._iO.onid3) { - _t._iO.onid3.apply(_t); } + }; this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { + if (isNaN(nPosition) || nPosition === null) { - return false; // flash safety net - } - if (_t.playState === 0 && nPosition > 0) { - // invalid position edge case for end/stop - nPosition = 0; + // flash safety net + return false; } + _t.position = nPosition; _t.processOnPosition(); - if (_fV > 8 && !_t.isHTML5) { + + if (!_t.isHTML5 && _fV > 8) { + if (_t._iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { _t.peakData = { left: oPeakData.leftPeak, right: oPeakData.rightPeak }; } + if (_t._iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { _t.waveformData = { left: oWaveformDataLeft.split(','), right: oWaveformDataRight.split(',') }; } + if (_t._iO.useEQData) { if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { var eqLeft = oEQData.leftEQ.split(','); @@ -1670,183 +2536,128 @@ function SoundManager(smURL, smID) { } } } + } + if (_t.playState === 1) { + // special case/hack: ensure buffering is false if loading from cache (and not yet started) - if (!_t.isHTML5 && _s.flashVersion === 8 && !_t.position && _t.isBuffering) { + if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { _t._onbufferchange(0); } + if (_t._iO.whileplaying) { - _t._iO.whileplaying.apply(_t); // flash may call after actual finish - } - if ((_t.loaded || (!_t.loaded && _t._iO.isMovieStar)) && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration - _t.position <= _t._iO.onbeforefinishtime) { - _t._onbeforefinish(); + // flash may call after actual finish + _t._iO.whileplaying.apply(_t); } + } + return true; + + }; + + this._onid3 = function(oID3PropNames, oID3Data) { + + // oID3PropNames: string array (names) + // ID3Data: string array (data) + _s._wD('SMSound._onid3(): "' + this.sID + '" ID3 data received.'); + + var oData = [], i, j; + + for (i = 0, j = oID3PropNames.length; i < j; i++) { + oData[oID3PropNames[i]] = oID3Data[i]; + } + _t.id3 = _mixin(_t.id3, oData); + + if (_t._iO.onid3) { + _t._iO.onid3.apply(_t); + } + }; - // Only applies to RTMP + // flash/RTMP-only + this._onconnect = function(bSuccess) { + var fN = 'SMSound._onconnect(): '; bSuccess = (bSuccess === 1); _s._wD(fN+'"'+_t.sID+'"'+(bSuccess?' connected.':' failed to connect? - '+_t.url), (bSuccess?1:2)); _t.connected = bSuccess; + if (bSuccess) { + _t.failures = 0; + if (_idCheck(_t.sID)) { if (_t.getAutoPlay()) { - _t.play(undefined, _t.getAutoPlay()); // only update the play state if auto playing + // only update the play state if auto playing + _t.play(undefined, _t.getAutoPlay()); } else if (_t._iO.autoLoad) { _t.load(); } } + if (_t._iO.onconnect) { _t._iO.onconnect.apply(_t,[bSuccess]); } - } - }; - this._onload = function(nSuccess) { - var fN = 'SMSound._onload(): ', loadOK = (nSuccess?true:false); - _s._wD(fN + '"' + _t.sID + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2)); - // - if (!loadOK && !_t.isHTML5) { - if (_s.sandbox.noRemote === true) { - _s._wD(fN + _str('noNet'), 1); - } - if (_s.sandbox.noLocal === true) { - _s._wD(fN + _str('noLocal'), 1); - } - } - // - _t.loaded = loadOK; - _t.readyState = loadOK?3:2; - _t._onbufferchange(0); - if (_t._iO.onload) { - _t._iO.onload.apply(_t, [loadOK]); } - return true; - }; - // fire onfailure() only once at most - // at this point we just recreate failed sounds rather than trying to reconnect. - this._onfailure = function(msg, level, code) { - _t.failures++; - _s._wD('SMSound._onfailure(): "'+_t.sID+'" count '+_t.failures); - if (_t._iO.onfailure && _t.failures === 1) { - _t._iO.onfailure(_t, msg, level, code); - } else { - _s._wD('SMSound._onfailure(): ignoring'); - } }; - this._onbeforefinish = function() { - if (!_t.didBeforeFinish) { - _t.didBeforeFinish = true; - if (_t._iO.onbeforefinish) { - _s._wD('SMSound._onbeforefinish(): "' + _t.sID + '"'); - _t._iO.onbeforefinish.apply(_t); + this._ondataerror = function(sError) { + + // flash 9 wave/eq data handler + // hack: called at start, and end from flash at/after onfinish() + if (_t.playState > 0) { + _s._wD('SMSound._ondataerror(): ' + sError); + if (_t._iO.ondataerror) { + _t._iO.ondataerror.apply(_t); } } + }; - this._onjustbeforefinish = function(msOffset) { - if (!_t.didJustBeforeFinish) { - _t.didJustBeforeFinish = true; - if (_t._iO.onjustbeforefinish) { - _s._wD('SMSound._onjustbeforefinish(): "' + _t.sID + '"'); - _t._iO.onjustbeforefinish.apply(_t); - } + }; // SMSound() + + /** + * Private SoundManager internals + * ------------------------------ + */ + + _getDocument = function() { + + return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); + + }; + + _id = function(sID) { + + return _doc.getElementById(sID); + + }; + + _mixin = function(oMain, oAdd) { + + // non-destructive merge + var o1 = {}, i, o2, o; + + // clone c1 + for (i in oMain) { + if (oMain.hasOwnProperty(i)) { + o1[i] = oMain[i]; } - }; + } - this._onfinish = function() { - // _s._wD('SMSound._onfinish(): "' + _t.sID + '" got instanceCount '+_t.instanceCount); - var _io_onfinish = _t._iO.onfinish; // store local copy before it gets trashed.. - _t._onbufferchange(0); - _t.resetOnPosition(0); - if (_t._iO.onbeforefinishcomplete) { - _t._iO.onbeforefinishcomplete.apply(_t); - } - // reset some state items - _t.didBeforeFinish = false; - _t.didJustBeforeFinish = false; - if (_t.instanceCount) { - _t.instanceCount--; - if (!_t.instanceCount) { - // reset instance options - _t.playState = 0; - _t.paused = false; - _t.instanceCount = 0; - _t.instanceOptions = {}; - _t._iO = {}; - _stop_html5_timer(); - } - if (!_t.instanceCount || _t._iO.multiShotEvents) { - // fire onfinish for last, or every instance - if (_io_onfinish) { - _s._wD('SMSound._onfinish(): "' + _t.sID + '"'); - _io_onfinish.apply(_t); - } - } - } - }; - - this._onbufferchange = function(nIsBuffering) { - var fN = 'SMSound._onbufferchange()'; - if (_t.playState === 0) { - // ignore if not playing - return false; - } - if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { - return false; - } - _t.isBuffering = (nIsBuffering === 1); - if (_t._iO.onbufferchange) { - _s._wD(fN + ': ' + nIsBuffering); - _t._iO.onbufferchange.apply(_t); - } - return true; - }; - - this._ondataerror = function(sError) { - // flash 9 wave/eq data handler - if (_t.playState > 0) { // hack: called at start, and end from flash at/after onfinish() - _s._wD('SMSound._ondataerror(): ' + sError); - if (_t._iO.ondataerror) { - _t._iO.ondataerror.apply(_t); - } - } - }; - - }; // SMSound() - - // --- private SM2 internals --- - - _getDocument = function() { - return (_doc.body?_doc.body:(_doc._docElement?_doc.documentElement:_doc.getElementsByTagName('div')[0])); - }; - - _id = function(sID) { - return _doc.getElementById(sID); - }; - - _mixin = function(oMain, oAdd) { - // non-destructive merge - var o1 = {}, i, o2, o; - for (i in oMain) { // clone c1 - if (oMain.hasOwnProperty(i)) { - o1[i] = oMain[i]; - } - } - o2 = (typeof oAdd === 'undefined'?_s.defaultOptions:oAdd); - for (o in o2) { - if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { - o1[o] = o2[o]; + o2 = (typeof oAdd === 'undefined'?_s.defaultOptions:oAdd); + for (o in o2) { + if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { + o1[o] = o2[o]; } } return o1; + }; _event = (function() { @@ -1858,34 +2669,46 @@ function SoundManager(smURL, smID) { }; function getArgs(oArgs) { + var args = _slice.call(oArgs), len = args.length; + if (old) { - args[1] = 'on' + args[1]; // prefix + // prefix + args[1] = 'on' + args[1]; if (len > 3) { - args.pop(); // no capture + // no capture + args.pop(); } } else if (len === 3) { args.push(false); } return args; + } function apply(args, sType) { + var element = args.shift(), method = [evt[sType]]; + if (old) { element[method](args[0], args[1]); } else { element[method].apply(element, args); } + } function add() { + apply(getArgs(arguments), 'add'); + } function remove() { + apply(getArgs(arguments), 'remove'); + } return { @@ -1895,366 +2718,1228 @@ function SoundManager(smURL, smID) { }()); - _html5OK = function(iO) { - return (!iO.serverURL && (iO.type?_html5CanPlay({type:iO.type}):_html5CanPlay(iO.url)||_html5Only)); // Use type, if specified. If HTML5-only mode, no other options, so just give 'er - }; + /** + * Internal HTML5 event handling + * ----------------------------- + */ - _html5CanPlay = function(sURL) { - // try to find MIME, test and return truthiness - if (!_s.useHTML5Audio || !_s.hasHTML5) { - return false; - } - var result, mime, offset, fileExt, item, aF = _s.audioFormats; - if (!_html5Ext) { - _html5Ext = []; - for (item in aF) { - if (aF.hasOwnProperty(item)) { - _html5Ext.push(item); - if (aF[item].related) { - _html5Ext = _html5Ext.concat(aF[item].related); - } - } - } - _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')','i'); - } - mime = (typeof sURL.type !== 'undefined'?sURL.type:null); - fileExt = (typeof sURL === 'string'?sURL.toLowerCase().match(_html5Ext):null); // TODO: Strip URL queries, etc. - if (!fileExt || !fileExt.length) { - if (!mime) { - return false; - } else { - // audio/mp3 -> mp3, result should be known - offset = mime.indexOf(';'); - fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); // strip "audio/X; codecs.." - } - } else { - fileExt = fileExt[0].substr(1); // "mp3", for example - } - if (fileExt && typeof _s.html5[fileExt] !== 'undefined') { - // result known - return _s.html5[fileExt]; - } else { - if (!mime) { - if (fileExt && _s.html5[fileExt]) { - return _s.html5[fileExt]; - } else { - // best-case guess, audio/whatever-dot-filename-format-you're-playing - mime = 'audio/'+fileExt; - } - } - result = _s.html5.canPlayType(mime); - _s.html5[fileExt] = result; - // _s._wD('canPlayType, found result: '+result); - return result; - } - }; + function _html5_event(oFn) { - _testHTML5 = function() { - if (!_s.useHTML5Audio || typeof Audio === 'undefined') { - return false; - } - // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/ - var a = (typeof Audio !== 'undefined' ? (_isOpera ? new Audio(null) : new Audio()) : null), item, support = {}, aF, i, _hasFlash = _detectFlash(); - function _cp(m) { - var canPlay, i, j, isOK = false; - if (!a || typeof a.canPlayType !== 'function') { - return false; - } - if (m instanceof Array) { - // iterate through all mime types, return any successes - for (i=0, j=m.length; i + if (this._t && this._t.sID) { + _s._wD(_h5+'ignoring '+e.type+': '+this._t.sID); + } else { + _s._wD(_h5+'ignoring '+e.type); } - return isOK; + // + return null; } else { - canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false); - return (canPlay && (canPlay.match(_s.html5Test)?true:false)); - } - } - // test all registered formats + codecs - aF = _s.audioFormats; - for (item in aF) { - if (aF.hasOwnProperty(item)) { - support[item] = _cp(aF[item].type); - // assign result to related formats, too - if (aF[item] && aF[item].related) { - for (i=aF[item].related.length; i--;) { - _s.html5[aF[item].related[i]] = support[item]; - } - } + return oFn.call(this, e); } - } - support.canPlayType = (a?_cp:null); - _s.html5 = _mixin(_s.html5, support); - return true; - }; - _strings = { - // - notReady: 'Not loaded yet - wait for soundManager.onload()/onready()', - notOK: 'Audio support is not available.', - appXHTML: _smc + 'createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.', - spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)', - swf404: _sm + ': Verify that %s is a valid path.', - tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)', - checkSWF: 'See SWF output for more debug info.', - localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/', - waitFocus: _sm + ': Special case: Waiting for focus-related event..', - waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...', - waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...', - needFunction: _sm + ': Function object expected for %s', - badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character', - noMS: 'MovieStar mode not enabled. Exiting.', - currentObj: '--- ' + _sm + '._debug(): Current sound objects ---', - waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash..', - waitOnload: _sm + ': Waiting for window.onload()', - docLoaded: _sm + ': Document already loaded', - onload: _smc + 'initComplete(): calling soundManager.onload()', - onloadOK: _sm + '.onload() complete', - init: '-- ' + _smc + 'init() --', - didInit: _smc + 'init(): Already called?', - flashJS: _sm + ': Attempting to call Flash from JS..', - noPolling: _sm + ': Polling (whileloading()/whileplaying() support) is disabled.', - secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html', - badRemove: 'Warning: Failed to remove flash movie.', - noPeak: 'Warning: peakData features unsupported for movieStar formats', - shutdown: _sm + '.disable(): Shutting down', - queue: _sm + ': Queueing %s handler', - smFail: _sm + ': Failed to initialise.', - smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.', - fbTimeout: 'No flash response, applying .'+_s.swfCSS.swfTimedout+' CSS..', - fbLoaded: 'Flash loaded', - fbHandler: _smc+'flashBlockHandler()', - manURL: 'SMSound.load(): Using manually-assigned URL', - onURL: _sm + '.load(): current URL already assigned.', - badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.', - as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)', - noNSLoop: 'Note: Looping not implemented for MovieStar formats', - needfl9: 'Note: Switching to flash 9, required for MP4 formats.', - mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case', - mfOn: 'mobileFlash::enabling on-screen flash repositioning', - policy: 'Enabling usePolicyFile for data access' - // - }; + }; - _str = function() { // o [,items to replace] - // - var args = _slice.call(arguments), // real array, please - o = args.shift(), // first arg - str = (_strings && _strings[o]?_strings[o]:''), i, j; - if (str && args && args.length) { - for (i = 0, j = args.length; i < j; i++) { - str = str.replace('%s', args[i]); - } - } - return str; - // - }; + } - _loopFix = function(sOpt) { - // flash 8 requires stream = false for looping to work - if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { - _wDS('as2loop'); - sOpt.stream = false; - } - return sOpt; - }; + _html5_events = { - _policyFix = function(sOpt, sPre) { - if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { - _s._wD((sPre?sPre+':':'') + _str('policy')); - sOpt.usePolicyFile = true; - } - return sOpt; - }; + // HTML5 event-name-to-handler map - _complain = function(sMsg) { - if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') { - console.warn(sMsg); - } else { - _s._wD(sMsg); - } - }; + abort: _html5_event(function(e) { - _doNothing = function() { - return false; - }; + _s._wD(_h5+'abort: '+this._t.sID); - _disableObject = function(o) { - for (var oProp in o) { - if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { - o[oProp] = _doNothing; - } - } - oProp = null; - }; + }), - _failSafely = function(bNoDisable) { - // general failure exception handler - if (typeof bNoDisable === 'undefined') { + // enough has loaded to play + + canplay: _html5_event(function(e) { + + if (this._t._html5_canplay) { + // this event has already fired. ignore. + return true; + } + + this._t._html5_canplay = true; + _s._wD(_h5+'canplay: '+this._t.sID+', '+this._t.url); + this._t._onbufferchange(0); + var position1K = (!isNaN(this._t.position)?this._t.position/1000:null); + + // set the position if position was set before the sound loaded + if (this._t.position && this.currentTime !== position1K) { + _s._wD(_h5+'canplay: setting position to '+position1K); + try { + this.currentTime = position1K; + } catch(ee) { + _s._wD(_h5+'setting position failed: '+ee.message, 2); + } + } + + }), + + load: _html5_event(function(e) { + + if (!this._t.loaded) { + this._t._onbufferchange(0); + // should be 1, and the same + this._t._whileloading(this._t.bytesTotal, this._t.bytesTotal, this._t._get_html5_duration()); + this._t._onload(true); + } + + }), + + emptied: _html5_event(function(e) { + + _s._wD(_h5+'emptied: '+this._t.sID); + + }), + + ended: _html5_event(function(e) { + + _s._wD(_h5+'ended: '+this._t.sID); + this._t._onfinish(); + + }), + + error: _html5_event(function(e) { + + _s._wD(_h5+'error: '+this.error.code); + // call load with error state? + this._t._onload(false); + + }), + + loadeddata: _html5_event(function(e) { + + var t = this._t, + // at least 1 byte, so math works + bytesTotal = t.bytesTotal || 1; + + _s._wD(_h5+'loadeddata: '+this._t.sID); + + // safari seems to nicely report progress events, eventually totalling 100% + if (!t._loaded && !_isSafari) { + t.duration = t._get_html5_duration(); + // fire whileloading() with 100% values + t._whileloading(bytesTotal, bytesTotal, t._get_html5_duration()); + t._onload(true); + } + + }), + + loadedmetadata: _html5_event(function(e) { + + _s._wD(_h5+'loadedmetadata: '+this._t.sID); + + }), + + loadstart: _html5_event(function(e) { + + _s._wD(_h5+'loadstart: '+this._t.sID); + // assume buffering at first + this._t._onbufferchange(1); + + }), + + play: _html5_event(function(e) { + + _s._wD(_h5+'play: '+this._t.sID+', '+this._t.url); + // once play starts, no buffering + this._t._onbufferchange(0); + + }), + + // TODO: verify if this is actually implemented anywhere yet. + playing: _html5_event(function(e) { + + _s._wD(_h5+'playing: '+this._t.sID+', '+this._t.url); + + // once play starts, no buffering + this._t._onbufferchange(0); + + }), + + progress: _html5_event(function(e) { + + if (this._t.loaded) { + return false; + } + + var i, j, str, buffered = 0, + isProgress = (e.type === 'progress'), + ranges = e.target.buffered, + + // firefox 3.6 implements e.loaded/total (bytes) + loaded = (e.loaded||0), + + total = (e.total||1); + + if (ranges && ranges.length) { + + // if loaded is 0, try TimeRanges implementation as % of load + // https://developer.mozilla.org/en/DOM/TimeRanges + + for (i=ranges.length; i--;) { + buffered = (ranges.end(i) - ranges.start(i)); + } + + // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges + loaded = buffered/e.target.duration; + + // + if (isProgress && ranges.length > 1) { + str = []; + j = ranges.length; + for (i=0; i + + } + + if (!isNaN(loaded)) { + + // if progress, likely not buffering + this._t._onbufferchange(0); + this._t._whileloading(loaded, total, this._t._get_html5_duration()); + if (loaded && total && loaded === total) { + // in case "onload" doesn't fire (eg. gecko 1.9.2) + _html5_events.load.call(this, e); + } + + } + + }), + + ratechange: _html5_event(function(e) { + + _s._wD(_h5+'ratechange: '+this._t.sID); + + }), + + suspend: _html5_event(function(e) { + + // download paused/stopped, may have finished (eg. onload) + + _s._wD(_h5+'suspend: '+this._t.sID); + _html5_events.progress.call(this, e); + this._t._onsuspend(); + + }), + + stalled: _html5_event(function(e) { + + _s._wD(_h5+'stalled: '+this._t.sID); + + }), + + timeupdate: _html5_event(function(e) { + + this._t._onTimer(); + + }), + + waiting: _html5_event(function(e) { + + // see also: seeking + _s._wD(_h5+'waiting: '+this._t.sID); + + // playback faster than download rate, etc. + this._t._onbufferchange(1); + + }) + + }; + + _html5OK = function(iO) { + + // Use type, if specified. If HTML5-only mode, no other options, so just give 'er + return (!iO.serverURL && (iO.type?_html5CanPlay({type:iO.type}):_html5CanPlay({url:iO.url})||_s.html5Only)); + + }; + + _html5Unload = function(oAudio) { + + /** + * Internal method: Unload media, and cancel any current/pending network requests. + * Firefox can load an empty URL, which allegedly destroys the decoder and stops the download. + * https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media + * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL. + */ + + if (oAudio) { + // Firefox likes '' for unload, most other UAs don't and fail to unload. + oAudio.src = (_is_firefox ? '' : _emptyURL); + } + + }; + + _html5CanPlay = function(o) { + + /** + * Try to find MIME, test and return truthiness + * o = { + * url: '/path/to/an.mp3', + * type: 'audio/mp3' + * } + */ + + if (!_s.useHTML5Audio || !_s.hasHTML5) { + return false; + } + + var url = (o.url || null), + mime = (o.type || null), + aF = _s.audioFormats, + result, + offset, + fileExt, + item; + + function preferFlashCheck(kind) { + + // whether flash should play a given type + return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); + + } + + // account for known cases like audio/mp3 + + if (mime && _s.html5[mime] !== 'undefined') { + return (_s.html5[mime] && !preferFlashCheck(mime)); + } + + if (!_html5Ext) { + _html5Ext = []; + for (item in aF) { + if (aF.hasOwnProperty(item)) { + _html5Ext.push(item); + if (aF[item].related) { + _html5Ext = _html5Ext.concat(aF[item].related); + } + } + } + _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')(\\?.*)?$','i'); + } + + // TODO: Strip URL queries, etc. + fileExt = (url ? url.toLowerCase().match(_html5Ext) : null); + + if (!fileExt || !fileExt.length) { + if (!mime) { + return false; + } else { + // audio/mp3 -> mp3, result should be known + offset = mime.indexOf(';'); + // strip "audio/X; codecs.." + fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); + } + } else { + // match the raw extension name - "mp3", for example + fileExt = fileExt[1]; + } + + if (fileExt && typeof _s.html5[fileExt] !== 'undefined') { + // result known + return (_s.html5[fileExt] && !preferFlashCheck(fileExt)); + } else { + mime = 'audio/'+fileExt; + result = _s.html5.canPlayType({type:mime}); + _s.html5[fileExt] = result; + // _s._wD('canPlayType, found result: '+result); + return (result && _s.html5[mime] && !preferFlashCheck(mime)); + } + + }; + + _testHTML5 = function() { + + if (!_s.useHTML5Audio || typeof Audio === 'undefined') { + return false; + } + + // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/ + var a = (typeof Audio !== 'undefined' ? (_isOpera ? new Audio(null) : new Audio()) : null), + item, support = {}, aF, i; + + function _cp(m) { + + var canPlay, i, j, isOK = false; + + if (!a || typeof a.canPlayType !== 'function') { + return false; + } + + if (m instanceof Array) { + // iterate through all mime types, return any successes + for (i=0, j=m.length; i + notReady: 'Not loaded yet - wait for soundManager.onload()/onready()', + notOK: 'Audio support is not available.', + domError: _smc + 'createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.', + spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)', + swf404: _sm + ': Verify that %s is a valid path.', + tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)', + checkSWF: 'See SWF output for more debug info.', + localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/', + waitFocus: _sm + ': Special case: Waiting for focus-related event..', + waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...', + waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...', + needFunction: _sm + ': Function object expected for %s', + badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character', + currentObj: '--- ' + _sm + '._debug(): Current sound objects ---', + waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash..', + waitOnload: _sm + ': Waiting for window.onload()', + docLoaded: _sm + ': Document already loaded', + onload: _smc + 'initComplete(): calling soundManager.onload()', + onloadOK: _sm + '.onload() complete', + init: _smc + 'init()', + didInit: _smc + 'init(): Already called?', + flashJS: _sm + ': Attempting to call Flash from JS..', + secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html', + badRemove: 'Warning: Failed to remove flash movie.', + noPeak: 'Warning: peakData features unsupported for movieStar formats', + shutdown: _sm + '.disable(): Shutting down', + queue: _sm + ': Queueing %s handler', + smFail: _sm + ': Failed to initialise.', + smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.', + fbTimeout: 'No flash response, applying .'+_s.swfCSS.swfTimedout+' CSS..', + fbLoaded: 'Flash loaded', + fbHandler: _smc+'flashBlockHandler()', + manURL: 'SMSound.load(): Using manually-assigned URL', + onURL: _sm + '.load(): current URL already assigned.', + badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.', + as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)', + noNSLoop: 'Note: Looping not implemented for MovieStar formats', + needfl9: 'Note: Switching to flash 9, required for MP4 formats.', + mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case', + mfOn: 'mobileFlash::enabling on-screen flash repositioning', + policy: 'Enabling usePolicyFile for data access' + // + + }; + + _str = function() { + + // internal string replace helper. + // arguments: o [,items to replace] + // + + // real array, please + var args = _slice.call(arguments), + + // first arg + o = args.shift(), + + str = (_strings && _strings[o]?_strings[o]:''), i, j; + if (str && args && args.length) { + for (i = 0, j = args.length; i < j; i++) { + str = str.replace('%s', args[i]); + } + } + + return str; + // + + }; + + _loopFix = function(sOpt) { + + // flash 8 requires stream = false for looping to work + if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { + _wDS('as2loop'); + sOpt.stream = false; + } + + return sOpt; + + }; + + _policyFix = function(sOpt, sPre) { + + if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { + _s._wD((sPre || '') + _str('policy')); + sOpt.usePolicyFile = true; + } + + return sOpt; + + }; + + _complain = function(sMsg) { + + // + if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') { + console.warn(sMsg); + } else { + _s._wD(sMsg); + } + // + + }; + + _doNothing = function() { + + return false; + + }; + + _disableObject = function(o) { + + var oProp; + + for (oProp in o) { + if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { + o[oProp] = _doNothing; + } + } + + oProp = null; + + }; + + _failSafely = function(bNoDisable) { + + // general failure exception handler + + if (typeof bNoDisable === 'undefined') { bNoDisable = false; } - if (_disabled || bNoDisable) { - _wDS('smFail', 2); - _s.disable(bNoDisable); + + if (_disabled || bNoDisable) { + _wDS('smFail', 2); + _s.disable(bNoDisable); + } + + }; + + _normalizeMovieURL = function(smURL) { + + var urlParams = null, url; + + if (smURL) { + if (smURL.match(/\.swf(\?.*)?$/i)) { + urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); + if (urlParams) { + // assume user knows what they're doing + return smURL; + } + } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { + // append trailing slash, if needed + smURL += '/'; + } + } + + url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; + + if (_s.noSWFCache) { + url += ('?ts=' + new Date().getTime()); + } + + return url; + + }; + + _setVersionInfo = function() { + + // short-hand for internal use + + _fV = parseInt(_s.flashVersion, 10); + + if (_fV !== 8 && _fV !== 9) { + _s._wD(_str('badFV', _fV, _defaultFlashVersion)); + _s.flashVersion = _fV = _defaultFlashVersion; + } + + // debug flash movie, if applicable + + var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); + + if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { + _s._wD(_str('needfl9')); + _s.flashVersion = _fV = 9; + } + + _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); + + // set up default options + if (_fV > 8) { + // +flash 9 base options + _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); + _s.features.buffering = true; + // +moviestar support + _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); + _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + _s.features.movieStar = true; + } else { + _s.features.movieStar = false; + } + + // regExp for flash canPlay(), etc. + _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; + + // if applicable, use _debug versions of SWFs + _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); + + _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); + + }; + + _setPolling = function(bPolling, bHighPerformance) { + + if (!_s.o) { + return false; + } + + _s.o._setPolling(bPolling, bHighPerformance); + + }; + + _initDebug = function() { + + // starts debug mode, creating output
for UAs without console object + + // allow force of debug mode via URL + if (_s.debugURLParam.test(_wl)) { + _s.debugMode = true; + } + + // + if (_id(_s.debugID)) { + return false; + } + + var oD, oDebug, oTarget, oToggle, tmp; + + if (_s.debugMode && !_id(_s.debugID) && ((!_hasConsole || !_s.useConsole) || (_s.useConsole && _hasConsole && !_s.consoleOnly))) { + + oD = _doc.createElement('div'); + oD.id = _s.debugID + '-toggle'; + + oToggle = { + 'position': 'fixed', + 'bottom': '0px', + 'right': '0px', + 'width': '1.2em', + 'height': '1.2em', + 'lineHeight': '1.2em', + 'margin': '2px', + 'textAlign': 'center', + 'border': '1px solid #999', + 'cursor': 'pointer', + 'background': '#fff', + 'color': '#333', + 'zIndex': 10001 + }; + + oD.appendChild(_doc.createTextNode('-')); + oD.onclick = _toggleDebug; + oD.title = 'Toggle SM2 debug console'; + + if (_ua.match(/msie 6/i)) { + oD.style.position = 'absolute'; + oD.style.cursor = 'hand'; + } + + for (tmp in oToggle) { + if (oToggle.hasOwnProperty(tmp)) { + oD.style[tmp] = oToggle[tmp]; + } + } + + oDebug = _doc.createElement('div'); + oDebug.id = _s.debugID; + oDebug.style.display = (_s.debugMode?'block':'none'); + + if (_s.debugMode && !_id(oD.id)) { + try { + oTarget = _getDocument(); + oTarget.appendChild(oD); + } catch(e2) { + throw new Error(_str('domError')+' \n'+e2.toString()); + } + oTarget.appendChild(oDebug); + } + + } + + oTarget = null; + // + + }; + + _idCheck = this.getSoundById; + + // + _wDS = function(o, errorLevel) { + + if (!o) { + return ''; + } else { + return _s._wD(_str(o), errorLevel); + } + + }; + + // last-resort debugging option + + if (_wl.indexOf('sm2-debug=alert') + 1 && _s.debugMode) { + _s._wD = function(sText) {window.alert(sText);}; + } + + _toggleDebug = function() { + + var o = _id(_s.debugID), + oT = _id(_s.debugID + '-toggle'); + + if (!o) { + return false; + } + + if (_debugOpen) { + // minimize + oT.innerHTML = '+'; + o.style.display = 'none'; + } else { + oT.innerHTML = '-'; + o.style.display = 'block'; + } + + _debugOpen = !_debugOpen; + + }; + + _debugTS = function(sEventType, bSuccess, sMessage) { + + // troubleshooter debug hooks + + if (typeof sm2Debugger !== 'undefined') { + try { + sm2Debugger.handleEvent(sEventType, bSuccess, sMessage); + } catch(e) { + // oh well + } + } + + return true; + + }; + // + + _getSWFCSS = function() { + + var css = []; + + if (_s.debugMode) { + css.push(_s.swfCSS.sm2Debug); + } + + if (_s.debugFlash) { + css.push(_s.swfCSS.flashDebug); + } + + if (_s.useHighPerformance) { + css.push(_s.swfCSS.highPerf); + } + + return css.join(' '); + + }; + + _flashBlockHandler = function() { + + // *possible* flash block situation. + + var name = _str('fbHandler'), + p = _s.getMoviePercent(), + css = _s.swfCSS, + error = {type:'FLASHBLOCK'}; + + if (_s.html5Only) { + return false; + } + + if (!_s.ok()) { + + if (_needsFlash) { + // make the movie more visible, so user can fix + _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); + _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':'')); + } + + _s.didFlashBlock = true; + + // fire onready(), complain lightly + _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); + _catchError(error); + + } else { + + // SM2 loaded OK (or recovered) + + if (_s.didFlashBlock) { + _s._wD(name+': Unblocked'); + } + + if (_s.oMC) { + _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); + } + + } + + }; + + _addOnEvent = function(sType, oMethod, oScope) { + + if (typeof _on_queue[sType] === 'undefined') { + _on_queue[sType] = []; + } + + _on_queue[sType].push({ + 'method': oMethod, + 'scope': (oScope || null), + 'fired': false + }); + + }; + + _processOnEvents = function(oOptions) { + + // assume onready, if unspecified + + if (!oOptions) { + oOptions = { + type: 'onready' + }; + } + + if (!_didInit && oOptions && !oOptions.ignoreInit) { + // not ready yet. + return false; + } + + if (oOptions.type === 'ontimeout' && _s.ok()) { + // invalid case + return false; + } + + var status = { + success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) + }, + + // queue specified by type, or none + srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), + + queue = [], i, j, + args = [status], + canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); + + if (oOptions.error) { + args[0].error = oOptions.error; + } + + for (i = 0, j = srcQueue.length; i < j; i++) { + if (srcQueue[i].fired !== true) { + queue.push(srcQueue[i]); + } + } + + if (queue.length) { + _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s')); + for (i = 0, j = queue.length; i < j; i++) { + if (queue[i].scope) { + queue[i].method.apply(queue[i].scope, args); + } else { + queue[i].method.apply(this, args); + } + if (!canRetry) { + // flashblock case doesn't count here + queue[i].fired = true; + } + } + } + + return true; + + }; + + _initUserOnload = function() { + + _win.setTimeout(function() { + + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + + _processOnEvents(); + + // call user-defined "onload", scoped to window + + if (_s.onload instanceof Function) { + _wDS('onload', 1); + _s.onload.apply(_win); + _wDS('onloadOK', 1); + } + + if (_s.waitForWindowLoad) { + _event.add(_win, 'load', _initUserOnload); + } + + },1); + + }; + + _detectFlash = function() { + + // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt + + if (_hasFlash !== undefined) { + // this work has already been done. + return _hasFlash; + } + + var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; + + if (nP && nP.length) { + type = 'application/x-shockwave-flash'; + types = n.mimeTypes; + if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { + hasPlugin = true; + } + } else if (typeof AX !== 'undefined') { + try { + obj = new AX('ShockwaveFlash.ShockwaveFlash'); + } catch(e) { + // oh well + } + hasPlugin = (!!obj); } + + _hasFlash = hasPlugin; + + return hasPlugin; + }; - _normalizeMovieURL = function(smURL) { - var urlParams = null; - if (smURL) { - if (smURL.match(/\.swf(\?.*)?$/i)) { - urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); - if (urlParams) { - return smURL; // assume user knows what they're doing - } - } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { - smURL = smURL + '/'; + _featureCheck = function() { + + var needsFlash, item, + + // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (iPad) + iOS4 works. + isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); + + if (isSpecial) { + + // has Audio(), but is broken; let it load links directly. + _s.hasHTML5 = false; + + // ignore flash case, however + _s.html5Only = true; + + if (_s.oMC) { + _s.oMC.style.display = 'none'; } + + return false; + } - return (smURL && smURL.lastIndexOf('/') !== - 1?smURL.substr(0, smURL.lastIndexOf('/') + 1):'./') + _s.movieURL; - }; - _setVersionInfo = function() { - if (_fV !== 8 && _fV !== 9) { - _s._wD(_str('badFV', _fV, _defaultFlashVersion)); - _s.flashVersion = _defaultFlashVersion; + if (_s.useHTML5Audio) { + + if (!_s.html5 || !_s.html5.canPlayType) { + _s._wD('SoundManager: No HTML5 Audio() support detected.'); + _s.hasHTML5 = false; + return true; + } else { + _s.hasHTML5 = true; + } + if (_isBadSafari) { + _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1); + if (_detectFlash()) { + return true; + } + } + } else { + + // flash needed (or, HTML5 needs enabling.) + return true; + } - var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); // debug flash movie, if applicable - if (_s.useHTML5Audio && !_html5Only && _s.audioFormats.mp4.required && _s.flashVersion < 9) { - _s._wD(_str('needfl9')); - _s.flashVersion = 9; + + for (item in _s.audioFormats) { + if (_s.audioFormats.hasOwnProperty(item)) { + if ((_s.audioFormats[item].required && !_s.html5.canPlayType(_s.audioFormats[item].type)) || _s.flash[item] || _s.flash[_s.audioFormats[item].type]) { + // flash may be required, or preferred for this format + needsFlash = true; + } + } } - _fV = _s.flashVersion; // short-hand for internal use - _s.version = _s.versionNumber + (_html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); - // set up default options - if (_fV > 8) { - _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); - _s.features.buffering = true; + + // sanity check.. + if (_s.ignoreFlash) { + needsFlash = false; } - if (_fV > 8 && _s.useMovieStar) { - // flash 9+ support for movieStar formats as well as MP3 - _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); - _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _s.netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - _s.mimePattern = _s.netStreamMimeTypes; - _s.features.movieStar = true; - } else { - _s.useMovieStar = false; - _s.features.movieStar = false; + + _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); + + return (!_s.html5Only); + + }; + + _startTimer = function(oSound) { + + if (!oSound._hasTimer) { + oSound._hasTimer = true; } - _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; - _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf',isDebug); - _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); + }; - _setPolling = function(bPolling, bHighPerformance) { - if (!_s.o || !_s.allowPolling) { - return false; + _stopTimer = function(oSound) { + + if (oSound._hasTimer) { + oSound._hasTimer = false; } - _s.o._setPolling(bPolling, bHighPerformance); + }; - function _initDebug() { - if (_s.debugURLParam.test(_wl)) { - _s.debugMode = true; // allow force of debug mode via URL + _catchError = function(options) { + + options = (typeof options !== 'undefined' ? options : {}); + + if (_s.onerror instanceof Function) { + _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); } - // - if (_id(_s.debugID)) { + + if (typeof options.fatal !== 'undefined' && options.fatal) { + _s.disable(); + } + + }; + + _badSafariFix = function() { + + // special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4 + if (!_isBadSafari || !_detectFlash()) { + // doesn't apply return false; } - var oD, oDebug, oTarget, oToggle, tmp; - if (_s.debugMode && !_id(_s.debugID) && ((!_hasConsole || !_s.useConsole) || (_s.useConsole && _hasConsole && !_s.consoleOnly))) { - oD = _doc.createElement('div'); - oD.id = _s.debugID + '-toggle'; - oToggle = { - 'position': 'fixed', - 'bottom': '0px', - 'right': '0px', - 'width': '1.2em', - 'height': '1.2em', - 'lineHeight': '1.2em', - 'margin': '2px', - 'textAlign': 'center', - 'border': '1px solid #999', - 'cursor': 'pointer', - 'background': '#fff', - 'color': '#333', - 'zIndex': 10001 - }; - oD.appendChild(_doc.createTextNode('-')); - oD.onclick = _toggleDebug; - oD.title = 'Toggle SM2 debug console'; - if (_ua.match(/msie 6/i)) { - oD.style.position = 'absolute'; - oD.style.cursor = 'hand'; - } - for (tmp in oToggle) { - if (oToggle.hasOwnProperty(tmp)) { - oD.style[tmp] = oToggle[tmp]; - } - } - oDebug = _doc.createElement('div'); - oDebug.id = _s.debugID; - oDebug.style.display = (_s.debugMode?'block':'none'); - if (_s.debugMode && !_id(oD.id)) { - try { - oTarget = _getDocument(); - oTarget.appendChild(oD); - } catch(e2) { - throw new Error(_str('appXHTML')); + + var aF = _s.audioFormats, i, item; + + for (item in aF) { + if (aF.hasOwnProperty(item)) { + if (item === 'mp3' || item === 'mp4') { + _s._wD(_sm+': Using flash fallback for '+item+' format'); + _s.html5[item] = false; + // assign result to related formats, too + if (aF[item] && aF[item].related) { + for (i = aF[item].related.length; i--;) { + _s.html5[aF[item].related[i]] = false; + } + } } - oTarget.appendChild(oDebug); } } - oTarget = null; + + }; + + /** + * Pseudo-private flash/ExternalInterface methods + * ---------------------------------------------- + */ + + this._setSandboxType = function(sandboxType) { + + // + var sb = _s.sandbox; + + sb.type = sandboxType; + sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')]; + + _s._wD('Flash security sandbox type: ' + sb.type); + + if (sb.type === 'localWithFile') { + + sb.noRemote = true; + sb.noLocal = false; + _wDS('secNote', 2); + + } else if (sb.type === 'localWithNetwork') { + + sb.noRemote = false; + sb.noLocal = true; + + } else if (sb.type === 'localTrusted') { + + sb.noRemote = false; + sb.noLocal = false; + + } // - } - _createMovie = function(smID, smURL) { + }; - var specialCase = null, - remoteURL = (smURL?smURL:_s.url), - localURL = (_s.altURL?_s.altURL:remoteURL), - oEmbed, oMovie, oTarget = _getDocument(), tmp, movieHTML, oEl, extraClass = _getSWFCSS(), s, x, sClass, side = '100%', isRTL = null, html = _doc.getElementsByTagName('html')[0]; - isRTL = (html && html.dir && html.dir.match(/rtl/i)); - smID = (typeof smID === 'undefined'?_s.id:smID); + this._externalInterfaceOK = function(flashDate) { + + // flash callback confirming flash loaded, EI working etc. + // flashDate = approx. timing/delay info for JS/flash bridge + + if (_s.swfLoaded) { + return false; + } + + var eiTime = new Date().getTime(); + + _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':'')); + _debugTS('swf', true); + _debugTS('flashtojs', true); + _s.swfLoaded = true; + _tryInitOnFocus = false; + + if (_isBadSafari) { + _badSafariFix(); + } + + if (_isIE) { + // IE needs a timeout OR delay until window.onload - may need TODO: investigating + setTimeout(_init, 100); + } else { + _init(); + } + + }; + + /** + * Private initialization helpers + * ------------------------------ + */ + + _createMovie = function(smID, smURL) { if (_didAppend && _appendSuccess) { - return false; // ignore if already succeeded + // ignore if already succeeded + return false; } function _initMsg() { - _s._wD('-- SoundManager 2 ' + _s.version + (!_html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_html5Only ? (_s.useMovieStar?', MovieStar mode':'') + (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : (_s.useFastPolling?'fast':'normal')) + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1); + _s._wD('-- SoundManager 2 ' + _s.version + (!_s.html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_s.html5Only ? (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : 'normal') + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1); } - if (_html5Only) { + if (_s.html5Only) { + + // 100% HTML5 mode _setVersionInfo(); + _initMsg(); _s.oMC = _id(_s.movieID); _init(); + // prevent multiple init attempts _didAppend = true; + _appendSuccess = true; + return false; + } - _didAppend = true; + // flash path + var remoteURL = (smURL || _s.url), + localURL = (_s.altURL || remoteURL), + swfTitle = 'JS/Flash audio component (SoundManager 2)', + oEmbed, oMovie, oTarget = _getDocument(), tmp, movieHTML, oEl, extraClass = _getSWFCSS(), + s, x, sClass, side = 'auto', isRTL = null, + html = _doc.getElementsByTagName('html')[0]; + + isRTL = (html && html.dir && html.dir.match(/rtl/i)); + smID = (typeof smID === 'undefined'?_s.id:smID); + + function param(name, value) { + return ''; + } // safety check for legacy (change to Flash 9 URL) _setVersionInfo(); - _s.url = _normalizeMovieURL(_s._overHTTP?remoteURL:localURL); + _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); smURL = _s.url; - _s.wmode = (!_s.wmode && _s.useHighPerformance && !_s.useMovieStar?'transparent':_s.wmode); + _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { + /** + * extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here + * does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout + * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?) + */ _s.specialWmodeCase = true; - // extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here - // does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout - // wmode breaks IE 8 on Vista + Win7 too in some cases, as of Jan.2011 (?) _wDS('spcWmode'); _s.wmode = null; } @@ -2268,10 +3953,12 @@ function SoundManager(smURL, smID) { 'quality': 'high', 'allowScriptAccess': _s.allowScriptAccess, 'bgcolor': _s.bgColor, - 'pluginspage': _s._http+'//www.macromedia.com/go/getflashplayer', + 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', + 'title': swfTitle, 'type': 'application/x-shockwave-flash', 'wmode': _s.wmode, - 'hasPriority': 'true' // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html + // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html + 'hasPriority': 'true' }; if (_s.debugFlash) { @@ -2279,20 +3966,35 @@ function SoundManager(smURL, smID) { } if (!_s.wmode) { - delete oEmbed.wmode; // don't write empty attribute + // don't write empty attribute + delete oEmbed.wmode; } if (_isIE) { + // IE is "special". oMovie = _doc.createElement('div'); - movieHTML = '' + (_s.wmode?' ':'') + '' + (_s.debugFlash?'':'') + ''; + movieHTML = [ + '', + param('movie', smURL), + param('AllowScriptAccess', _s.allowScriptAccess), + param('quality', oEmbed.quality), + (_s.wmode? param('wmode', _s.wmode): ''), + param('bgcolor', _s.bgColor), + param('hasPriority', 'true'), + (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), + '' + ].join(''); + } else { + oMovie = _doc.createElement('embed'); for (tmp in oEmbed) { if (oEmbed.hasOwnProperty(tmp)) { oMovie.setAttribute(tmp, oEmbed[tmp]); } } + } _initDebug(); @@ -2300,15 +4002,19 @@ function SoundManager(smURL, smID) { oTarget = _getDocument(); if (oTarget) { - _s.oMC = _id(_s.movieID)?_id(_s.movieID):_doc.createElement('div'); + + _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); + if (!_s.oMC.id) { + _s.oMC.id = _s.movieID; _s.oMC.className = _s.swfCSS.swfDefault + ' ' + extraClass; - // "hide" flash movie s = null; oEl = null; + if (!_s.useFlashBlock) { if (_s.useHighPerformance) { + // on-screen at all times s = { 'position': 'fixed', 'width': '8px', @@ -2319,6 +4025,7 @@ function SoundManager(smURL, smID) { 'overflow': 'hidden' }; } else { + // hide off-screen, lower priority s = { 'position': 'absolute', 'width': '6px', @@ -2331,9 +4038,12 @@ function SoundManager(smURL, smID) { } } } + if (_isWebkit) { - _s.oMC.style.zIndex = 10000; // soundcloud-reported render/crash fix, safari 5 + // soundcloud-reported render/crash fix, safari 5 + _s.oMC.style.zIndex = 10000; } + if (!_s.debugFlash) { for (x in s) { if (s.hasOwnProperty(x)) { @@ -2341,6 +4051,7 @@ function SoundManager(smURL, smID) { } } } + try { if (!_isIE) { _s.oMC.appendChild(oMovie); @@ -2353,10 +4064,12 @@ function SoundManager(smURL, smID) { } _appendSuccess = true; } catch(e) { - throw new Error(_str('appXHTML')); + throw new Error(_str('domError')+' \n'+e.toString()); } + } else { - // it's already in the document. + + // SM2 container is already in the document (eg. flashblock use case) sClass = _s.oMC.className; _s.oMC.className = (sClass?sClass+' ':_s.swfCSS.swfDefault) + (extraClass?' '+extraClass:''); _s.oMC.appendChild(oMovie); @@ -2366,31 +4079,35 @@ function SoundManager(smURL, smID) { oEl.innerHTML = movieHTML; } _appendSuccess = true; + } - } - if (specialCase) { - _s._wD(specialCase); } + _didAppend = true; _initMsg(); - _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_s._overHTTP && _s.altURL?' (alternate URL)':''), 1); + _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_overHTTP && _s.altURL?' (alternate URL)':''), 1); return true; - }; - _idCheck = this.getSoundById; + }; _initMovie = function() { - if (_html5Only) { + + if (_s.html5Only) { _createMovie(); return false; } + // attempt to get, or create, movie + // may already exist if (_s.o) { - return false; // may already exist + return false; } - _s.o = _s.getMovie(_s.id); // inline markup + + // inline markup case + _s.o = _s.getMovie(_s.id); + if (!_s.o) { if (!_oRemoved) { // try to create @@ -2407,48 +4124,56 @@ function SoundManager(smURL, smID) { } _s.o = _s.getMovie(_s.id); } + + // if (_s.o) { - _s._wD(_smc+'initMovie(): Got '+_s.o.nodeName+' element ('+(_didAppend?'created via JS':'static HTML')+')'); _wDS('waitEI'); } + // + if (_s.oninitmovie instanceof Function) { setTimeout(_s.oninitmovie, 1); } + return true; - }; - _go = function(sURL) { - // where it all begins. - if (sURL) { - _s.url = sURL; - } - _initMovie(); }; _delayWaitForEI = function() { - setTimeout(_waitForEI, 500); + + setTimeout(_waitForEI, 1000); + }; _waitForEI = function() { + if (_waitingForEI) { return false; } + _waitingForEI = true; _event.remove(_win, 'load', _delayWaitForEI); + if (_tryInitOnFocus && !_isFocused) { + // giant Safari 3.1 hack - assume mousemove = focus given lack of focus event _wDS('waitFocus'); return false; } + var p; if (!_didInit) { p = _s.getMoviePercent(); _s._wD(_str('waitImpatient', (p === 100?' (SWF loaded)':(p > 0?' (SWF ' + p + '% loaded)':'')))); } + setTimeout(function() { + p = _s.getMoviePercent(); + + // if (!_didInit) { _s._wD(_sm + ': No Flash response within expected time.\nLikely causes: ' + (p === 0?'Loading ' + _s.movieURL + ' may have failed (and/or Flash ' + _fV + '+ not present?), ':'') + 'Flash blocked or JS-Flash security error.' + (_s.debugFlash?' ' + _str('checkSWF'):''), 2); - if (!_s._overHTTP && p) { + if (!_overHTTP && p) { _wDS('localFail', 2); if (!_s.debugFlash) { _wDS('tryDebug', 2); @@ -2458,9 +4183,12 @@ function SoundManager(smURL, smID) { // if 0 (not null), probably a 404. _s._wD(_str('swf404', _s.url)); } - _debugTS('flashtojs', false, ': Timed out' + _s._overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'); + _debugTS('flashtojs', false, ': Timed out' + _overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'); } + // + // give up / time-out, depending + if (!_didInit && _okToDisable) { if (p === null) { // SWF failed. Maybe blocked. @@ -2482,316 +4210,116 @@ function SoundManager(smURL, smID) { } } } - }, _s.flashLoadTimeout); - }; - - _go = function(sURL) { - // where it all begins. - if (sURL) { - _s.url = sURL; - } - _initMovie(); - }; - - // - _wDS = function(o, errorLevel) { - if (!o) { - return ''; - } else { - return _s._wD(_str(o), errorLevel); - } - }; - - if (_wl.indexOf('debug=alert') + 1 && _s.debugMode) { - _s._wD = function(sText) {window.alert(sText);}; - } - - _toggleDebug = function() { - var o = _id(_s.debugID), - oT = _id(_s.debugID + '-toggle'); - if (!o) { - return false; - } - if (_debugOpen) { - // minimize - oT.innerHTML = '+'; - o.style.display = 'none'; - } else { - oT.innerHTML = '-'; - o.style.display = 'block'; - } - _debugOpen = !_debugOpen; - }; - - _debugTS = function(sEventType, bSuccess, sMessage) { - // troubleshooter debug hooks - if (typeof sm2Debugger !== 'undefined') { - try { - sm2Debugger.handleEvent(sEventType, bSuccess, sMessage); - } catch(e) { - // oh well - } - } - return true; - }; - // - - _getSWFCSS = function() { - var css = []; - if (_s.debugMode) { - css.push(_s.swfCSS.sm2Debug); - } - if (_s.debugFlash) { - css.push(_s.swfCSS.flashDebug); - } - if (_s.useHighPerformance) { - css.push(_s.swfCSS.highPerf); - } - return css.join(' '); - }; - - _flashBlockHandler = function() { - // *possible* flash block situation. - var name = _str('fbHandler'), p = _s.getMoviePercent(), css = _s.swfCSS; - if (!_s.ok()) { - if (_needsFlash) { - // make the movie more visible, so user can fix - _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); - _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':'')); - } - _s.didFlashBlock = true; - _processOnEvents({type:'ontimeout',ignoreInit:true}); // fire onready(), complain lightly - if (_s.onerror instanceof Function) { - _s.onerror.apply(_win); - } - } else { - // SM2 loaded OK (or recovered) - if (_s.didFlashBlock) { - _s._wD(name+': Unblocked'); - } - if (_s.oMC) { - _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); - } - } - }; - - _handleFocus = function() { - function cleanup() { - _event.remove(_win, 'focus', _handleFocus); - _event.remove(_win, 'load', _handleFocus); - } - if (_isFocused || !_tryInitOnFocus) { - cleanup(); - return true; - } - _okToDisable = true; - _isFocused = true; - _s._wD(_smc+'handleFocus()'); - if (_isSafari && _tryInitOnFocus) { - // giant Safari 3.1 hack - assume mousemove = focus given lack of focus event - _event.remove(_win, 'mousemove', _handleFocus); - } - // allow init to restart - _waitingForEI = false; - cleanup(); - return true; - }; - - _initComplete = function(bNoDisable) { - if (_didInit) { - return false; - } - if (_html5Only) { - // all good. - _s._wD('-- SoundManager 2: loaded --'); - _didInit = true; - _processOnEvents(); - _initUserOnload(); - return true; - } - var sClass = _s.oMC.className, - wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()); - if (!wasTimeout) { - _didInit = true; - } - _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'security/load error':'OK') + ') --', 1); - if (_disabled || bNoDisable) { - if (_s.useFlashBlock) { - _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_s.swfCSS.swfTimedout:_s.swfCSS.swfError); - } - _processOnEvents({type:'ontimeout'}); - _debugTS('onload', false); - if (_s.onerror instanceof Function) { - _s.onerror.apply(_win); - } - return false; - } else { - _debugTS('onload', true); - } - _event.add(_win, 'unload', _doNothing); // prevent browser from showing cached state via back button, because flash will be dead - if (_s.waitForWindowLoad && !_windowLoaded) { - _wDS('waitOnload'); - _event.add(_win, 'load', _initUserOnload); - return false; - } else { - if (_s.waitForWindowLoad && _windowLoaded) { - _wDS('docLoaded'); - } - _initUserOnload(); - } - return true; - }; - - _addOnEvent = function(sType, oMethod, oScope) { - if (typeof _on_queue[sType] === 'undefined') { - _on_queue[sType] = []; - } - _on_queue[sType].push({ - 'method': oMethod, - 'scope': (oScope || null), - 'fired': false - }); - }; - - _processOnEvents = function(oOptions) { - if (!oOptions) { // assume onready, if unspecified - oOptions = { - type: 'onready' - }; - } - if (!_didInit && oOptions && !oOptions.ignoreInit) { - // not ready yet. - return false; - } - var status = { - success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) - }, - srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), // queue specified by type, or none - queue = [], i, j, - canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); - for (i = 0; i < srcQueue.length; i++) { - if (srcQueue[i].fired !== true) { - queue.push(srcQueue[i]); - } - } - if (queue.length) { - _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s')); - for (i = 0, j = queue.length; i < j; i++) { - if (queue[i].scope) { - queue[i].method.apply(queue[i].scope, [status]); - } else { - queue[i].method(status); - } - if (!canRetry) { // flashblock case doesn't count here - queue[i].fired = true; - } - } - } - return true; - }; - - _initUserOnload = function() { - _win.setTimeout(function() { - if (_s.useFlashBlock) { - _flashBlockHandler(); - } - _processOnEvents(); - // call user-defined "onload", scoped to window - if (_s.onload instanceof Function) { - _wDS('onload', 1); - _s.onload.apply(_win); - _wDS('onloadOK', 1); - } - if (_s.waitForWindowLoad) { - _event.add(_win, 'load', _initUserOnload); - } - },1); + + }, _s.flashLoadTimeout); + }; - _detectFlash = function() { + _handleFocus = function() { - // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt + function cleanup() { + _event.remove(_win, 'focus', _handleFocus); + _event.remove(_win, 'load', _handleFocus); + } - if (_hasFlash !== undefined) { - // this work has already been done. - return _hasFlash; + if (_isFocused || !_tryInitOnFocus) { + cleanup(); + return true; } - var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; + _okToDisable = true; + _isFocused = true; + _s._wD(_smc+'handleFocus()'); - if (nP && nP.length) { + if (_isSafari && _tryInitOnFocus) { + _event.remove(_win, 'mousemove', _handleFocus); + } - type = 'application/x-shockwave-flash'; - types = n.mimeTypes; - if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { - hasPlugin = true; - } + // allow init to restart + _waitingForEI = false; - } else if (typeof AX !== 'undefined') { + cleanup(); + return true; - try { - obj = new AX('ShockwaveFlash.ShockwaveFlash'); - } catch(e) { - // oh well - } - hasPlugin = (!!obj); + }; - } + _showSupport = function() { - _hasFlash = hasPlugin; + var item, tests = []; - return hasPlugin; + if (_s.useHTML5Audio && _s.hasHTML5) { + for (item in _s.audioFormats) { + if (_s.audioFormats.hasOwnProperty(item)) { + tests.push(item + ': ' + _s.html5[item] + (!_s.html5[item] && _hasFlash && _s.flash[item] ? ' (using flash)' : (_s.preferFlash && _s.flash[item] && _hasFlash ? ' (preferring flash)': (!_s.html5[item] ? ' (' + (_s.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : '')))); + } + } + _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1); + } }; - _featureCheck = function() { - var needsFlash, item, - isSpecial = (_ua.match(/iphone os (1|2|3_0|3_1)/i)?true:false); // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (iPad) + iOS4 works. - if (isSpecial) { - _s.hasHTML5 = false; // has Audio(), but is broken; let it load links directly. - _html5Only = true; // ignore flash case, however - if (_s.oMC) { - _s.oMC.style.display = 'none'; - } + _initComplete = function(bNoDisable) { + + if (_didInit) { return false; } - if (_s.useHTML5Audio) { - if (!_s.html5 || !_s.html5.canPlayType) { - _s._wD('SoundManager: No HTML5 Audio() support detected.'); - _s.hasHTML5 = false; - return true; - } else { - _s.hasHTML5 = true; + + if (_s.html5Only) { + // all good. + _s._wD('-- SoundManager 2: loaded --'); + _didInit = true; + _initUserOnload(); + _debugTS('onload', true); + return true; + } + + var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), + error; + + if (!wasTimeout) { + _didInit = true; + if (_disabled) { + error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; } - if (_isBadSafari) { - _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1); - if (_detectFlash()) { - return true; - } + } + + _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'security/load error':'OK') + ') --', 1); + + if (_disabled || bNoDisable) { + if (_s.useFlashBlock && _s.oMC) { + _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_s.swfCSS.swfTimedout:_s.swfCSS.swfError); } + _processOnEvents({type:'ontimeout', error:error}); + _debugTS('onload', false); + _catchError(error); + return false; } else { - // flash required. - return true; + _debugTS('onload', true); } - for (item in _s.audioFormats) { - if (_s.audioFormats.hasOwnProperty(item) && _s.audioFormats[item].required && !_s.html5.canPlayType(_s.audioFormats[item].type)) { - // may need flash for this format? - needsFlash = true; + + if (_s.waitForWindowLoad && !_windowLoaded) { + _wDS('waitOnload'); + _event.add(_win, 'load', _initUserOnload); + return false; + } else { + // + if (_s.waitForWindowLoad && _windowLoaded) { + _wDS('docLoaded'); } + // + _initUserOnload(); } - // sanity check.. - if (_s.ignoreFlash) { - needsFlash = false; - } - _html5Only = (_s.useHTML5Audio && _s.hasHTML5 && !needsFlash && !_s.requireFlash); - return (_detectFlash() && needsFlash); + + return true; + }; _init = function() { - var item, tests = []; + _wDS('init'); // called after onload() + if (_didInit) { _wDS('didInit'); return false; @@ -2801,16 +4329,7 @@ function SoundManager(smURL, smID) { _event.remove(_win, 'load', _s.beginDelayedInit); } - if (_s.hasHTML5) { - for (item in _s.audioFormats) { - if (_s.audioFormats.hasOwnProperty(item)) { - tests.push(item+': '+_s.html5[item]); - } - } - _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1); - } - - if (_html5Only) { + if (_s.html5Only) { if (!_didInit) { // we don't need no steenking flash! _cleanup(); @@ -2822,194 +4341,180 @@ function SoundManager(smURL, smID) { // flash path _initMovie(); + try { + _wDS('flashJS'); - _s.o._externalInterfaceTest(false); // attempt to talk to Flash - if (!_s.allowPolling) { - _wDS('noPolling', 1); - } else { - _setPolling(true, _s.flashPollingInterval ? _s.flashPollingInterval : (_s.useFastPolling ? 10 : 50)); - } + + // attempt to talk to Flash + _s.o._externalInterfaceTest(false); + + // apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling + // (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates) + _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); + if (!_s.debugMode) { + // stop the SWF from making debug output calls to JS _s.o._disableDebug(); } + _s.enabled = true; _debugTS('jstoflash', true); + + if (!_s.html5Only) { + // prevent browser from showing cached page state (or rather, restoring "suspended" page state) via back button, because flash may be dead + // http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/ + _event.add(_win, 'unload', _doNothing); + } + } catch(e) { + _s._wD('js/flash exception: ' + e.toString()); _debugTS('jstoflash', false); - _failSafely(true); // don't disable, for reboot() + _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); + // don't disable, for reboot() + _failSafely(true); _initComplete(); + return false; + } + _initComplete(); - // event cleanup + + // disconnect events _cleanup(); - return true; - }; - _beginInit = function() { - if (_initPending) { - return false; - } - _createMovie(); - _initMovie(); - _initPending = true; return true; + }; - _dcLoaded = function() { + _domContentLoaded = function() { + if (_didDCLoaded) { return false; } + _didDCLoaded = true; _initDebug(); - if (!_s.useHTML5Audio) { - if (!_detectFlash()) { - _s._wD('SoundManager: No Flash detected, trying HTML5'); - _s.useHTML5Audio = true; - } - } - _testHTML5(); - _s.html5.usingFlash = _featureCheck(); - _needsFlash = _s.html5.usingFlash; - _didDCLoaded = true; - if (_doc.removeEventListener) { - _doc.removeEventListener('DOMContentLoaded', _dcLoaded, false); - } - _go(); - return true; - }; - - _startTimer = function(oSound) { - if (!oSound._hasTimer) { - oSound._hasTimer = true; - } - }; - _stopTimer = function(oSound) { - if (oSound._hasTimer) { - oSound._hasTimer = false; - } - }; + /** + * Temporary feature: allow force of HTML5 via URL params: sm2-usehtml5audio=0 or 1 + * Ditto for sm2-preferFlash, too. + */ + // + (function(){ - _die = function() { - if (_s.onerror instanceof Function) { - _s.onerror(); - } - _s.disable(); - }; + var a = 'sm2-usehtml5audio=', l = _wl.toLowerCase(), b = null, + a2 = 'sm2-preferflash=', b2 = null, hasCon = (typeof console !== 'undefined' && typeof console.log !== 'undefined'); - _badSafariFix = function() { - // special case: "bad" Safari can fall back to flash for MP3/MP4 - if (!_isBadSafari || !_detectFlash()) { - return false; // doesn't apply - } - var aF = _s.audioFormats, i, item; - for (item in aF) { - if (aF.hasOwnProperty(item)) { - // special case: "bad" Safari can fall back to flash for MP3/MP4 - if (item === 'mp3' || item === 'mp4') { - _s._wD(_sm+': Using flash fallback for '+item+' format'); - _s.html5[item] = false; - // assign result to related formats, too - if (aF[item] && aF[item].related) { - for (i = aF[item].related.length; i--;) { - _s.html5[aF[item].related[i]] = false; - } - } + if (l.indexOf(a) !== -1) { + b = (l.charAt(l.indexOf(a)+a.length) === '1'); + if (hasCon) { + console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter'); } + _s.useHTML5Audio = b; } - } - }; - // pseudo-private methods called by Flash + if (l.indexOf(a2) !== -1) { + b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1'); + if (hasCon) { + console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter'); + } + _s.preferFlash = b2; + } - this._setSandboxType = function(sandboxType) { - // - var sb = _s.sandbox; - sb.type = sandboxType; - sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')]; - _s._wD('Flash security sandbox type: ' + sb.type); - if (sb.type === 'localWithFile') { - sb.noRemote = true; - sb.noLocal = false; - _wDS('secNote', 2); - } else if (sb.type === 'localWithNetwork') { - sb.noRemote = false; - sb.noLocal = true; - } else if (sb.type === 'localTrusted') { - sb.noRemote = false; - sb.noLocal = false; - } + }()); // - }; - this._externalInterfaceOK = function(flashDate) { - // flash callback confirming flash loaded, EI working etc. - // flashDate = approx. timing/delay info for JS/flash bridge - if (_s.swfLoaded) { - return false; + if (!_hasFlash && _s.hasHTML5) { + _s._wD('SoundManager: No Flash detected'+(!_s.useHTML5Audio?', enabling HTML5.':'. Trying HTML5-only mode.')); + _s.useHTML5Audio = true; + // make sure we aren't preferring flash, either + // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak. + _s.preferFlash = false; } - var eiTime = new Date().getTime(); - _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':'')); - _debugTS('swf', true); - _debugTS('flashtojs', true); - _s.swfLoaded = true; - _tryInitOnFocus = false; - if (_isBadSafari) { - _badSafariFix(); + + _testHTML5(); + _s.html5.usingFlash = _featureCheck(); + _needsFlash = _s.html5.usingFlash; + _showSupport(); + + if (!_hasFlash && _needsFlash) { + _s._wD('SoundManager: Fatal error: Flash is needed to play some required formats, but is not available.'); + // TODO: Fatal here vs. timeout approach, etc. + // hack: fail sooner. + _s.flashLoadTimeout = 1; } - if (_isIE) { - // IE needs a timeout OR delay until window.onload - may need TODO: investigating - setTimeout(_init, 100); - } else { - _init(); + + if (_doc.removeEventListener) { + _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); } + + _initMovie(); + return true; + }; - _dcIE = function() { + _domContentLoadedIE = function() { + if (_doc.readyState === 'complete') { - _dcLoaded(); - _doc.detachEvent('onreadystatechange', _dcIE); + _domContentLoaded(); + _doc.detachEvent('onreadystatechange', _domContentLoadedIE); } + return true; + }; - // focus and window load, init - if (!_s.hasHTML5 || _needsFlash) { - // only applies to Flash mode - _event.add(_win, 'focus', _handleFocus); - _event.add(_win, 'load', _handleFocus); - _event.add(_win, 'load', _delayWaitForEI); - if (_isSafari && _tryInitOnFocus) { - _event.add(_win, 'mousemove', _handleFocus); // massive Safari focus hack - } + // sniff up-front + _detectFlash(); + + // focus and window load, init (primarily flash-driven) + _event.add(_win, 'focus', _handleFocus); + _event.add(_win, 'load', _handleFocus); + _event.add(_win, 'load', _delayWaitForEI); + + if (_isSafari && _tryInitOnFocus) { + // massive Safari 3.1 focus detection hack + _event.add(_win, 'mousemove', _handleFocus); } if (_doc.addEventListener) { - _doc.addEventListener('DOMContentLoaded', _dcLoaded, false); + + _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); + } else if (_doc.attachEvent) { - _doc.attachEvent('onreadystatechange', _dcIE); + + _doc.attachEvent('onreadystatechange', _domContentLoadedIE); + } else { + // no add/attachevent support - safe to assume no JS -> Flash either _debugTS('onload', false); - _die(); + _catchError({type:'NO_DOM2_EVENTS', fatal:true}); + } if (_doc.readyState === 'complete') { - setTimeout(_dcLoaded,100); + // DOMReady has already happened. + setTimeout(_domContentLoaded,100); } } // SoundManager() // SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading + if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { soundManager = new SoundManager(); } -// public interfaces +/** + * SoundManager public interfaces + * ------------------------------ + */ + window.SoundManager = SoundManager; // constructor -window.soundManager = soundManager; // public API, flash callbacks etc +window.soundManager = soundManager; // public API, flash callbacks etc. -}(window)); +}(window)); \ No newline at end of file diff --git a/telemeta/htdocs/timeside/js/player.js b/telemeta/htdocs/timeside/js/player.js index 6560d50f..cdc7f065 100644 --- a/telemeta/htdocs/timeside/js/player.js +++ b/telemeta/htdocs/timeside/js/player.js @@ -1007,7 +1007,6 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ // map.clear(); // ruler.clear(); - var rulerAdd = ruler.add; if(markers){ @@ -1022,8 +1021,6 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ }); } - - //the function above calls map.add: //add bindings when adding a marker: map.bind('add',function(data){ @@ -1054,7 +1051,6 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ player.fire('markerMoved',data); }); - //remove map.bind('remove',function(data){ ruler.remove.apply(ruler, [data.index]); @@ -1066,7 +1062,5 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ ruler.setEditable.apply(ruler, [data.index, data.value]); player.fire('markerEditStateChanged',data); }); - } - -}); \ No newline at end of file +}); diff --git a/telemeta/htdocs/timeside/js/timeside.js b/telemeta/htdocs/timeside/js/timeside.js index 3d49f47f..646d8c77 100644 --- a/telemeta/htdocs/timeside/js/timeside.js +++ b/telemeta/htdocs/timeside/js/timeside.js @@ -786,4 +786,4 @@ Timeside.utils.loadScripts = function(scriptsOptionalRoot,scriptArray, optionalO }); } } -}; \ No newline at end of file +}; diff --git a/telemeta/templates/telemeta_default/mediaitem_detail.html b/telemeta/templates/telemeta_default/mediaitem_detail.html index 628cf18d..9e926ac9 100644 --- a/telemeta/templates/telemeta_default/mediaitem_detail.html +++ b/telemeta/templates/telemeta_default/mediaitem_detail.html @@ -34,11 +34,13 @@ {% if item.file %} {% if public_access or perms.telemeta.can_play_all_items %} //initializing soundManager default properties - soundManager.url = "{% url telemeta-timeside "swf/" %}"; soundManager.flashVersion = 9; - soundManager.useMovieStar = true; // enable MP4/M4A/AAC + soundManager.url = "{% url telemeta-timeside "swf/" %}"; soundManager.debugMode = false; soundManager.allowPolling = true; + soundManager.useHTML5Audio = true; + soundManager.preferFlash = false; + //initializing the visualizers to be passed to the player var visualizers = {}; {% for v in visualizers %} -- 2.39.5