/*! SoundManager 2: Javascript Sound for the Web -------------------------------------------- http://schillmania.com/projects/soundmanager2/ Copyright (c) 2008, Scott Schiller. All rights reserved. Code licensed under the BSD License: http://schillmania.com/projects/soundmanager2/license.txt V2.95a.20090501 */ var soundManager = null; function SoundManager(smURL,smID) { this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9. this.debugMode = false; // enable debugging output (div#soundmanager-debug, OR console if available + configured) // eyeOS 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 = 'index.php?version=' + EXTERN_CACHE_VERSION + '&extern=libs/eyeSound/null.mp3'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only) // eyeOS this.allowPolling = true; // allow flash to poll for status update (required for "while playing", peak, sound spectrum functions to work.) this.useMovieStar = false; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio + video formats (AAC, M4V, FLV, MOV etc.) this.bgColor = '#ffffff'; // movie (.swf) background color, '#000000' useful if showing on-screen/full-screen video etc. this.useHighPerformance = false; // position:fixed flash movie gives increased js/flash speed this.flashLoadTimeout = 750; // ms to wait for flash movie to load before failing (0 = infinity) this.wmode = 'transparent'; // mode to render the flash movie in - null, transparent, opaque (last two allow layering of HTML on top) // eyeOS this.allowFullScreen = true; // enter full-screen (via double-click on movie) for flash 9+ video 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) '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" '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 'position': null, // offset (milliseconds) to seek to within loaded sound data. 'pan': 0, // "pan" settings, left-to-right, -100 to 100 'volume': 50 // self-explanatory. 0-100, the latter being the max. // eyeOS }; this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used 'isMovieStar': null, // "MovieStar" MPEG4 audio/video 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. '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/video options, merged into defaultOptions if flash 9 + movieStar mode is enabled 'onmetadata': null, // callback for when video width/height etc. are received 'useVideo': false, // if loading movieStar content, whether to show video 'bufferTime': null // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try up to 3 seconds) }; // jslint global declarations /*global SM2_DEFER, sm2Debugger, alert, console, document, navigator, setTimeout, window */ var SMSound = null; // defined later var _s = this; this.version = null; this.versionNumber = 'V2.95a.20090501'; this.movieURL = null; this.url = null; this.altURL = null; this.swfLoaded = false; this.enabled = false; this.o = null; this.id = (smID||'sm2movie'); this.oMC = null; this.sounds = {}; this.soundIDs = []; this.muted = false; this.isFullScreen = false; // set later by flash 9+ this.isIE = (navigator.userAgent.match(/MSIE/i)); this.isSafari = (navigator.userAgent.match(/safari/i)); this.isGecko = (navigator.userAgent.match(/gecko/i)); this.debugID = 'soundmanager-debug'; this.specialWmodeCase = false; this._debugOpen = true; this._didAppend = false; this._appendSuccess = false; this._didInit = false; this._disabled = false; this._windowLoaded = false; this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined'); this._debugLevels = ['log','info','warn','error']; this._defaultFlashVersion = 8; this._oRemoved = null; this._oRemovedHTML = null; var _$ = function(sID) { return document.getElementById(sID); }; this.filePatterns = { flash8: /\.mp3(\?.*)?$/i, flash9: /\.mp3(\?.*)?$/i }; 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.filePattern = null; 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 }; this._setVersionInfo = function() { if (_s.flashVersion != 8 && _s.flashVersion != 9) { //alert('soundManager.flashVersion must be 8 or 9. "'+_s.flashVersion+'" is invalid. Reverting to '+_s._defaultFlashVersion+'.'); // eyeOS _s.flashVersion = _s._defaultFlashVersion; } _s.version = _s.versionNumber+(_s.flashVersion==9?' (AS3/Flash 9)':' (AS2/Flash 8)'); // set up default options if (_s.flashVersion > 8) { _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.flash9Options); _s.features.buffering = true; } if (_s.flashVersion > 8 && _s.useMovieStar) { // flash 9+ support for movieStar formats as well as MP3 _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.movieStarOptions); _s.filePatterns.flash9 = new RegExp('\\.(mp3|'+_s.netStreamTypes.join('|')+')(\\?.*)?$','i'); _s.features.movieStar = true; } else { _s.useMovieStar = false; _s.features.movieStar = false; } _s.filePattern = _s.filePatterns[(_s.flashVersion!=8?'flash9':'flash8')]; _s.movieURL = (_s.flashVersion==8?'soundmanager2.swf':'soundmanager2_flash9.swf'); _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_s.flashVersion>8); }; this._overHTTP = (document.location?document.location.protocol.match(/http/i):null); this._waitingforEI = false; this._initPending = false; this._tryInitOnFocus = (this.isSafari && typeof document.hasFocus == 'undefined'); this._isFocused = (typeof document.hasFocus != 'undefined'?document.hasFocus():null); this._okToDisable = !this._tryInitOnFocus; this.useAltURL = !this._overHTTP; // use altURL if not "online" var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html'; this.strings = { notReady: 'Not loaded yet - wait for soundManager.onload() before calling sound-related methods', appXHTML: 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.' }; // --- public methods --- this.supported = function() { return (_s._didInit && !_s._disabled); }; this.getMovie = function(smID) { return _s.isIE?window[smID]:(_s.isSafari?_$(smID)||document[smID]:_$(smID)); }; this.loadFromXML = function(sXmlUrl) { try { _s.o._loadFromXML(sXmlUrl); } catch(e) { _s._failSafely(); return true; } }; this.createSound = function(oOptions) { if (!_s._didInit) { throw _s._complain('soundManager.createSound(): '+_s.strings.notReady,arguments.callee.caller); } if (arguments.length == 2) { // function overloading in JS! :) ..assume simple createSound(id,url) use case oOptions = {'id':arguments[0],'url':arguments[1]}; } var thisOptions = _s._mergeObjects(oOptions); // inherit SM2 defaults var _tO = thisOptions; // alias _s._wD('soundManager.createSound(): '+_tO.id+' ('+_tO.url+')',1); if (_s._idCheck(_tO.id,true)) { _s._wD('soundManager.createSound(): '+_tO.id+' exists',1); return _s.sounds[_tO.id]; } if (_s.flashVersion > 8 && _s.useMovieStar) { if (_tO.isMovieStar === null) { _tO.isMovieStar = (_tO.url.match(_s.netStreamPattern)?true:false); } if (_tO.isMovieStar) { _s._wD('soundManager.createSound(): using MovieStar handling'); } if (_tO.isMovieStar && (_tO.usePeakData || _tO.useWaveformData || _tO.useEQData)) { _s._wD('Warning: peak/waveform/eqData features unsupported for non-MP3 formats'); _tO.usePeakData = false; _tO.useWaveformData = false; _tO.useEQData = false; } } _s.sounds[_tO.id] = new SMSound(_tO); _s.soundIDs[_s.soundIDs.length] = _tO.id; // AS2: if (_s.flashVersion == 8) { _s.o._createSound(_tO.id,_tO.onjustbeforefinishtime); } else { _s.o._createSound(_tO.id,_tO.url,_tO.onjustbeforefinishtime,_tO.usePeakData,_tO.useWaveformData,_tO.useEQData,_tO.isMovieStar,(_tO.isMovieStar?_tO.useVideo:false),(_tO.isMovieStar?_tO.bufferTime:false)); } if (_tO.autoLoad || _tO.autoPlay) { // TODO: does removing timeout here cause problems? if (_s.sounds[_tO.id]) { _s.sounds[_tO.id].load(_tO); } } if (_tO.autoPlay) { _s.sounds[_tO.id].play(); } return _s.sounds[_tO.id]; }; this.createVideo = function(oOptions) { if (arguments.length==2) { oOptions = {'id':arguments[0],'url':arguments[1]}; } if (_s.flashVersion >= 9) { oOptions.isMovieStar = true; oOptions.useVideo = true; } else { _s._wD('soundManager.createVideo(): flash 9 required for video. Exiting.',2); return false; } if (!_s.useMovieStar) { _s._wD('soundManager.createVideo(): MovieStar mode not enabled. Exiting.',2); } return _s.createSound(oOptions); }; this.destroySound = function(sID,bFromSound) { // explicitly destroy a sound before normal page unload, etc. if (!_s._idCheck(sID)) { return false; } for (var i=0; i<_s.soundIDs.length; i++) { if (_s.soundIDs[i] == sID) { _s.soundIDs.splice(i,1); continue; } } // conservative option: avoid crash with ze flash 8 // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP + flash 8?? // if (_s.flashVersion != 8) { _s.sounds[sID].unload(); // } if (!bFromSound) { // ignore if being called from SMSound instance _s.sounds[sID].destruct(); } delete _s.sounds[sID]; }; this.destroyVideo = this.destroySound; this.load = function(sID,oOptions) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].load(oOptions); }; this.unload = function(sID) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].unload(); }; this.play = function(sID,oOptions) { if (!_s._didInit) { throw _s._complain('soundManager.play(): '+_s.strings.notReady,arguments.callee.caller); } if (!_s._idCheck(sID)) { if (typeof oOptions != 'Object') { oOptions = {url:oOptions}; // overloading use case: play('mySound','/path/to/some.mp3'); } if (oOptions && oOptions.url) { // overloading use case, creation + playing of sound: .play('someID',{url:'/path/to.mp3'}); _s._wD('soundController.play(): attempting to create "'+sID+'"',1); oOptions.id = sID; _s.createSound(oOptions); } else { return false; } } _s.sounds[sID].play(oOptions); }; this.start = this.play; // just for convenience this.setPosition = function(sID,nMsecOffset) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].setPosition(nMsecOffset); }; this.stop = function(sID) { if (!_s._idCheck(sID)) { return false; } _s._wD('soundManager.stop('+sID+')',1); _s.sounds[sID].stop(); }; this.stopAll = function() { _s._wD('soundManager.stopAll()',1); for (var oSound in _s.sounds) { if (_s.sounds[oSound] instanceof SMSound) { _s.sounds[oSound].stop(); // apply only to sound objects } } }; this.pause = function(sID) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].pause(); }; this.pauseAll = function() { for (var i=_s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].pause(); } }; this.resume = function(sID) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].resume(); }; this.resumeAll = function() { for (var i=_s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].resume(); } }; this.togglePause = function(sID) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].togglePause(); }; this.setPan = function(sID,nPan) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].setPan(nPan); }; this.setVolume = function(sID,nVol) { if (!_s._idCheck(sID)) { return false; } _s.sounds[sID].setVolume(nVol); }; this.mute = function(sID) { if (typeof sID != 'string') { sID = null; } if (!sID) { _s._wD('soundManager.mute(): Muting all sounds'); for (var i=_s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].mute(); } _s.muted = true; } else { if (!_s._idCheck(sID)) { return false; } _s._wD('soundManager.mute(): Muting "'+sID+'"'); _s.sounds[sID].mute(); } }; this.muteAll = function() { _s.mute(); }; this.unmute = function(sID) { if (typeof sID != 'string') { sID = null; } if (!sID) { _s._wD('soundManager.unmute(): Unmuting all sounds'); for (var i=_s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].unmute(); } _s.muted = false; } else { if (!_s._idCheck(sID)) { return false; } _s._wD('soundManager.unmute(): Unmuting "'+sID+'"'); _s.sounds[sID].unmute(); } }; this.unmuteAll = function() { _s.unmute(); }; this.getMemoryUse = function() { if (_s.flashVersion == 8) { // not supported in Flash 8 return 0; } if (_s.o) { return parseInt(_s.o._getMemoryUse(),10); } }; this.setPolling = function(bPolling) { if (!_s.o || !_s.allowPolling) { return false; } _s.o._setPolling(bPolling); }; this.disable = function(bNoDisable) { // destroy all functions if (typeof bNoDisable == 'undefined') { bNoDisable = false; } if (_s._disabled) { return false; } _s._disabled = true; _s._wD('soundManager.disable(): Shutting down',1); for (var i=_s.soundIDs.length; i--;) { _s._disableObject(_s.sounds[_s.soundIDs[i]]); } _s.initComplete(bNoDisable); // fire "complete", despite fail // _s._disableObject(_s); // taken out to allow reboot() }; this.canPlayURL = function(sURL) { return (sURL?(sURL.match(_s.filePattern)?true:false):null); }; this.getSoundById = function(sID,suppressDebug) { if (!sID) { throw new Error('SoundManager.getSoundById(): sID is null/undefined'); } var result = _s.sounds[sID]; if (!result && !suppressDebug) { _s._wD('"'+sID+'" is an invalid sound ID.',2); // soundManager._wD('trace: '+arguments.callee.caller); } return result; }; this.onload = function() { // window.onload() equivalent for SM2, ready to create sounds etc. // this is a stub - you can override this in your own external script, eg. soundManager.onload = function() {} soundManager._wD('Warning: soundManager.onload() is undefined.',2); }; this.onerror = function() { // stub for user handler, called when SM2 fails to load/init }; // --- "private" methods --- this._idCheck = this.getSoundById; this._complain = function(sMsg,oCaller) { // Try to create meaningful custom errors, w/stack trace to the "offending" line var sPre = 'Error: '; if (!oCaller) { return new Error(sPre+sMsg); } var e = new Error(''); // make a mistake. var stackMsg = null; if (e.stack) { // potentially dangerous: Try to return a meaningful stacktrace where provided (Mozilla) try { var splitChar = '@'; var stackTmp = e.stack.split(splitChar); stackMsg = stackTmp[4]; // try to return only the relevant bit, skipping internal SM2 shiz } catch(ee) { // oops. stackMsg = e.stack; } } if (typeof console != 'undefined' && typeof console.trace != 'undefined') { console.trace(); } var errorDesc = sPre+sMsg+'. \nCaller: '+oCaller.toString()+(e.stack?' \nTop of stacktrace: '+stackMsg:(e.message?' \nMessage: '+e.message:'')); // See JS error/debug/console output for real error source, stack trace / message detail where possible. return new Error(errorDesc); }; var _doNothing = function() { return false; }; _doNothing._protected = true; this._disableObject = function(o) { for (var oProp in o) { if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') { o[oProp] = _doNothing; } } oProp = null; }; this._failSafely = function(bNoDisable) { // general failure exception handler if (typeof bNoDisable == 'undefined') { bNoDisable = false; } if (!_s._disabled || bNoDisable) { _s._wD('soundManager: Failed to initialise.',2); _s.disable(bNoDisable); } }; this._normalizeMovieURL = function(smURL) { return 'index.php?version=' + EXTERN_CACHE_VERSION + '&extern=libs/eyeSound/' + _s.movieURL; // eyeOS }; this._getDocument = function() { return (document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName('div')[0])); }; this._getDocument._protected = true; this._createMovie = function(smID,smURL) { if (_s._didAppend && _s._appendSuccess) { return false; // ignore if already succeeded } if (window.location.href.indexOf('debug=1')+1) { _s.debugMode = true; // allow force of debug mode via URL } _s._didAppend = true; // safety check for legacy (change to Flash 9 URL) _s._setVersionInfo(); var remoteURL = (smURL?smURL:_s.url); var localURL = (_s.altURL?_s.altURL:remoteURL); _s.url = _s._normalizeMovieURL(_s._overHTTP?remoteURL:localURL); smURL = _s.url; var specialCase = null; if (_s.useHighPerformance && _s.useMovieStar && _s.defaultOptions.useVideo === true) { specialCase = 'soundManager note: disabling highPerformance, not applicable with movieStar mode + useVideo'; _s.useHighPerformance = false; } _s.wmode = (!_s.wmode && _s.useHighPerformance && !_s.useMovieStar?'transparent':_s.wmode); if (_s.wmode !== null && _s.flashLoadTimeout !== 0 && !_s.useHighPerformance && !_s.isIE && navigator.platform.match(/win32/i)) { _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 _s._wD('soundManager note: Removing wmode, preventing off-screen SWF loading issue'); _s.wmode = null; } if (_s.flashVersion == 8) { _s.allowFullScreen = false; } var oEmbed = { name: smID, id: smID, src: smURL, width: '100%', height: '100%', quality: 'high', allowScriptAccess: 'always', bgcolor: _s.bgColor, pluginspage: 'http://www.macromedia.com/go/getflashplayer', type: 'application/x-shockwave-flash', wmode: _s.wmode, allowfullscreen: (_s.allowFullScreen?'true':'false') }; if (!_s.wmode) { delete oEmbed.wmode; // don't write empty attribute } var oObject = { id: smID, data: smURL, type: 'application/x-shockwave-flash', width: '100%', height: '100%', wmode: _s.wmode }; var oMovie = null; var tmp = null; if (_s.isIE) { // IE is "special". oMovie = document.createElement('div'); var movieHTML = ''+(_s.wmode?' ':'')+''; } else { oMovie = document.createElement('embed'); for (tmp in oEmbed) { if (oEmbed.hasOwnProperty(tmp)) { oMovie.setAttribute(tmp,oEmbed[tmp]); } } } var oD = document.createElement('div'); oD.id = _s.debugID+'-toggle'; var 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(document.createTextNode('-')); oD.onclick = _s._toggleDebug; oD.title = 'Toggle SM2 debug console'; if (navigator.userAgent.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]; } } var oTarget = _s._getDocument(); if (oTarget) { _s.oMC = _$('sm2-container')?_$('sm2-container'):document.createElement('div'); if (!_s.oMC.id) { _s.oMC.id = 'sm2-container'; _s.oMC.className = 'movieContainer'; // "hide" flash movie var s = null; var oEl = null; if (_s.useHighPerformance) { s = { position: 'fixed', width: '8px', height: '8px', // must be at least 6px for flash to run fast. odd? yes. bottom: '0px', left: '0px' // zIndex:-1 // sit behind everything else - potentially dangerous/buggy? }; } else { s = { position: 'absolute', width: '1px', height: '1px', top: '-999px', left: '-999px' }; } var x = null; for (x in s) { if (s.hasOwnProperty(x)) { _s.oMC.style[x] = s[x]; } } try { if (!_s.isIE) { _s.oMC.appendChild(oMovie); } oTarget.appendChild(_s.oMC); if (_s.isIE) { oEl = _s.oMC.appendChild(document.createElement('div')); oEl.className = 'sm2-object-box'; oEl.innerHTML = movieHTML; } _s._appendSuccess = true; } catch(e) { throw new Error(_s.strings.appXHTML); } } else { // it's already in the document. _s.oMC.appendChild(oMovie); if (_s.isIE) { oEl = _s.oMC.appendChild(document.createElement('div')); oEl.className = 'sm2-object-box'; oEl.innerHTML = movieHTML; } _s._appendSuccess = true; } if (!_$(_s.debugID) && ((!_s._hasConsole||!_s.useConsole)||(_s.useConsole && _s._hasConsole && !_s.consoleOnly))) { var oDebug = document.createElement('div'); oDebug.id = _s.debugID; oDebug.style.display = (_s.debugMode?'block':'none'); if (_s.debugMode && !_$(oD.id)) { try { oTarget.appendChild(oD); } catch(e2) { throw new Error(_s.strings.appXHTML); } oTarget.appendChild(oDebug); } } oTarget = null; } if (specialCase) { _s._wD(specialCase); } _s._wD('-- SoundManager 2 '+_s.version+(_s.useMovieStar?', MovieStar mode':'')+(_s.useHighPerformance?', high performance mode':'')+(_s.wmode?', wmode: '+_s.wmode:'')+' --',1); _s._wD('soundManager._createMovie(): Trying to load '+smURL+(!_s._overHTTP && _s.altURL?' (alternate URL)':''),1); }; // aliased to this._wD() this._writeDebug = function(sText,sType,bTimestamp) { if (!_s.debugMode) { return false; } if (typeof bTimestamp != 'undefined' && bTimestamp) { sText = sText + ' | '+new Date().getTime(); } if (_s._hasConsole && _s.useConsole) { var sMethod = _s._debugLevels[sType]; if (typeof console[sMethod] != 'undefined') { console[sMethod](sText); } else { console.log(sText); } if (_s.useConsoleOnly) { return true; } } var sDID = 'soundmanager-debug'; try { var o = _$(sDID); if (!o) { return false; } var oItem = document.createElement('div'); if (++_s._wdCount%2===0) { oItem.className = 'sm2-alt'; } // sText = sText.replace(/\n/g,'
'); if (typeof sType == 'undefined') { sType = 0; } else { sType = parseInt(sType,10); } oItem.appendChild(document.createTextNode(sText)); if (sType) { if (sType >= 2) { oItem.style.fontWeight = 'bold'; } if (sType == 3) { oItem.style.color = '#ff3333'; } } // o.appendChild(oItem); // top-to-bottom o.insertBefore(oItem,o.firstChild); // bottom-to-top } catch(e) { // oh well } o = null; }; this._writeDebug._protected = true; this._wdCount = 0; this._wdCount._protected = true; this._wD = this._writeDebug; this._wDAlert = function(sText) { alert(sText); }; if (window.location.href.indexOf('debug=alert')+1 && _s.debugMode) { _s._wD = _s._wDAlert; } this._toggleDebug = function() { var o = _$(_s.debugID); var oT = _$(_s.debugID+'-toggle'); if (!o) { return false; } if (_s._debugOpen) { // minimize oT.innerHTML = '+'; o.style.display = 'none'; } else { oT.innerHTML = '-'; o.style.display = 'block'; } _s._debugOpen = !_s._debugOpen; }; this._toggleDebug._protected = true; this._debug = function() { _s._wD('--- soundManager._debug(): Current sound objects ---',1); for (var i=0,j=_s.soundIDs.length; i0) { _s._wD('soundManager._initMovie(): Waiting for ExternalInterface call from Flash..'); } } }; this.waitForExternalInterface = function() { if (_s._waitingForEI) { return false; } _s._waitingForEI = true; if (_s._tryInitOnFocus && !_s._isFocused) { _s._wD('soundManager: Special case: Waiting for focus-related event..'); return false; } if (_s.flashLoadTimeout>0) { if (!_s._didInit) { _s._wD('soundManager: Getting impatient, still waiting for Flash.. ;)'); } setTimeout(function() { if (!_s._didInit) { _s._wD('soundManager: No Flash response within reasonable time after document load.\nPossible causes: Loading '+_s.movieURL+' failed, Flash version under '+_s.flashVersion+', no support, flash blocked or JS-Flash security error.',2); if (!_s._overHTTP) { _s._wD('soundManager: Loading this page from local/network file system (not over HTTP?) Flash security likely restricting JS-Flash access. Consider adding current URL to "trusted locations" in the Flash player security settings manager at '+flashCPLink+', or simply serve this content over HTTP.',2); } _s._debugTS('flashtojs',false,': Timed out'+(_s._overHTTP)?' (Check flash security)':' (No plugin/missing SWF?)'); } // if still not initialized and no other options, give up if (!_s._didInit && _s._okToDisable) { _s._failSafely(true); // don't disable, for reboot() } },_s.flashLoadTimeout); } else if (!_s.didInit) { _s._wD('soundManager: Waiting indefinitely for Flash...'); } }; this.handleFocus = function() { if (_s._isFocused || !_s._tryInitOnFocus) { return true; } _s._okToDisable = true; _s._isFocused = true; _s._wD('soundManager.handleFocus()'); if (_s._tryInitOnFocus) { // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented. window.removeEventListener('mousemove',_s.handleFocus,false); } // allow init to restart _s._waitingForEI = false; setTimeout(_s.waitForExternalInterface,500); // detach event if (window.removeEventListener) { window.removeEventListener('focus',_s.handleFocus,false); } else if (window.detachEvent) { window.detachEvent('onfocus',_s.handleFocus); } }; this.initComplete = function(bNoDisable) { if (_s._didInit) { return false; } _s._didInit = true; _s._wD('-- SoundManager 2 '+(_s._disabled?'failed to load':'loaded')+' ('+(_s._disabled?'security/load error':'OK')+') --',1); if (_s._disabled || bNoDisable) { _s._wD('soundManager.initComplete(): calling soundManager.onerror()',1); _s._debugTS('onload',false); _s.onerror.apply(window); return false; } else { _s._debugTS('onload',true); } if (_s.waitForWindowLoad && !_s._windowLoaded) { _s._wD('soundManager: Waiting for window.onload()'); if (window.addEventListener) { window.addEventListener('load',_s.initUserOnload,false); } else if (window.attachEvent) { window.attachEvent('onload',_s.initUserOnload); } return false; } else { if (_s.waitForWindowLoad && _s._windowLoaded) { _s._wD('soundManager: Document already loaded'); } _s.initUserOnload(); } }; this.initUserOnload = function() { _s._wD('soundManager.initComplete(): calling soundManager.onload()',1); // call user-defined "onload", scoped to window _s.onload.apply(window); _s._wD('soundManager.onload() complete',1); }; this.init = function() { _s._wD('-- soundManager.init() --'); // called after onload() _s._initMovie(); if (_s._didInit) { _s._wD('soundManager.init(): Already called?'); return false; } // event cleanup if (window.removeEventListener) { window.removeEventListener('load',_s.beginDelayedInit,false); } else if (window.detachEvent) { window.detachEvent('onload',_s.beginDelayedInit); } try { _s._wD('Attempting to call Flash from JS..'); _s.o._externalInterfaceTest(false); // attempt to talk to Flash // _s._wD('Flash ExternalInterface call (JS-Flash) OK',1); if (!_s.allowPolling) { _s._wD('Polling (whileloading/whileplaying support) is disabled.',1); } _s.setPolling(true); if (!_s.debugMode) { _s.o._disableDebug(); } _s.enabled = true; _s._debugTS('jstoflash',true); } catch(e) { _s._debugTS('jstoflash',false); _s._failSafely(true); // don't disable, for reboot() _s.initComplete(); return false; } _s.initComplete(); }; this.beginDelayedInit = function() { _s._wD('soundManager.beginDelayedInit()'); _s._windowLoaded = true; setTimeout(_s.waitForExternalInterface,500); setTimeout(_s.beginInit,20); }; this.beginInit = function() { if (_s._initPending) { return false; } _s.createMovie(); // ensure creation if not already done _s._initMovie(); _s._initPending = true; return true; }; this.domContentLoaded = function() { _s._wD('soundManager.domContentLoaded()'); if (document.removeEventListener) { document.removeEventListener('DOMContentLoaded',_s.domContentLoaded,false); } _s.go(); }; this._externalInterfaceOK = function() { // callback from flash for confirming that movie loaded, EI is working etc. if (_s.swfLoaded) { return false; } _s._wD('soundManager._externalInterfaceOK()'); _s._debugTS('swf',true); _s._debugTS('flashtojs',true); _s.swfLoaded = true; _s._tryInitOnFocus = false; if (_s.isIE) { // IE needs a timeout OR delay until window.onload - may need TODO: investigating setTimeout(_s.init,100); } else { _s.init(); } }; 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; _s._wD('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',2); } else if (sb.type == 'localWithNetwork') { sb.noRemote = false; sb.noLocal = true; } else if (sb.type == 'localTrusted') { sb.noRemote = false; sb.noLocal = false; } }; this.reboot = function() { // attempt to reset and init SM2 _s._wD('soundManager.reboot()'); if (_s.soundIDs.length) { _s._wD('Destroying '+_s.soundIDs.length+' SMSound objects...'); } for (var i=_s.soundIDs.length; i--;) { _s.sounds[_s.soundIDs[i]].destruct(); } // trash ze flash try { if (_s.isIE) { _s.oRemovedHTML = _s.o.innerHTML; } _s.oRemoved = _s.o.parentNode.removeChild(_s.o); _s._wD('Flash movie removed.'); } catch(e) { // uh-oh. _s._wD('Warning: Failed to remove flash movie.',2); } _s.enabled = false; _s._didInit = false; _s._waitingForEI = false; _s._initPending = false; _s._didInit = false; _s._didAppend = false; _s._appendSuccess = false; _s._didInit = false; _s._disabled = false; _s._waitingforEI = true; _s.swfLoaded = false; _s.soundIDs = {}; _s.sounds = []; _s.o = null; _s._wD('soundManager: Rebooting...'); window.setTimeout(function() { soundManager.beginDelayedInit(); },20); }; this.destruct = function() { _s._wD('soundManager.destruct()'); _s.disable(true); }; // SMSound (sound object) SMSound = function(oOptions) { var _t = this; this.sID = oOptions.id; this.url = oOptions.url; this.options = _s._mergeObjects(oOptions); this.instanceOptions = this.options; // per-play-instance-specific options this._iO = this.instanceOptions; // short alias // assign property defaults (volume, pan etc.) this.pan = this.options.pan; this.volume = this.options.volume; this._lastURL = null; this._debug = function() { if (_s.debugMode) { var stuff = null; var msg = []; var sF = null; var sfBracket = null; var maxLength = 64; // # of characters of function code to show before truncating 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 sfBracket = sF.indexOf('{'); msg[msg.length] = ' '+stuff+': {'+sF.substr(sfBracket+1,(Math.min(Math.max(sF.indexOf('\n')-1,maxLength),maxLength))).replace(/\n/g,'')+'... }'; } else { msg[msg.length] = ' '+stuff+': '+_t.options[stuff]; } } } _s._wD('SMSound() merged options: {\n'+msg.join(', \n')+'\n}'); } }; this._debug(); this.id3 = { /* Name/value pairs set via Flash when available - see reference for names: http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html (eg., this.id3.songname or this.id3['songname']) */ }; this.resetProperties = function(bLoaded) { _t.bytesLoaded = null; _t.bytesTotal = null; _t.position = null; _t.duration = null; _t.durationEstimate = null; _t.loaded = false; _t.playState = 0; _t.paused = false; _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success _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 = []; }; _t.resetProperties(); // --- public methods --- this.load = function(oOptions) { if (typeof oOptions != 'undefined') { _t._iO = _s._mergeObjects(oOptions); _t.instanceOptions = _t._iO; } else { oOptions = _t.options; _t._iO = oOptions; _t.instanceOptions = _t._iO; // console.log('typeof oOptions: '+(typeof oOptions)+', lastURL: '+_t._lastURL+', _t.url: '+_t.url); if (_t._lastURL && _t._lastURL != _t.url) { _s._wD('SMSound.load(): Using manually-assigned URL'); _t._iO.url = _t.url; _t.url = null; } } if (typeof _t._iO.url == 'undefined') { _t._iO.url = _t.url; } _s._wD('soundManager.load(): '+_t._iO.url,1); if (_t._iO.url == _t.url && _t.readyState !== 0 && _t.readyState != 2) { _s._wD('soundManager.load(): current URL already assigned.',1); return false; } _t.url = _t._iO.url; _t._lastURL = _t._iO.url; _t.loaded = false; _t.readyState = 1; _t.playState = 0; // (oOptions.autoPlay?1:0); // if autoPlay, assume "playing" is true (no way to detect when it actually starts in Flash unless onPlay is watched?) try { if (_s.flashVersion==8) { _s.o._load(_t.sID,_t._iO.url,_t._iO.stream,_t._iO.autoPlay,(_t._iO.whileloading?1:0)); } else { _s.o._load(_t.sID,_t._iO.url,_t._iO.stream?true:false,_t._iO.autoPlay?true:false); // ,(_tO.whileloading?true:false) if (_t._iO.isMovieStar && _t._iO.autoLoad && !_t._iO.autoPlay) { // special case: MPEG4 content must start playing to load, then pause to prevent playing. _t.pause(); } } } catch(e) { _s._wD('SMSound.load(): Exception: JS-Flash communication failed, or JS error.',2); _s._debugTS('onload',false); _s.onerror(); _s.disable(); } }; this.unload = function() { // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3 // Flash 9/AS3: Close stream, preventing further load if (_t.readyState !== 0) { _s._wD('SMSound.unload(): "'+_t.sID+'"'); if (_t.readyState != 2) { // reset if not error _t.setPosition(0,true); // reset current sound positioning } _s.o._unload(_t.sID,_s.nullURL); // reset load/status flags _t.resetProperties(); } }; this.destruct = function() { // kill sound within Flash _s._wD('SMSound.destruct(): "'+_t.sID+'"'); _s.o._destroySound(_t.sID); _s.destroySound(_t.sID,true); // ensure deletion from controller }; this.play = function(oOptions) { if (!oOptions) { oOptions = {}; } _t._iO = _s._mergeObjects(oOptions,_t._iO); _t._iO = _s._mergeObjects(_t._iO,_t.options); _t.instanceOptions = _t._iO; if (_t.playState == 1) { var allowMulti = _t._iO.multiShot; if (!allowMulti) { _s._wD('SMSound.play(): "'+_t.sID+'" already playing (one-shot)',1); return false; } else { _s._wD('SMSound.play(): "'+_t.sID+'" already playing (multi-shot)',1); } } if (!_t.loaded) { if (_t.readyState === 0) { _s._wD('SMSound.play(): Attempting to load "'+_t.sID+'"',1); // try to get this sound playing ASAP _t._iO.stream = true; _t._iO.autoPlay = true; // TODO: need to investigate when false, double-playing // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here _t.load(_t._iO); // try to get this sound playing ASAP } else if (_t.readyState == 2) { _s._wD('SMSound.play(): Could not load "'+_t.sID+'" - exiting',2); return false; } else { _s._wD('SMSound.play(): "'+_t.sID+'" is loading - attempting to play..',1); } } else { _s._wD('SMSound.play(): "'+_t.sID+'"'); } if (_t.paused) { _t.resume(); } else { _t.playState = 1; if (!_t.instanceCount || _s.flashVersion > 8) { _t.instanceCount++; } _t.position = (typeof _t._iO.position != 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0); if (_t._iO.onplay) { _t._iO.onplay.apply(_t); } _t.setVolume(_t._iO.volume,true); // restrict volume to instance options only _t.setPan(_t._iO.pan,true); _s.o._start(_t.sID,_t._iO.loop||1,(_s.flashVersion==9?_t.position:_t.position/1000)); } }; this.start = this.play; // just for convenience this.stop = function(bAll) { if (_t.playState == 1) { _t.playState = 0; _t.paused = false; // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s); if (_t._iO.onstop) { _t._iO.onstop.apply(_t); } _s.o._stop(_t.sID,bAll); _t.instanceCount = 0; _t._iO = {}; // _t.instanceOptions = _t._iO; } }; this.setPosition = function(nMsecOffset,bNoDebug) { if (typeof nMsecOffset == 'undefined') { nMsecOffset = 0; } var offset = Math.min(_t.duration,Math.max(nMsecOffset,0)); // position >= 0 and <= current available (loaded) duration _t._iO.position = offset; if (!bNoDebug) { // _s._wD('SMSound.setPosition('+nMsecOffset+')'+(nMsecOffset != offset?', corrected value: '+offset:'')); } _s.o._setPosition(_t.sID,(_s.flashVersion==9?_t._iO.position:_t._iO.position/1000),(_t.paused||!_t.playState)); // if paused or not playing, will not resume (by playing) }; this.pause = function() { if (_t.paused || _t.playState === 0) { return false; } _s._wD('SMSound.pause()'); _t.paused = true; _s.o._pause(_t.sID); if (_t._iO.onpause) { _t._iO.onpause.apply(_t); } }; this.resume = function() { if (!_t.paused || _t.playState === 0) { return false; } _s._wD('SMSound.resume()'); _t.paused = false; _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume) if (_t._iO.onresume) { _t._iO.onresume.apply(_t); } }; this.togglePause = function() { _s._wD('SMSound.togglePause()'); if (_t.playState === 0) { _t.play({position:(_s.flashVersion==9?_t.position:_t.position/1000)}); return false; } if (_t.paused) { _t.resume(); } else { _t.pause(); } }; this.setPan = function(nPan,bInstanceOnly) { if (typeof nPan == 'undefined') { nPan = 0; } if (typeof bInstanceOnly == 'undefined') { bInstanceOnly = false; } _s.o._setPan(_t.sID,nPan); _t._iO.pan = nPan; if (!bInstanceOnly) { _t.pan = nPan; } }; this.setVolume = function(nVol,bInstanceOnly) { if (typeof nVol == 'undefined') { nVol = 100; } if (typeof bInstanceOnly == 'undefined') { bInstanceOnly = false; } _s.o._setVolume(_t.sID,(_s.muted&&!_t.muted)||_t.muted?0:nVol); _t._iO.volume = nVol; if (!bInstanceOnly) { _t.volume = nVol; } }; this.mute = function() { _t.muted = true; _s.o._setVolume(_t.sID,0); }; this.unmute = function() { _t.muted = false; var hasIO = typeof _t._iO.volume != 'undefined'; _s.o._setVolume(_t.sID,hasIO?_t._iO.volume:_t.options.volume); }; // --- "private" methods called by Flash --- this._whileloading = function(nBytesLoaded,nBytesTotal,nDuration) { if (!_t._iO.isMovieStar) { _t.bytesLoaded = nBytesLoaded; _t.bytesTotal = nBytesTotal; _t.duration = Math.floor(nDuration); _t.durationEstimate = parseInt((_t.bytesTotal/_t.bytesLoaded)*_t.duration,10); if (_t.readyState != 3 && _t._iO.whileloading) { _t._iO.whileloading.apply(_t); } } else { _t.bytesLoaded = nBytesLoaded; _t.bytesTotal = nBytesTotal; _t.duration = Math.floor(nDuration); _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 = []; for (var i=0,j=oID3PropNames.length; i 0) { // can happen at the end of a video where nPosition == 33 for some reason, after finishing.??? // can also happen with a normal stop operation. This resets the position to 0. // _s._writeDebug('Note: Not playing, but position = '+nPosition); nPosition = 0; } _t.position = nPosition; 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 && typeof oEQData != 'undefined' && oEQData) { _t.eqData = oEQData; } if (_t.playState == 1) { // special case/hack: ensure buffering is false (instant load from cache, thus buffering stuck at 1?) if (_t.isBuffering) { _t._onbufferchange(0); } if (_t._iO.whileplaying) { _t._iO.whileplaying.apply(_t); // flash may call after actual finish } if (_t.loaded && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration-_t.position <= _t._iO.onbeforefinishtime) { _s._wD('duration-position <= onbeforefinishtime: '+_t.duration+' - '+_t.position+' <= '+_t._iO.onbeforefinishtime+' ('+(_t.duration-_t.position)+')'); _t._onbeforefinish(); } } }; this._onload = function(bSuccess) { bSuccess = (bSuccess==1?true:false); _s._wD('SMSound._onload(): "'+_t.sID+'"'+(bSuccess?' loaded.':' failed to load? - '+_t.url),(bSuccess?1:2)); if (!bSuccess) { if (_s.sandbox.noRemote === true) { _s._wD('SMSound._onload(): Reminder: Flash security is denying network/internet access',1); } if (_s.sandbox.noLocal === true) { _s._wD('SMSound._onload(): Reminder: Flash security is denying local access',1); } } _t.loaded = bSuccess; _t.readyState = bSuccess?3:2; if (_t._iO.onload) { _t._iO.onload.apply(_t); } }; 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._onjustbeforefinish = function(msOffset) { // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187) if (!_t.didJustBeforeFinish) { _t.didJustBeforeFinish = true; if (_t._iO.onjustbeforefinish) { _s._wD('SMSound._onjustbeforefinish(): "'+_t.sID+'"'); _t._iO.onjustbeforefinish.apply(_t); } } }; this._onfinish = function() { // sound has finished playing // TODO: calling user-defined onfinish() should happen after setPosition(0) // OR: onfinish() and then setPosition(0) is bad. 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.setPosition(0); _t.playState = 0; _t.paused = false; _t.instanceCount = 0; _t.instanceOptions = {}; if (_t._iO.onfinish) { _s._wD('SMSound._onfinish(): "'+_t.sID+'"'); _t._iO.onfinish.apply(_t); } } } else { if (_t.useVideo) { // video has finished // may need to reset position for next play call, "rewind" // _t.setPosition(0); } // _t.setPosition(0); } }; this._onmetadata = function(oMetaData) { // movieStar mode only _s._wD('SMSound.onmetadata()'); // Contains a subset of metadata. Note that files may have their own unique metadata. // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html if (!oMetaData.width && !oMetaData.height) { _s._wD('No width/height given, assuming defaults'); oMetaData.width = 320; oMetaData.height = 240; } _t.metadata = oMetaData; // potentially-large object from flash _t.width = oMetaData.width; _t.height = oMetaData.height; if (_t._iO.onmetadata) { _s._wD('SMSound._onmetadata(): "'+_t.sID+'"'); _t._iO.onmetadata.apply(_t); } _s._wD('SMSound.onmetadata() complete'); }; this._onbufferchange = function(bIsBuffering) { if (_t.playState === 0) { // ignore if not playing return false; } if (bIsBuffering == _t.isBuffering) { // ignore initial "false" default, if matching _s._wD('_onbufferchange: ignoring false default / loaded sound'); return false; } _t.isBuffering = (bIsBuffering==1?true:false); if (_t._iO.onbufferchange) { _s._wD('SMSound._onbufferchange(): '+bIsBuffering); _t._iO.onbufferchange.apply(_t); } }; 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); } } else { // _s._wD('SMSound._ondataerror(): ignoring'); } }; }; // SMSound() this._onfullscreenchange = function(bFullScreen) { _s._wD('onfullscreenchange(): '+bFullScreen); _s.isFullScreen = (bFullScreen==1?true:false); if (!_s.isFullScreen) { // attempt to restore window focus after leaving full-screen try { window.focus(); _s._wD('window.focus()'); } catch(e) { // oh well } } }; // register a few event handlers if (window.addEventListener) { window.addEventListener('focus',_s.handleFocus,false); window.addEventListener('load',_s.beginDelayedInit,false); window.addEventListener('unload',_s.destruct,false); if (_s._tryInitOnFocus) { window.addEventListener('mousemove',_s.handleFocus,false); // massive Safari focus hack } } else if (window.attachEvent) { window.attachEvent('onfocus',_s.handleFocus); window.attachEvent('onload',_s.beginDelayedInit); window.attachEvent('unload',_s.destruct); } else { // no add/attachevent support - safe to assume no JS -> Flash either. _s._debugTS('onload',false); soundManager.onerror(); soundManager.disable(); } if (document.addEventListener) { document.addEventListener('DOMContentLoaded',_s.domContentLoaded,false); } } // SoundManager() // set var SM2_DEFER = true; in your own script to prevent auto start-up if (FlashDetect.installed) { // eyeOS soundManager = new SoundManager(); }