PageSourceSearch

https://chopin.pl/scripts/soundmanager2.js

js chopin.pl collected 2026-09-24 17:54:28 UTC 49,684 bytes, 1,529 lines download raw bytes

1/*!
2   SoundManager 2: Javascript Sound for the Web
3   --------------------------------------------
4   http://schillmania.com/projects/soundmanager2/
5
6   Copyright (c) 2008, Scott Schiller. All rights reserved.
7   Code licensed under the BSD License:
8   http://schillmania.com/projects/soundmanager2/license.txt
9
10   V2.93a.20090117
11*/
12
13var soundManager = null;
14
15function SoundManager(smURL,smID) {
16 
17  this.flashVersion = 8;           // version of flash to require, either 8 or 9. Some API features require Flash 9.
18  this.debugMode = true;           // enable debugging output (div#soundmanager-debug, OR console if available + configured)
19  this.useConsole = true;          // use firebug/safari console.log()-type debug console if available
20  this.consoleOnly = false;        // if console is being used, do not create/write to #soundmanager-debug
21  this.waitForWindowLoad = false;  // force SM2 to wait for window.onload() before trying to call soundManager.onload()
22  this.nullURL = 'null.mp3';       // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)
23  this.allowPolling = true;        // allow flash to poll for status update (required for "while playing", peak, sound spectrum functions to work.)
24  this.useMovieStar = false;	   // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio + video formats (AAC, M4V, FLV, MOV etc.)
25  this.bgColor = '#ffffff';	   // movie (.swf) background color, useful if showing on-screen for video etc.
26  this.useHighPerformance = true;  // position:fixed flash movie gives increased js/flash speed, but buggy and disabled for firefox/win32 by default (set value to 'always' to override)
27
28  this.defaultOptions = {
29    '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)
30    'stream': true,                // allows playing before entire file has loaded (recommended)
31    'autoPlay': false,             // enable playing of file as soon as possible (much faster if "stream" is true)
32    'onid3': null,                 // callback function for "ID3 data is added/available"
33    'onload': null,                // callback function for "load finished"
34    'whileloading': null,          // callback function for "download progress update" (X of Y bytes received)
35    'onplay': null,                // callback for "play" start
36    'onpause': null,               // callback for "pause"
37    'onresume': null,              // callback for "resume" (pause toggle)
38    'whileplaying': null,          // callback during play (position update)
39    'onstop': null,                // callback for "user stop"
40    'onfinish': null,              // callback function for "sound finished playing"
41    'onbeforefinish': null,        // callback for "before sound finished playing (at [time])"
42    'onbeforefinishtime': 5000,    // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)
43    'onbeforefinishcomplete':null, // function to call when said sound finishes playing
44    'onjustbeforefinish':null,     // callback for [n] msec before end of current sound
45    'onjustbeforefinishtime':200,  // [n] - if not using, set to 0 (or null handler) and event will not fire.
46    'multiShot': true,             // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
47    'position': null,              // offset (milliseconds) to seek to within loaded sound data.
48    'pan': 0,                      // "pan" settings, left-to-right, -100 to 100
49    'volume': 100                  // self-explanatory. 0-100, the latter being the max.
50  };
51
52  this.flash9Options = {           // flash 9-only options, merged into defaultOptions if flash 9 is being used
53    'isMovieStar': null,	   // "MovieStar" MPEG4 audio/video mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
54    'usePeakData': false,          // enable left/right channel peak (level) data
55    'useWaveformData': false,      // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.
56    'useEQData': false             // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.
57  };
58
59  this.movieStarOptions = {        // flash 9.0r115+ MPEG4 audio/video options, merged into defaultOptions if flash 9 + movieStar mode is enabled
60    'onmetadata': null,		   // callback for when video width/height etc. are received
61    'useVideo': false		   // if loading movieStar content, whether to show video
62  };
63
64  // jslint global declarations
65  /*global sm2Debugger, alert, console, document, navigator, setTimeout, window */
66
67  var SMSound = null; // defined later
68
69  var _s = this;
70  this.version = null;
71  this.versionNumber = 'V2.93a.20090117';
72  this.movieURL = null;
73  this.url = null;
74  this.altURL = null;
75  this.swfLoaded = false;
76  this.enabled = false;
77  this.o = null;
78  this.id = (smID||'sm2movie');
79  this.oMC = null;
80  this.sounds = {};
81  this.soundIDs = [];
82  this.muted = false;
83  this.isIE = (navigator.userAgent.match(/MSIE/i));
84  this.isSafari = (navigator.userAgent.match(/safari/i));
85  this.isGecko = (navigator.userAgent.match(/gecko/i));
86  this.debugID = 'soundmanager-debug';
87  this._debugOpen = true;
88  this._didAppend = false;
89  this._appendSuccess = false;
90  this._didInit = false;
91  this._disabled = false;
92  this._windowLoaded = false;
93  this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined');
94  this._debugLevels = ['log','info','warn','error'];
95  this._defaultFlashVersion = 8;
96
97  this.filePatterns = {
98	flash8: /\.mp3(\?.*)?$/i,
99	flash9: /\.mp3(\?.*)?$/i
100  };
101
102  this.netStreamTypes = ['aac','flv','mov','mp4','m4v','f4v','m4a','mp4v','3gp','3g2']; // Flash v9.0r115+ "moviestar" formats
103  this.netStreamPattern = new RegExp('\\.('+this.netStreamTypes.join('|')+')(\\?.*)?$','i');
104
105  this.filePattern = null;
106  this.features = {
107    peakData: false,
108    waveformData: false,
109    eqData: false,
110    movieStar: false
111  };
112
113  this.sandbox = {
114    'type': null,
115    'types': {
116      'remote': 'remote (domain-based) rules',
117      'localWithFile': 'local with file access (no internet access)',
118      'localWithNetwork': 'local with network (internet access only, no local access)',
119      'localTrusted': 'local, trusted (local + internet access)'
120    },
121    'description': null,
122    'noRemote': null,
123    'noLocal': null
124  };
125
126  this._setVersionInfo = function() {
127    if (_s.flashVersion != 8 && _s.flashVersion != 9) {
128      alert('soundManager.flashVersion must be 8 or 9. "'+_s.flashVersion+'" is invalid. Reverting to '+_s._defaultFlashVersion+'.');
129      _s.flashVersion = _s._defaultFlashVersion;
130    }
131    _s.version = _s.versionNumber+(_s.flashVersion==9?' (AS3/Flash 9)':' (AS2/Flash 8)');
132    // set up default options
133	if (_s.flashVersion > 8) {
134	  _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.flash9Options);
135	}
136    if (_s.flashVersion > 8 && _s.useMovieStar) {
137      // flash 9+ support for movieStar formats as well as MP3
138      _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.movieStarOptions);
139      _s.filePatterns.flash9 = new RegExp('\\.(mp3|'+_s.netStreamTypes.join('|')+')(\\?.*)?$','i');
140      _s.features.movieStar = true;
141    } else {
142      _s.useMovieStar = false;
143      _s.features.movieStar = false;
144    }
145    _s.filePattern = _s.filePatterns[(_s.flashVersion!=8?'flash9':'flash8')];
146    _s.movieURL = (_s.flashVersion==8?'soundmanager2.swf':'soundmanager2_flash9.swf');
147    _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_s.flashVersion==9);
148  };
149
150  this._overHTTP = (document.location?document.location.protocol.match(/http/i):null);
151  this._waitingforEI = false;
152  this._initPending = false;
153  this._tryInitOnFocus = (this.isSafari && typeof document.hasFocus == 'undefined');
154  this._isFocused = (typeof document.hasFocus != 'undefined'?document.hasFocus():null);
155  this._okToDisable = !this._tryInitOnFocus;
156
157  this.useAltURL = !this._overHTTP; // use altURL if not "online"
158
159  var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html';
160
161  // --- public methods ---
162  
163  this.supported = function() {
164    return (_s._didInit && !_s._disabled);
165  };
166
167  this.getMovie = function(smID) {
168    return _s.isIE?window[smID]:(_s.isSafari?document.getElementById(smID)||document[smID]:document.getElementById(smID));
169  };
170
171  this.loadFromXML = function(sXmlUrl) {
172    try {
173      _s.o._loadFromXML(sXmlUrl);
174    } catch(e) {
175      _s._failSafely();
176      return true;
177    }
178  };
179
180  this.createSound = function(oOptions) {
181    if (!_s._didInit) {
182	  throw new Error('soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods');
183	}
184    if (arguments.length == 2) {
185      // function overloading in JS! :) ..assume simple createSound(id,url) use case
186      oOptions = {'id':arguments[0],'url':arguments[1]};
187    }
188    var thisOptions = _s._mergeObjects(oOptions); // inherit SM2 defaults
189    var _tO = thisOptions; // alias
190    _s._wD('soundManager.createSound(): '+_tO.id+' ('+_tO.url+')',1);
191    if (_s._idCheck(_tO.id,true)) {
192      _s._wD('soundManager.createSound(): '+_tO.id+' exists',1);
193      return _s.sounds[_tO.id];
194    }
195    if (_s.flashVersion > 8 && _s.useMovieStar) {
196	  if (_tO.isMovieStar === null) {
197	    _tO.isMovieStar = (_tO.url.match(_s.netStreamPattern)?true:false);
198	  }
199	  if (_tO.isMovieStar) {
200	    _s._wD('soundManager.createSound(): using MovieStar handling');
201	  }
202	  if (_tO.isMovieStar && (_tO.usePeakData || _tO.useWaveformData || _tO.useEQData)) {
203	    _s._wD('Warning: peak/waveform/eqData features unsupported for non-MP3 formats');
204	    _tO.usePeakData = false;
205		_tO.useWaveformData = false;
206		_tO.useEQData = false;
207	  }
208    }
209    _s.sounds[_tO.id] = new SMSound(_tO);
210    _s.soundIDs[_s.soundIDs.length] = _tO.id;
211    // AS2:
212    if (_s.flashVersion == 8) {
213      _s.o._createSound(_tO.id,_tO.onjustbeforefinishtime);
214    } else {
215      _s.o._createSound(_tO.id,_tO.url,_tO.onjustbeforefinishtime,_tO.usePeakData,_tO.useWaveformData,_tO.useEQData,_tO.isMovieStar,(_tO.isMovieStar?_tO.useVideo:false));
216    }
217    if (_tO.autoLoad || _tO.autoPlay) {
218      // TODO: does removing timeout here cause problems?
219        if (_s.sounds[_tO.id]) {
220          _s.sounds[_tO.id].load(_tO);
221        }
222    }
223    if (_tO.autoPlay) {
224	  _s.sounds[_tO.id].play();
225	}
226    return _s.sounds[_tO.id];
227  };
228
229  this.createVideo = function(oOptions) {
230    if (arguments.length==2) {
231      oOptions = {'id':arguments[0],'url':arguments[1]};
232    }
233    if (_s.flashVersion >= 9) {
234      oOptions.isMovieStar = true;
235      oOptions.useVideo = true;
236    } else {
237      _s._wD('soundManager.createVideo(): flash 9 required for video. Exiting.',2);
238      return false;
239    }
240    if (!_s.useMovieStar) {
241      _s._wD('soundManager.createVideo(): MovieStar mode not enabled. Exiting.',2);
242    }
243    return _s.createSound(oOptions);
244  };
245
246  this.destroySound = function(sID,bFromSound) {
247    // explicitly destroy a sound before normal page unload, etc.
248    if (!_s._idCheck(sID)) {
249      return false;
250    }
251    for (var i=0; i<_s.soundIDs.length; i++) {
252      if (_s.soundIDs[i] == sID) {
253	    _s.soundIDs.splice(i,1);
254        continue;
255      }
256    }
257    // conservative option: avoid crash with ze flash 8
258    // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP + flash 8??
259    // if (_s.flashVersion != 8) {
260      _s.sounds[sID].unload();
261    // }
262    if (!bFromSound) {
263      // ignore if being called from SMSound instance
264      _s.sounds[sID].destruct();
265    }
266    delete _s.sounds[sID];
267  };
268
269  this.destroyVideo = this.destroySound;
270
271  this.load = function(sID,oOptions) {
272    if (!_s._idCheck(sID)) {
273      return false;
274    }
275    _s.sounds[sID].load(oOptions);
276  };
277
278  this.unload = function(sID) {
279    if (!_s._idCheck(sID)) {
280      return false;
281    }
282    _s.sounds[sID].unload();
283  };
284
285  this.play = function(sID,oOptions) {
286    if (!_s._idCheck(sID)) {
287      if (typeof oOptions != 'Object') {
288		oOptions = {url:oOptions}; // overloading use case: play('mySound','/path/to/some.mp3');
289	  }
290      if (oOptions && oOptions.url) {
291        // overloading use case, creation + playing of sound: .play('someID',{url:'/path/to.mp3'});
292        _s._wD('soundController.play(): attempting to create "'+sID+'"',1);
293        oOptions.id = sID;
294        _s.createSound(oOptions);
295      } else {
296        return false;
297      }
298    }
299    _s.sounds[sID].play(oOptions);
300  };
301
302  this.start = this.play; // just for convenience
303
304  this.setPosition = function(sID,nMsecOffset) {
305    if (!_s._idCheck(sID)) {
306      return false;
307    }
308    _s.sounds[sID].setPosition(nMsecOffset);
309  };
310
311  this.stop = function(sID) {
312    if (!_s._idCheck(sID)) {
313	  return false;
314	}
315    _s._wD('soundManager.stop('+sID+')',1);
316    _s.sounds[sID].stop(); 
317  };
318
319  this.stopAll = function() {
320    _s._wD('soundManager.stopAll()',1);
321    for (var oSound in _s.sounds) {
322      if (_s.sounds[oSound] instanceof SMSound) {
323		_s.sounds[oSound].stop(); // apply only to sound objects
324	  }
325    }
326  };
327
328  this.pause = function(sID) {
329    if (!_s._idCheck(sID)) {
330	  return false;
331	}
332    _s.sounds[sID].pause();
333  };
334
335  this.pauseAll = function() {
336    for (var i=_s.soundIDs.length; i--;) {
337      _s.sounds[_s.soundIDs[i]].pause();
338    }
339  };
340
341  this.resume = function(sID) {
342    if (!_s._idCheck(sID)) {
343	  return false;
344	}
345    _s.sounds[sID].resume();
346  };
347
348  this.resumeAll = function() {
349    for (var i=_s.soundIDs.length; i--;) {
350      _s.sounds[_s.soundIDs[i]].resume();
351    }
352  };
353
354  this.togglePause = function(sID) {
355    if (!_s._idCheck(sID)) {
356	  return false;
357	}
358    _s.sounds[sID].togglePause();
359  };
360
361  this.setPan = function(sID,nPan) {
362    if (!_s._idCheck(sID)) {
363	  return false;
364	}
365    _s.sounds[sID].setPan(nPan);
366  };
367
368  this.setVolume = function(sID,nVol) {
369    if (!_s._idCheck(sID)) {
370	  return false;
371	}
372    _s.sounds[sID].setVolume(nVol);
373  };
374
375  this.mute = function(sID) {
376	if (typeof sID != 'string') {
377	  sID = null;
378	}
379    if (!sID) {
380      _s._wD('soundManager.mute(): Muting all sounds');
381      for (var i=_s.soundIDs.length; i--;) {
382        _s.sounds[_s.soundIDs[i]].mute();
383      }
384      _s.muted = true;
385    } else {
386      if (!_s._idCheck(sID)) {
387	    return false;
388	  }
389      _s._wD('soundManager.mute(): Muting "'+sID+'"');
390      _s.sounds[sID].mute();
391    }
392  };
393
394  this.muteAll = function() {
395    _s.mute();
396  };
397
398  this.unmute = function(sID) {
399    if (typeof sID != 'string') {
400	  sID = null;
401	}
402    if (!sID) {
403      _s._wD('soundManager.unmute(): Unmuting all sounds');
404      for (var i=_s.soundIDs.length; i--;) {
405        _s.sounds[_s.soundIDs[i]].unmute();
406      }
407      _s.muted = false;
408    } else {
409      if (!_s._idCheck(sID)) {
410		return false;
411	  }
412      _s._wD('soundManager.unmute(): Unmuting "'+sID+'"');
413      _s.sounds[sID].unmute();
414    }
415  };
416
417  this.unmuteAll = function() {
418    _s.unmute();
419  };
420
421  this.getMemoryUse = function() {
422    if (_s.flashVersion == 8) {
423      // not supported in Flash 8
424      return 0;
425    }
426    if (_s.o) {
427      return parseInt(_s.o._getMemoryUse(),10);
428    }
429  };
430
431  this.setPolling = function(bPolling) {
432    if (!_s.o || !_s.allowPolling) {
433	  return false;
434	}
435    // _s._wD('soundManager.setPolling('+bPolling+')');
436    _s.o._setPolling(bPolling);
437  };
438
439  this.disable = function(bUnload) {
440    // destroy all functions
441    if (_s._disabled) {
442	  return false;
443	}
444    _s._disabled = true;
445    _s._wD('soundManager.disable(): Disabling all functions - future calls will return false.',1);
446    for (var i=_s.soundIDs.length; i--;) {
447      _s._disableObject(_s.sounds[_s.soundIDs[i]]);
448    }
449    _s.initComplete(); // fire "complete", despite fail
450    _s._disableObject(_s);
451  };
452
453  this.canPlayURL = function(sURL) {
454    return (sURL?(sURL.match(_s.filePattern)?true:false):null);	
455  };
456
457  this.getSoundById = function(sID,suppressDebug) {
458    if (!sID) {
459	  throw new Error('SoundManager.getSoundById(): sID is null/undefined');
460	}
461    var result = _s.sounds[sID];
462    if (!result && !suppressDebug) {
463      _s._wD('"'+sID+'" is an invalid sound ID.',2);
464      // soundManager._wD('trace: '+arguments.callee.caller);
465    }
466    return result;
467  };
468
469  this.onload = function() {
470    // window.onload() equivalent for SM2, ready to create sounds etc.
471    // this is a stub - you can override this in your own external script, eg. soundManager.onload = function() {}
472    soundManager._wD('<em>Warning</em>: soundManager.onload() is undefined.',2);
473  };
474
475  this.onerror = function() {
476    // stub for user handler, called when SM2 fails to load/init
477  };
478
479  // --- "private" methods ---
480
481  this._idCheck = this.getSoundById;
482
483  var _doNothing = function() {
484    return false;
485  };
486  _doNothing._protected = true;
487
488  this._disableObject = function(o) {
489    for (var oProp in o) {
490      if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') {
491		o[oProp] = _doNothing;
492	  }
493    }
494    oProp = null;
495  };
496
497  this._failSafely = function() {
498    // exception handler for "object doesn't support this property or method" or general failure
499    if (!_s._disabled) {
500      _s._wD('soundManager: Failed to initialise.',2);
501      _s.disable();
502    }
503  };
504  
505  this._normalizeMovieURL = function(smURL) {
506    var urlParams = null;
507    if (smURL) {
508      if (smURL.match(/\.swf(\?.*)?$/i)) {
509        urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?')+4);
510        if (urlParams) {
511          return smURL; // assume user knows what they're doing
512        }
513      } else if (smURL.lastIndexOf('/') != smURL.length-1) {
514        smURL = smURL+'/';
515      }
516    }
517    return(smURL && smURL.lastIndexOf('/')!=-1?smURL.substr(0,smURL.lastIndexOf('/')+1):'./')+_s.movieURL;
518  };
519
520  this._getDocument = function() {
521    return (document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName('div')[0]));
522  };
523
524  this._getDocument._protected = true;
525
526  this._createMovie = function(smID,smURL) {
527    if (_s._didAppend && _s._appendSuccess) {
528	  return false; // ignore if already succeeded
529	}
530    if (window.location.href.indexOf('debug=1')+1) {
531	  _s.debugMode = true; // allow force of debug mode via URL
532	}
533    _s._didAppend = true;
534	
535    // safety check for legacy (change to Flash 9 URL)
536    _s._setVersionInfo();
537    var remoteURL = (smURL?smURL:_s.url);
538    var localURL = (_s.altURL?_s.altURL:remoteURL);
539    _s.url = _s._normalizeMovieURL(_s._overHTTP?remoteURL:localURL);
540    smURL = _s.url;
541
542    var specialCase = null;
543    if (_s.useHighPerformance && _s.useHighPerformance != 'always' && navigator.platform.match(/win32/i) && navigator.userAgent.match(/firefox/i)) {
544      specialCase = 'Note: disabling highPerformance, known issues with this browser/OS combo.';
545      _s.useHighPerformance = false;
546    }
547
548    if (_s.useHighPerformance && _s.useMovieStar) {
549	  specialCase = 'Note: disabling highPerformance, not applicable with movieStar mode on';
550	  _s.useHighPerformance = false;
551	}
552
553    var oEmbed = {
554      name: smID,
555      id: smID,
556      src: smURL,
557      width: '100%',
558      height: '100%',
559      quality: 'high',
560      allowScriptAccess: 'always',
561      bgcolor: _s.bgColor,
562      pluginspage: 'http://www.macromedia.com/go/getflashplayer',
563      type: 'application/x-shockwave-flash'
564    };
565
566    var oObject = {
567      id: smID,
568      data: smURL,
569      type: 'application/x-shockwave-flash',
570      width: '100%',
571      height: '100%'
572    };
573
574    var oObjectParams = {
575      movie: smURL,
576      AllowScriptAccess: 'always',
577      quality: 'high',
578      bgcolor: _s.bgColor
579    };
580
581    if (_s.useHighPerformance && !_s.useMovieStar) {
582      oEmbed.wmode = 'transparent';
583      oObjectParams.wmode = 'transparent';
584    }
585
586    var oMovie = null;
587    var tmp = null;
588
589    if (_s.isIE) {
590      // IE is "special".
591      oMovie = document.createElement('div');
592      var movieHTML = '<object id="'+smID+'" data="'+smURL+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+smURL+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(_s.useHighPerformance && !_s.useMovieStar?'<param name="wmode" value="transparent" /> ':'')+'<param name="bgcolor" value="'+_s.bgColor+'" /><!-- --></object>';
593    } else {
594      oMovie = document.createElement('embed');
595      for (tmp in oEmbed) {
596	    if (oEmbed.hasOwnProperty(tmp)) {
597          oMovie.setAttribute(tmp,oEmbed[tmp]);
598		}
599      }
600    }
601
602    var oD = document.createElement('div');
603    oD.id = _s.debugID+'-toggle';
604    var oToggle = {
605      position: 'fixed',
606      bottom: '0px',
607      right: '0px',
608      width: '1.2em',
609      height: '1.2em',
610      lineHeight: '1.2em',
611      margin: '2px',
612      textAlign: 'center',
613      border: '1px solid #999',
614      cursor: 'pointer',
615      background: '#fff',
616      color: '#333',
617      zIndex: 10001
618    };
619
620    oD.appendChild(document.createTextNode('-'));
621    oD.onclick = _s._toggleDebug;
622    oD.title = 'Toggle SM2 debug console';
623
624    if (navigator.userAgent.match(/msie 6/i)) {
625      oD.style.position = 'absolute';
626      oD.style.cursor = 'hand';
627    }
628
629    for (tmp in oToggle) {
630 	  if (oToggle.hasOwnProperty(tmp)) {
631        oD.style[tmp] = oToggle[tmp];
632	  }
633    }
634
635    var appXHTML = 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.';
636
637    var oTarget = _s._getDocument();
638
639    if (oTarget) {
640       
641      _s.oMC = document.getElementById('sm2-container')?document.getElementById('sm2-container'):document.createElement('div');
642
643      if (!_s.oMC.id) {
644        _s.oMC.id = 'sm2-container';
645        _s.oMC.className = 'movieContainer';
646        // "hide" flash movie
647        var s = null;
648        var oEl = null;
649        if (_s.useHighPerformance) {
650          s = {
651 	    	position: 'fixed',
652		    width: '8px',
653            height: '8px', // must be at least 6px for flash to run fast. odd? yes.
654            bottom: '0px',
655            left: '0px',
656	    	zIndex:-1 // sit behind everything else
657          };
658        } else {
659          s = {
660            position: 'absolute',
661		    width: '1px',
662            height: '1px',
663            bottom: '0px',
664            left: '0px'
665          };
666        }
667        var x = null;
668        for (x in s) {
669		  if (s.hasOwnProperty(x)) {
670            _s.oMC.style[x] = s[x];
671		  }
672        }
673        try {
674		  if (!_s.isIE) {
675    	    _s.oMC.appendChild(oMovie);
676		  }
677          oTarget.appendChild(_s.oMC);
678		  if (_s.isIE) {
679			oEl = _s.oMC.appendChild(document.createElement('div'));
680			oEl.className = 'sm2-object-box';
681			oEl.innerHTML = movieHTML;
682          }
683          _s._appendSuccess = true;
684        } catch(e) {
685          throw new Error(appXHTML);
686        }
687      } else {
688        // it's already in the document.
689        _s.oMC.appendChild(oMovie);
690		if (_s.isIE) {
691		  oEl = _s.oMC.appendChild(document.createElement('div'));
692		  oEl.className = 'sm2-object-box';
693		  oEl.innerHTML = movieHTML;
694        }
695        _s._appendSuccess = true;
696      }
697
698      if (!document.getElementById(_s.debugID) && ((!_s._hasConsole||!_s.useConsole)||(_s.useConsole && _s._hasConsole && !_s.consoleOnly))) {
699        var oDebug = document.createElement('div');
700        oDebug.id = _s.debugID;
701        oDebug.style.display = (_s.debugMode?'block':'none');
702        if (_s.debugMode) {
703          try {
704            oTarget.appendChild(oD);
705          } catch(e2) {
706            throw new Error(appXHTML);
707          }
708        }
709        oTarget.appendChild(oDebug);
710      }
711      oTarget = null;
712    }
713
714    if (specialCase) {
715      _s._wD(specialCase);
716    }
717
718    _s._wD('-- SoundManager 2 '+_s.version+(_s.useMovieStar?', MovieStar mode':'')+(_s.useHighPerformance?', high performance mode':'')+' --',1);
719    _s._wD('soundManager._createMovie(): Trying to load '+smURL+(!_s._overHTTP && _s.altURL?'(alternate URL)':''),1);
720  };
721
722  // aliased to this._wD()
723  this._writeDebug = function(sText,sType,bTimestamp) {
724    if (!_s.debugMode) {
725	  return false;
726	}
727    if (typeof bTimestamp != 'undefined' && bTimestamp) {
728      sText = sText + ' | '+new Date().getTime();
729    }
730    if (_s._hasConsole && _s.useConsole) {
731      var sMethod = _s._debugLevels[sType];
732      if (typeof console[sMethod] != 'undefined') {
733        console[sMethod].apply(console,[sText]); // apply() fix for firebug 1.3, so "this" == console
734      } else {
735        console.log(sText);
736      }
737      if (_s.useConsoleOnly) {
738	    return true;
739	  }
740    }
741    var sDID = 'soundmanager-debug';
742    try {
743      var o = document.getElementById(sDID);
744      if (!o) {
745		return false;
746	  }
747      var oItem = document.createElement('div');
748      // sText = sText.replace(/\n/g,'<br />');
749      if (typeof sType == 'undefined') {
750        sType = 0;
751      } else {
752        sType = parseInt(sType,10);
753      }
754      oItem.appendChild(document.createTextNode(sText));
755      if (sType) {
756        if (sType >= 2) {
757		  oItem.style.fontWeight = 'bold';
758		}
759        if (sType == 3) {
760		  oItem.style.color = '#ff3333';
761		}
762      }
763      // o.appendChild(oItem); // top-to-bottom
764      o.insertBefore(oItem,o.firstChild); // bottom-to-top
765    } catch(e) {
766      // oh well
767    }
768    o = null;
769  };
770  this._writeDebug._protected = true;
771  this._wD = this._writeDebug;
772
773  this._wDAlert = function(sText) { alert(sText); };
774
775  if (window.location.href.indexOf('debug=alert')+1 && _s.debugMode) {
776    _s._wD = _s._wDAlert;
777  }
778
779  this._toggleDebug = function() {
780    var o = document.getElementById(_s.debugID);
781    var oT = document.getElementById(_s.debugID+'-toggle');
782    if (!o) {
783	  return false;
784	}
785    if (_s._debugOpen) {
786      // minimize
787      oT.innerHTML = '+';
788      o.style.display = 'none';
789    } else {
790      oT.innerHTML = '-';
791      o.style.display = 'block';
792    }
793    _s._debugOpen = !_s._debugOpen;
794  };
795
796  this._toggleDebug._protected = true;
797
798  this._debug = function() {
799    _s._wD('--- soundManager._debug(): Current sound objects ---',1);
800    for (var i=0,j=_s.soundIDs.length; i<j; i++) {
801      _s.sounds[_s.soundIDs[i]]._debug();
802    }
803  };
804
805  this._debugTS = function(sEventType,bSuccess,sMessage) {
806    // troubleshooter debug hooks
807    if (typeof sm2Debugger != 'undefined') {
808	  try {
809	    sm2Debugger.handleEvent(sEventType,bSuccess,sMessage);
810	  } catch(e) {
811	    // oh well	
812	  }
813    }
814  };
815
816  this._debugTS._protected = true;
817
818  this._mergeObjects = function(oMain,oAdd) {
819    // non-destructive merge
820    var o1 = {}; // clone o1
821    for (var i in oMain) {
822	  if (oMain.hasOwnProperty(i)) {
823        o1[i] = oMain[i];
824	  }
825    }
826    var o2 = (typeof oAdd == 'undefined'?_s.defaultOptions:oAdd);
827    for (var o in o2) {
828      if (o2.hasOwnProperty(o) && typeof o1[o] == 'undefined') {
829		o1[o] = o2[o];
830	  }
831    }
832    return o1;
833  };
834
835  this.createMovie = function(sURL) {
836    if (sURL) {
837      _s.url = sURL;
838    }
839    _s._initMovie();
840  };
841
842  this.go = this.createMovie; // nice alias
843
844  this._initMovie = function() {
845    // attempt to get, or create, movie
846    if (_s.o) {
847	  return false; // pre-init may have fired this function before window.onload(), may already exist
848	}
849    _s.o = _s.getMovie(_s.id); // try to get flash movie (inline markup)
850    if (!_s.o) {
851      // try to create
852      _s._createMovie(_s.id,_s.url);
853      _s.o = _s.getMovie(_s.id);
854    }
855    if (_s.o) {
856      _s._wD('soundManager._initMovie(): Got '+_s.o.nodeName+' element ('+(_s._didAppend?'created via JS':'static HTML')+')',1);
857      _s._wD('soundManager._initMovie(): Waiting for ExternalInterface call from Flash..');
858    }
859  };
860
861  this.waitForExternalInterface = function() {
862    if (_s._waitingForEI) {
863	  return false;
864	}
865    _s._waitingForEI = true;
866    if (_s._tryInitOnFocus && !_s._isFocused) {
867      _s._wD('soundManager: Special case: Flash may not have started due to non-focused tab (Safari is lame), and/or focus cannot be detected. Waiting for focus-related event..');
868      return false;
869    }
870    if (!_s._didInit) {
871      _s._wD('soundManager: Getting impatient, still waiting for Flash.. ;)');
872    }
873    setTimeout(function() {
874      if (!_s._didInit) {
875        _s._wD('soundManager: No Flash response within reasonable time after document load.\nPossible causes: Flash version under 8, no support, or Flash security denying JS-Flash communication.',2);
876        if (!_s._overHTTP) {
877          _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);
878        }
879        _s._debugTS('flashtojs',false,': Timed out'+(_s._overHTTP)?' (Check flash security)':' (No plugin/missing SWF?)');
880      }
881      // if still not initialized and no other options, give up
882      if (!_s._didInit && _s._okToDisable) {
883		_s._failSafely();
884	  }
885    },750);
886  };
887
888  this.handleFocus = function() {
889    if (_s._isFocused || !_s._tryInitOnFocus) {
890	  return true;
891	}
892    _s._okToDisable = true;
893    _s._isFocused = true;
894    _s._wD('soundManager.handleFocus()');
895    if (_s._tryInitOnFocus) {
896      // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented.
897      window.removeEventListener('mousemove',_s.handleFocus,false);
898    }
899    // allow init to restart
900    _s._waitingForEI = false;
901    setTimeout(_s.waitForExternalInterface,500);
902    // detach event
903    if (window.removeEventListener) {
904      window.removeEventListener('focus',_s.handleFocus,false);
905    } else if (window.detachEvent) {
906      window.detachEvent('onfocus',_s.handleFocus);
907    }
908  };
909
910  this.initComplete = function() {
911    if (_s._didInit) {
912	  return false;
913	}
914    _s._didInit = true;
915    _s._wD('-- SoundManager 2 '+(_s._disabled?'failed to load':'loaded')+' ('+(_s._disabled?'security/load error':'OK')+') --',1);
916    if (_s._disabled) {
917      _s._wD('soundManager.initComplete(): calling soundManager.onerror()',1);
918      _s._debugTS('onload',false);
919      _s.onerror.apply(window);
920      return false;
921    } else {
922	  _s._debugTS('onload',true);
923    }
924    if (_s.waitForWindowLoad && !_s._windowLoaded) {
925      _s._wD('soundManager: Waiting for window.onload()');
926      if (window.addEventListener) {
927        window.addEventListener('load',_s.initUserOnload,false);
928      } else if (window.attachEvent) {
929        window.attachEvent('onload',_s.initUserOnload);
930      }
931      return false;
932    } else {
933      if (_s.waitForWindowLoad && _s._windowLoaded) {
934        _s._wD('soundManager: Document already loaded');
935      }
936      _s.initUserOnload();
937    }
938  };
939
940  this.initUserOnload = function() {
941    _s._wD('soundManager.initComplete(): calling soundManager.onload()',1);
942    // call user-defined "onload", scoped to window
943    _s.onload.apply(window);
944    _s._wD('soundManager.onload() complete',1);
945  };
946
947  this.init = function() {
948    _s._wD('-- soundManager.init() --');
949    // called after onload()
950    _s._initMovie();
951    if (_s._didInit) {
952      _s._wD('soundManager.init(): Already called?');
953      return false;
954    }
955    // event cleanup
956    if (window.removeEventListener) {
957      window.removeEventListener('load',_s.beginDelayedInit,false);
958    } else if (window.detachEvent) {
959      window.detachEvent('onload',_s.beginDelayedInit);
960    }
961    try {
962      _s._wD('Attempting to call Flash from JS..');
963      _s.o._externalInterfaceTest(false); // attempt to talk to Flash
964      // _s._wD('Flash ExternalInterface call (JS-Flash) OK',1);
965      if (!_s.allowPolling) {
966	    _s._wD('Polling (whileloading/whileplaying support) is disabled.',1);
967	  }
968      _s.setPolling(true);
969	  if (!_s.debugMode) {
970		_s.o._disableDebug();
971	  }
972      _s.enabled = true;
973      _s._debugTS('jstoflash',true);
974    } catch(e) {
975	  _s._debugTS('jstoflash',false);
976      _s._failSafely();
977      _s.initComplete();
978      return false;
979    }
980    _s.initComplete();
981  };
982
983  this.beginDelayedInit = function() {
984    _s._wD('soundManager.beginDelayedInit(): Document loaded');
985    _s._windowLoaded = true;
986    setTimeout(_s.waitForExternalInterface,500);
987    setTimeout(_s.beginInit,20);
988  };
989
990  this.beginInit = function() {
991    if (_s._initPending) {
992	  return false;
993	}
994    _s.createMovie(); // ensure creation if not already done
995    _s._initMovie();
996    _s._initPending = true;
997    return true;
998  };
999
1000  this.domContentLoaded = function() {
1001    _s._wD('soundManager.domContentLoaded()');
1002    if (document.removeEventListener) {
1003	  document.removeEventListener('DOMContentLoaded',_s.domContentLoaded,false);
1004	}
1005    _s.go();
1006  };
1007
1008  this._externalInterfaceOK = function() {
1009    // callback from flash for confirming that movie loaded, EI is working etc.
1010    if (_s.swfLoaded) {
1011	  return false;
1012	}
1013    _s._wD('soundManager._externalInterfaceOK()');
1014    _s._debugTS('swf',true);
1015    _s._debugTS('flashtojs',true);
1016    _s.swfLoaded = true;
1017    _s._tryInitOnFocus = false;
1018    if (_s.isIE) {
1019      // IE needs a timeout OR delay until window.onload - may need TODO: investigating
1020      setTimeout(_s.init,100);
1021    } else {
1022      _s.init();
1023    }
1024  };
1025
1026  this._setSandboxType = function(sandboxType) {
1027    var sb = _s.sandbox;
1028    sb.type = sandboxType;
1029    sb.description = sb.types[(typeof sb.types[sandboxType] != 'undefined'?sandboxType:'unknown')];
1030    _s._wD('Flash security sandbox type: '+sb.type);
1031    if (sb.type == 'localWithFile') {
1032      sb.noRemote = true;
1033      sb.noLocal = false;
1034      _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);
1035    } else if (sb.type == 'localWithNetwork') {
1036      sb.noRemote = false;
1037      sb.noLocal = true;
1038    } else if (sb.type == 'localTrusted') {
1039      sb.noRemote = false;
1040      sb.noLocal = false;
1041    }
1042  };
1043
1044  this.destruct = function() {
1045    _s._wD('soundManager.destruct()');
1046    _s.disable(true);
1047  };
1048  
1049  // SMSound (sound object)
1050  
1051  SMSound = function(oOptions) {
1052  var _t = this;
1053  this.sID = oOptions.id;
1054  this.url = oOptions.url;
1055  this.options = _s._mergeObjects(oOptions);
1056  this.instanceOptions = this.options; // per-play-instance-specific options
1057  this._iO = this.instanceOptions; // short alias
1058
1059  // assign property defaults (volume, pan etc.)
1060  this.pan = this.options.pan;
1061  this.volume = this.options.volume;
1062
1063  this._debug = function() {
1064    if (_s.debugMode) {
1065    var stuff = null;
1066    var msg = [];
1067    var sF = null;
1068    var sfBracket = null;
1069    var maxLength = 64; // # of characters of function code to show before truncating
1070    for (stuff in _t.options) {
1071      if (_t.options[stuff] !== null) {
1072        if (_t.options[stuff] instanceof Function) {
1073	      // handle functions specially
1074	      sF = _t.options[stuff].toString();
1075	      sF = sF.replace(/\s\s+/g,' '); // normalize spaces
1076	      sfBracket = sF.indexOf('{');
1077	      msg[msg.length] = ' '+stuff+': {'+sF.substr(sfBracket+1,(Math.min(Math.max(sF.indexOf('\n')-1,maxLength),maxLength))).replace(/\n/g,'')+'... }';
1078	    } else {
1079	      msg[msg.length] = ' '+stuff+': '+_t.options[stuff];
1080	    }
1081      }
1082    }
1083    _s._wD('SMSound() merged options: {\n'+msg.join(', \n')+'\n}');
1084    }
1085  };
1086
1087  this._debug();
1088
1089  this.id3 = {
1090   /* 
1091    Name/value pairs set via Flash when available - see reference for names:
1092    http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html
1093    (eg., this.id3.songname or this.id3['songname'])
1094   */
1095  };
1096
1097  this.resetProperties = function(bLoaded) {
1098    _t.bytesLoaded = null;
1099    _t.bytesTotal = null;
1100    _t.position = null;
1101    _t.duration = null;
1102    _t.durationEstimate = null;
1103    _t.loaded = false;
1104    _t.playState = 0;
1105    _t.paused = false;
1106    _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success
1107    _t.muted = false;
1108    _t.didBeforeFinish = false;
1109    _t.didJustBeforeFinish = false;
1110    _t.instanceOptions = {};
1111    _t.instanceCount = 0;
1112    _t.peakData = {
1113      left: 0,
1114      right: 0
1115    };
1116    _t.waveformData = [];
1117    _t.eqData = [];
1118  };
1119
1120  _t.resetProperties();
1121
1122  // --- public methods ---
1123
1124  this.load = function(oOptions) {
1125    if (typeof oOptions != 'undefined') {
1126      _t._iO = _s._mergeObjects(oOptions);
1127      _t.instanceOptions = _t._iO;
1128    } else {
1129      oOptions = _t.options;
1130      _t._iO = oOptions;
1131      _t.instanceOptions = _t._iO;
1132    } 
1133    if (typeof _t._iO.url == 'undefined') {
1134      _t._iO.url = _t.url;
1135    }
1136    _s._wD('soundManager.load(): '+_t._iO.url,1);
1137    if (_t._iO.url == _t.url && _t.readyState !== 0 && _t.readyState != 2) {
1138      _s._wD('soundManager.load(): current URL already assigned.',1);
1139      return false;
1140    }
1141    _t.loaded = false;
1142    _t.readyState = 1;
1143    _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?)
1144    try {
1145      if (_s.flashVersion==8) {
1146        _s.o._load(_t.sID,_t._iO.url,_t._iO.stream,_t._iO.autoPlay,(_t._iO.whileloading?1:0));
1147      } else {
1148        _s.o._load(_t.sID,_t._iO.url,_t._iO.stream?true:false,_t._iO.autoPlay?true:false); // ,(_tO.whileloading?true:false)
1149        if (_t._iO.isMovieStar && _t._iO.autoLoad && !_t._iO.autoPlay) {
1150          // special case: MPEG4 content must start playing to load, then pause to prevent playing.
1151          _t.pause();
1152        }
1153      }
1154    } catch(e) {
1155      _s._wD('SMSound.load(): Exception: JS-Flash communication failed, or JS error.',2);
1156      _s._debugTS('onload',false);
1157      _s.onerror();
1158      _s.disable();
1159    }
1160
1161  };
1162
1163  this.unload = function() {
1164    // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3
1165    // Flash 9/AS3: Close stream, preventing further load
1166    if (_t.readyState !== 0) {
1167      _s._wD('SMSound.unload(): "'+_t.sID+'"');
1168      if (_t.readyState != 2) { // reset if not error
1169        _t.setPosition(0,true); // reset current sound positioning
1170      }
1171      _s.o._unload(_t.sID,_s.nullURL);
1172      // reset load/status flags
1173      _t.resetProperties();
1174    }
1175  };
1176
1177  this.destruct = function() {
1178    // kill sound within Flash
1179    _s._wD('SMSound.destruct(): "'+_t.sID+'"');
1180    _s.o._destroySound(_t.sID);
1181    _s.destroySound(_t.sID,true);
1181 // ensure deletion from controller
1182  };
1183
1184  this.play = function(oOptions) {
1185    if (!oOptions) {
1186	  oOptions = {};
1187    }
1188    _t._iO = _s._mergeObjects(oOptions,_t._iO);
1189    _t._iO = _s._mergeObjects(_t._iO,_t.options);
1190    _t.instanceOptions = _t._iO;
1191    if (_t.playState == 1) {
1192      var allowMulti = _t._iO.multiShot;
1193      if (!allowMulti) {
1194        _s._wD('SMSound.play(): "'+_t.sID+'" already playing (one-shot)',1);
1195        return false;
1196      } else {
1197        _s._wD('SMSound.play(): "'+_t.sID+'" already playing (multi-shot)',1);
1198      }
1199    }
1200    if (!_t.loaded) {
1201      if (_t.readyState === 0) {
1202        _s._wD('SMSound.play(): Attempting to load "'+_t.sID+'"',1);
1203        // try to get this sound playing ASAP
1204        _t._iO.stream = true;
1205        _t._iO.autoPlay = true;
1206        // TODO: need to investigate when false, double-playing
1207        // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here
1208        _t.load(_t._iO); // try to get this sound playing ASAP
1209      } else if (_t.readyState == 2) {
1210        _s._wD('SMSound.play(): Could not load "'+_t.sID+'" - exiting',2);
1211        return false;
1212      } else {
1213        _s._wD('SMSound.play(): "'+_t.sID+'" is loading - attempting to play..',1);
1214      }
1215    } else {
1216      _s._wD('SMSound.play(): "'+_t.sID+'"');
1217    }
1218    if (_t.paused) {
1219      _t.resume();
1220    } else {
1221      _t.playState = 1;
1222      if (!_t.instanceCount || _s.flashVersion == 9) {
1223		_t.instanceCount++;
1224	  }
1225      _t.position = (typeof _t._iO.position != 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);
1226      if (_t._iO.onplay) {
1227		_t._iO.onplay.apply(_t);
1228	  }
1229      _t.setVolume(_t._iO.volume,true); // restrict volume to instance options only
1230      _t.setPan(_t._iO.pan,true);
1231      _s.o._start(_t.sID,_t._iO.loop||1,(_s.flashVersion==9?_t.position:_t.position/1000));
1232    }
1233  };
1234
1235  this.start = this.play; // just for convenience
1236
1237  this.stop = function(bAll) {
1238    if (_t.playState == 1) {
1239      _t.playState = 0;
1240      _t.paused = false;
1241      // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);
1242      if (_t._iO.onstop) {
1243		_t._iO.onstop.apply(_t);
1244	  }
1245      _s.o._stop(_t.sID,bAll);
1246      _t.instanceCount = 0;
1247      _t._iO = {};
1248      // _t.instanceOptions = _t._iO;
1249    }
1250  };
1251
1252  this.setPosition = function(nMsecOffset,bNoDebug) {
1253    if (typeof nMsecOffset == 'undefined') {
1254      nMsecOffset = 0;
1255    }
1256    var offset = Math.min(_t.duration,Math.max(nMsecOffset,0)); // position >= 0 and <= current available (loaded) duration
1257    _t._iO.position = offset;
1258    if (!bNoDebug) {
1259      _s._wD('SMSound.setPosition('+nMsecOffset+')'+(nMsecOffset != offset?', corrected value: '+offset:''));
1260    }
1261    _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)
1262  };
1263
1264  this.pause = function() {
1265    if (_t.paused || _t.playState === 0) {
1266	  return false;
1267	}
1268    _s._wD('SMSound.pause()');
1269    _t.paused = true;
1270    _s.o._pause(_t.sID);
1271    if (_t._iO.onpause) {
1272	  _t._iO.onpause.apply(_t);
1273	}
1274  };
1275
1276  this.resume = function() {
1277    if (!_t.paused || _t.playState === 0) {
1278	  return false;
1279	}
1280    _s._wD('SMSound.resume()');
1281    _t.paused = false;
1282    _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)
1283    if (_t._iO.onresume) {
1284	  _t._iO.onresume.apply(_t);
1285	}
1286  };
1287
1288  this.togglePause = function() {
1289    _s._wD('SMSound.togglePause()');
1290    if (!_t.playState) {
1291      _t.play({position:(_s.flashVersion==9?_t.position:_t.position/1000)});
1292      return false;
1293    }
1294    if (_t.paused) {
1295      _t.resume();
1296    } else {
1297      _t.pause();
1298    }
1299  };
1300
1301  this.setPan = function(nPan,bInstanceOnly) {
1302    if (typeof nPan == 'undefined') {
1303      nPan = 0;
1304    }
1305    if (typeof bInstanceOnly == 'undefined') {
1306      bInstanceOnly = false;
1307    }
1308    _s.o._setPan(_t.sID,nPan);
1309    _t._iO.pan = nPan;
1310    if (!bInstanceOnly) {
1311      _t.pan = nPan;
1312    }
1313  };
1314
1315  this.setVolume = function(nVol,bInstanceOnly) {
1316    if (typeof nVol == 'undefined') {
1317      nVol = 100;
1318    }
1319    if (typeof bInstanceOnly == 'undefined') {
1320      bInstanceOnly = false;
1321    }
1322    _s.o._setVolume(_t.sID,(_s.muted&&!_t.muted)||_t.muted?0:nVol);
1323    _t._iO.volume = nVol;
1324    if (!bInstanceOnly) {
1325      _t.volume = nVol;
1326    }
1327  };
1328
1329  this.mute = function() {
1330    _t.muted = true;
1331    _s.o._setVolume(_t.sID,0);
1332  };
1333
1334  this.unmute = function() {
1335    _t.muted = false;
1336    var hasIO = typeof _t._iO.volume != 'undefined';
1337    _s.o._setVolume(_t.sID,hasIO?_t._iO.volume:_t.options.volume,hasIO?false:true);
1338  };
1339
1340  // --- "private" methods called by Flash ---
1341
1342  this._whileloading = function(nBytesLoaded,nBytesTotal,nDuration) {
1343    if (!_t._iO.isMovieStar) {
1344      _t.bytesLoaded = nBytesLoaded;
1345      _t.bytesTotal = nBytesTotal;
1346      _t.duration = Math.floor(nDuration);
1347      _t.durationEstimate = parseInt((_t.bytesTotal/_t.bytesLoaded)*_t.duration,10); // estimate total time (will only be accurate with CBR MP3s.)
1348      if (_t.readyState != 3 && _t._iO.whileloading) {
1349	_t._iO.whileloading.apply(_t);
1350      }
1351    } else {
1352      _t.bytesLoaded = nBytesLoaded;
1353      _t.bytesTotal = nBytesTotal;
1354      _t.duration = Math.floor(nDuration);
1355      _t.durationEstimate = _t.duration;
1356      if (_t.readyState != 3 && _t._iO.whileloading) {
1357	_t._iO.whileloading.apply(_t);
1358      }
1359    }
1360  };
1361
1362  this._onid3 = function(oID3PropNames,oID3Data) {
1363    // oID3PropNames: string array (names)
1364    // ID3Data: string array (data)
1365    _s._wD('SMSound._onid3(): "'+this.sID+'" ID3 data received.');
1366    var oData = [];
1367    for (var i=0,j=oID3PropNames.length; i<j; i++) {
1368      oData[oID3PropNames[i]] = oID3Data[i];
1369      // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);
1370    }
1371    _t.id3 = _s._mergeObjects(_t.id3,oData);
1372    if (_t._iO.onid3) {
1373      _t._iO.onid3.apply(_t);
1374    }
1375  };
1376
1377  this._whileplaying = function(nPosition,oPeakData,oWaveformData,oEQData) {
1378    if (isNaN(nPosition) || nPosition === null) {
1379      return false; // Flash may return NaN at times
1380    }
1381    _t.position = nPosition;
1382	if (_t._iO.usePeakData && typeof oPeakData != 'undefined' && oPeakData) {
1383	  _t.peakData = {
1384	   left: oPeakData.leftPeak,
1385	   right: oPeakData.rightPeak
1386	  };
1387	}
1388	if (_t._iO.useWaveformData && typeof oWaveformData != 'undefined' && oWaveformData) {
1389	  _t.waveformData = oWaveformData;
1390	  /*
1391	  _t.spectrumData = {
1392	   left: oSpectrumData.left.split(','),
1393	   right: oSpectrumData.right.split(',')
1394	  }
1395	  */
1396	}
1397	if (_t._iO.useEQData && typeof oEQData != 'undefined' && oEQData) {
1398	  _t.eqData = oEQData;
1399	}
1400    if (_t.playState == 1) {
1401      if (_t._iO.whileplaying) {
1402	_t._iO.whileplaying.apply(_t); // flash may call after actual finish
1403      }
1404      if (_t.loaded && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration-_t.position <= _t._iO.onbeforefinishtime) {
1405        _s._wD('duration-position &lt;= onbeforefinishtime: '+_t.duration+' - '+_t.position+' &lt= '+_t._iO.onbeforefinishtime+' ('+(_t.duration-_t.position)+')');
1406        _t._onbeforefinish();
1407      }
1408    }
1409  };
1410
1411  this._onload = function(bSuccess) {
1412    bSuccess = (bSuccess==1?true:false);
1413    _s._wD('SMSound._onload(): "'+_t.sID+'"'+(bSuccess?' loaded.':' failed to load? - '+_t.url));
1414    if (!bSuccess) {
1415      if (_s.sandbox.noRemote === true) {
1416        _s._wD('SMSound._onload(): Reminder: Flash security is denying network/internet access',1);
1417      }
1418      if (_s.sandbox.noLocal === true) {
1419        _s._wD('SMSound._onload(): Reminder: Flash security is denying local access',1);
1420      }
1421    }
1422    _t.loaded = bSuccess;
1423    _t.readyState = bSuccess?3:2;
1424    if (_t._iO.onload) {
1425      _t._iO.onload.apply(_t);
1426    }
1427  };
1428
1429  this._onbeforefinish = function() {
1430    if (!_t.didBeforeFinish) {
1431      _t.didBeforeFinish = true;
1432      if (_t._iO.onbeforefinish) {
1433        _s._wD('SMSound._onbeforefinish(): "'+_t.sID+'"');
1434        _t._iO.onbeforefinish.apply(_t);
1435      }
1436    }
1437  };
1438
1439  this._onjustbeforefinish = function(msOffset) {
1440    // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187)
1441    if (!_t.didJustBeforeFinish) {
1442      _t.didJustBeforeFinish = true;
1443      if (_t._iO.onjustbeforefinish) {
1444        _s._wD('SMSound._onjustbeforefinish(): "'+_t.sID+'"');
1445        _t._iO.onjustbeforefinish.apply(_t);
1446      }
1447    }
1448  };
1449
1450  this._onfinish = function() {
1451    // sound has finished playing
1452
1453    // TODO: calling user-defined onfinish() should happen after setPosition(0)
1454    // OR: onfinish() and then setPosition(0) is bad.
1455
1456    if (_t._iO.onbeforefinishcomplete) {
1457      _t._iO.onbeforefinishcomplete.apply(_t);
1458    }
1459    // reset some state items
1460    _t.didBeforeFinish = false;
1461    _t.didJustBeforeFinish = false;
1462    if (_t.instanceCount) {
1463      _t.instanceCount--;
1464      if (!_t.instanceCount) {
1465        // reset instance options
1466        // _t.setPosition(0);
1467        _t.playState = 0;
1468        _t.paused = false;
1469        _t.instanceCount = 0;
1470        _t.instanceOptions = {};
1471        if (_t._iO.onfinish) {
1472          _s._wD('SMSound._onfinish(): "'+_t.sID+'"');
1473          _t._iO.onfinish.apply(_t);
1474        }
1475      }
1476    } else {
1477      // _t.setPosition(0);
1478    }
1479  };
1480
1481  this._onmetadata = function(oMetaData) {
1482    // movieStar mode only
1483    _s._wD('SMSound.onmetadata()');
1484    // Contains a subset of metadata. Note that files may have their own unique metadata.
1485    // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html
1486    if (!oMetaData.width && !oMetaData.height) {
1487	  _s._wD('No width/height given, assuming defaults');
1488	  oMetaData.width = 320;
1489	  oMetaData.height = 240;
1490    }
1491    _t.metadata = oMetaData; // potentially-large object from flash
1492    _t.width = oMetaData.width;
1493    _t.height = oMetaData.height;
1494    if (_t._iO.onmetadata) {
1495      _s._wD('SMSound._onmetadata(): "'+_t.sID+'"');
1496      _t._iO.onmetadata.apply(_t);
1497    }
1498    _s._wD('SMSound.onmetadata() complete');
1499  };
1500
1501  }; // SMSound()
1502
1503  // register a few event handlers
1504  if (window.addEventListener) {
1505    window.addEventListener('focus',_s.handleFocus,false);
1506    window.addEventListener('load',_s.beginDelayedInit,false);
1507    window.addEventListener('unload',_s.destruct,false);
1508    if (_s._tryInitOnFocus) {
1509      window.addEventListener('mousemove',_s.handleFocus,false); // massive Safari focus hack
1510    }
1511  } else if (window.attachEvent) {
1512    window.attachEvent('onfocus',_s.handleFocus);
1513    window.attachEvent('onload',_s.beginDelayedInit);
1514    window.attachEvent('unload',_s.destruct);
1515  } else {
1516    // no add/attachevent support - safe to assume no JS -> Flash either.
1517    _s._debugTS('onload',false);
1518    soundManager.onerror();
1519    soundManager.disable();
1520  }
1521
1522  if (document.addEventListener) {
1523	document.addEventListener('DOMContentLoaded',_s.domContentLoaded,false);
1524  }
1525
1526} // SoundManager()
1527
1528soundManager = new SoundManager();
1529

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.