]>
jfr.im git - irc/quakenet/qwebirc.git/blob - static/js/soundmanager2.js
508d461770d04696ed1872fe7517fd30834ae327
2 SoundManager 2: Javascript Sound for the Web
3 --------------------------------------------
4 http://schillmania.com/projects/soundmanager2/
6 Copyright (c) 2008, Scott Schiller. All rights reserved.
7 Code licensed under the BSD License:
8 http://schillmania.com/projects/soundmanager2/license.txt
13 var soundManager
= null ;
15 function SoundManager ( smURL
, smID
) {
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)
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.
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.
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
64 // jslint global declarations
65 /*global sm2Debugger, alert, console, document, navigator, setTimeout, window */
67 var SMSound
= null ; // defined later
71 this . versionNumber
= 'V2.93a.20090117' ;
75 this . swfLoaded
= false ;
78 this . id
= ( smID
|| 'sm2movie' );
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 ;
98 flash8 : /\.mp3(\?.*)?$/i ,
99 flash9 : /\.mp3(\?.*)?$/i
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' );
105 this . filePattern
= null ;
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)'
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
;
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
);
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 ;
142 _s
. useMovieStar
= false ;
143 _s
. features
. movieStar
= false ;
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 );
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
;
157 this . useAltURL
= ! this . _overHTTP
; // use altURL if not "online"
159 var flashCPLink
= 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html' ;
161 // --- public methods ---
163 this . supported = function () {
164 return ( _s
. _didInit
&& ! _s
. _disabled
);
167 this . getMovie = function ( smID
) {
168 return _s
. isIE
? window
[ smID
]:( _s
. isSafari
? document
. getElementById ( smID
)|| document
[ smID
]: document
. getElementById ( smID
));
171 this . loadFromXML = function ( sXmlUrl
) {
173 _s
. o
. _loadFromXML ( sXmlUrl
);
180 this . createSound = function ( oOptions
) {
182 throw new Error ( 'soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods' );
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 ]};
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
];
195 if ( _s
. flashVersion
> 8 && _s
. useMovieStar
) {
196 if ( _tO
. isMovieStar
=== null ) {
197 _tO
. isMovieStar
= ( _tO
. url
. match ( _s
. netStreamPattern
)? true : false );
199 if ( _tO
. isMovieStar
) {
200 _s
. _wD ( 'soundManager.createSound(): using MovieStar handling' );
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 ;
209 _s
. sounds
[ _tO
. id
] = new SMSound ( _tO
);
210 _s
. soundIDs
[ _s
. soundIDs
. length
] = _tO
. id
;
212 if ( _s
. flashVersion
== 8 ) {
213 _s
. o
. _createSound ( _tO
. id
, _tO
. onjustbeforefinishtime
);
215 _s
. o
. _createSound ( _tO
. id
, _tO
. url
, _tO
. onjustbeforefinishtime
, _tO
. usePeakData
, _tO
. useWaveformData
, _tO
. useEQData
, _tO
. isMovieStar
,( _tO
. isMovieStar
? _tO
. useVideo : false ));
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
);
224 _s
. sounds
[ _tO
. id
]. play ();
226 return _s
. sounds
[ _tO
. id
];
229 this . createVideo = function ( oOptions
) {
230 if ( arguments
. length
== 2 ) {
231 oOptions
= { 'id' : arguments
[ 0 ], 'url' : arguments
[ 1 ]};
233 if ( _s
. flashVersion
>= 9 ) {
234 oOptions
. isMovieStar
= true ;
235 oOptions
. useVideo
= true ;
237 _s
. _wD ( 'soundManager.createVideo(): flash 9 required for video. Exiting.' , 2 );
240 if (! _s
. useMovieStar
) {
241 _s
. _wD ( 'soundManager.createVideo(): MovieStar mode not enabled. Exiting.' , 2 );
243 return _s
. createSound ( oOptions
);
246 this . destroySound = function ( sID
, bFromSound
) {
247 // explicitly destroy a sound before normal page unload, etc.
248 if (! _s
. _idCheck ( sID
)) {
251 for ( var i
= 0 ; i
< _s
. soundIDs
. length
; i
++) {
252 if ( _s
. soundIDs
[ i
] == sID
) {
253 _s
. soundIDs
. splice ( i
, 1 );
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 ();
263 // ignore if being called from SMSound instance
264 _s
. sounds
[ sID
]. destruct ();
266 delete _s
. sounds
[ sID
];
269 this . destroyVideo
= this . destroySound
;
271 this . load = function ( sID
, oOptions
) {
272 if (! _s
. _idCheck ( sID
)) {
275 _s
. sounds
[ sID
]. load ( oOptions
);
278 this . unload = function ( sID
) {
279 if (! _s
. _idCheck ( sID
)) {
282 _s
. sounds
[ sID
]. unload ();
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');
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 );
294 _s
. createSound ( oOptions
);
299 _s
. sounds
[ sID
]. play ( oOptions
);
302 this . start
= this . play
; // just for convenience
304 this . setPosition = function ( sID
, nMsecOffset
) {
305 if (! _s
. _idCheck ( sID
)) {
308 _s
. sounds
[ sID
]. setPosition ( nMsecOffset
);
311 this . stop = function ( sID
) {
312 if (! _s
. _idCheck ( sID
)) {
315 _s
. _wD ( 'soundManager.stop(' + sID
+ ')' , 1 );
316 _s
. sounds
[ sID
]. stop ();
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
328 this . pause = function ( sID
) {
329 if (! _s
. _idCheck ( sID
)) {
332 _s
. sounds
[ sID
]. pause ();
335 this . pauseAll = function () {
336 for ( var i
= _s
. soundIDs
. length
; i
--;) {
337 _s
. sounds
[ _s
. soundIDs
[ i
]]. pause ();
341 this . resume = function ( sID
) {
342 if (! _s
. _idCheck ( sID
)) {
345 _s
. sounds
[ sID
]. resume ();
348 this . resumeAll = function () {
349 for ( var i
= _s
. soundIDs
. length
; i
--;) {
350 _s
. sounds
[ _s
. soundIDs
[ i
]]. resume ();
354 this . togglePause = function ( sID
) {
355 if (! _s
. _idCheck ( sID
)) {
358 _s
. sounds
[ sID
]. togglePause ();
361 this . setPan = function ( sID
, nPan
) {
362 if (! _s
. _idCheck ( sID
)) {
365 _s
. sounds
[ sID
]. setPan ( nPan
);
368 this . setVolume = function ( sID
, nVol
) {
369 if (! _s
. _idCheck ( sID
)) {
372 _s
. sounds
[ sID
]. setVolume ( nVol
);
375 this . mute = function ( sID
) {
376 if ( typeof sID
!= 'string' ) {
380 _s
. _wD ( 'soundManager.mute(): Muting all sounds' );
381 for ( var i
= _s
. soundIDs
. length
; i
--;) {
382 _s
. sounds
[ _s
. soundIDs
[ i
]]. mute ();
386 if (! _s
. _idCheck ( sID
)) {
389 _s
. _wD ( 'soundManager.mute(): Muting "' + sID
+ '"' );
390 _s
. sounds
[ sID
]. mute ();
394 this . muteAll = function () {
398 this . unmute = function ( sID
) {
399 if ( typeof sID
!= 'string' ) {
403 _s
. _wD ( 'soundManager.unmute(): Unmuting all sounds' );
404 for ( var i
= _s
. soundIDs
. length
; i
--;) {
405 _s
. sounds
[ _s
. soundIDs
[ i
]]. unmute ();
409 if (! _s
. _idCheck ( sID
)) {
412 _s
. _wD ( 'soundManager.unmute(): Unmuting "' + sID
+ '"' );
413 _s
. sounds
[ sID
]. unmute ();
417 this . unmuteAll = function () {
421 this . getMemoryUse = function () {
422 if ( _s
. flashVersion
== 8 ) {
423 // not supported in Flash 8
427 return parseInt ( _s
. o
. _getMemoryUse (), 10 );
431 this . setPolling = function ( bPolling
) {
432 if (! _s
. o
|| ! _s
. allowPolling
) {
435 // _s._wD('soundManager.setPolling('+bPolling+')');
436 _s
. o
. _setPolling ( bPolling
);
439 this . disable = function ( bUnload
) {
440 // destroy all functions
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
]]);
449 _s
. initComplete (); // fire "complete", despite fail
450 _s
. _disableObject ( _s
);
453 this . canPlayURL = function ( sURL
) {
454 return ( sURL
?( sURL
. match ( _s
. filePattern
)? true : false ): null );
457 this . getSoundById = function ( sID
, suppressDebug
) {
459 throw new Error ( 'SoundManager.getSoundById(): sID is null/undefined' );
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);
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 );
475 this . onerror = function () {
476 // stub for user handler, called when SM2 fails to load/init
479 // --- "private" methods ---
481 this . _idCheck
= this . getSoundById
;
483 var _doNothing = function () {
486 _doNothing
. _protected
= true ;
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
;
497 this . _failSafely = function () {
498 // exception handler for "object doesn't support this property or method" or general failure
500 _s
. _wD ( 'soundManager: Failed to initialise.' , 2 );
505 this . _normalizeMovieURL = function ( smURL
) {
506 var urlParams
= null ;
508 if ( smURL
. match ( /\.swf(\?.*)?$/i )) {
509 urlParams
= smURL
. substr ( smURL
. toLowerCase (). lastIndexOf ( '.swf?' )+ 4 );
511 return smURL
; // assume user knows what they're doing
513 } else if ( smURL
. lastIndexOf ( '/' ) != smURL
. length
- 1 ) {
517 return ( smURL
&& smURL
. lastIndexOf ( '/' )!=- 1 ? smURL
. substr ( 0 , smURL
. lastIndexOf ( '/' )+ 1 ): './' )+ _s
. movieURL
;
520 this . _getDocument = function () {
521 return ( document
. body
? document
. body :( document
. documentElement
? document
. documentElement : document
. getElementsByTagName ( 'div' )[ 0 ]));
524 this . _getDocument
. _protected
= true ;
526 this . _createMovie = function ( smID
, smURL
) {
527 if ( _s
. _didAppend
&& _s
. _appendSuccess
) {
528 return false ; // ignore if already succeeded
530 if ( window
. location
. href
. indexOf ( 'debug=1' )+ 1 ) {
531 _s
. debugMode
= true ; // allow force of debug mode via URL
533 _s
. _didAppend
= true ;
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
);
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 ;
548 if ( _s
. useHighPerformance
&& _s
. useMovieStar
) {
549 specialCase
= 'Note: disabling highPerformance, not applicable with movieStar mode on' ;
550 _s
. useHighPerformance
= false ;
560 allowScriptAccess : 'always' ,
562 pluginspage : 'http://www.macromedia.com/go/getflashplayer' ,
563 type : 'application/x-shockwave-flash'
569 type : 'application/x-shockwave-flash' ,
574 var oObjectParams
= {
576 AllowScriptAccess : 'always' ,
581 if ( _s
. useHighPerformance
&& ! _s
. useMovieStar
) {
582 oEmbed
. wmode
= 'transparent' ;
583 oObjectParams
. wmode
= 'transparent' ;
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>' ;
594 oMovie
= document
. createElement ( 'embed' );
595 for ( tmp
in oEmbed
) {
596 if ( oEmbed
. hasOwnProperty ( tmp
)) {
597 oMovie
. setAttribute ( tmp
, oEmbed
[ tmp
]);
602 var oD
= document
. createElement ( 'div' );
603 oD
. id
= _s
. debugID
+ '-toggle' ;
613 border : '1px solid #999' ,
620 oD
. appendChild ( document
. createTextNode ( '-' ));
621 oD
. onclick
= _s
. _toggleDebug
;
622 oD
. title
= 'Toggle SM2 debug console' ;
624 if ( navigator
. userAgent
. match (/ msie
6 / i
)) {
625 oD
. style
. position
= 'absolute' ;
626 oD
. style
. cursor
= 'hand' ;
629 for ( tmp
in oToggle
) {
630 if ( oToggle
. hasOwnProperty ( tmp
)) {
631 oD
. style
[ tmp
] = oToggle
[ tmp
];
635 var appXHTML
= 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.' ;
637 var oTarget
= _s
. _getDocument ();
641 _s
. oMC
= document
. getElementById ( 'sm2-container' )? document
. getElementById ( 'sm2-container' ): document
. createElement ( 'div' );
644 _s
. oMC
. id
= 'sm2-container' ;
645 _s
. oMC
. className
= 'movieContainer' ;
646 // "hide" flash movie
649 if ( _s
. useHighPerformance
) {
653 height : '8px' , // must be at least 6px for flash to run fast. odd? yes.
656 zIndex :- 1 // sit behind everything else
660 position : 'absolute' ,
669 if ( s
. hasOwnProperty ( x
)) {
670 _s
. oMC
. style
[ x
] = s
[ x
];
675 _s
. oMC
. appendChild ( oMovie
);
677 oTarget
. appendChild ( _s
. oMC
);
679 oEl
= _s
. oMC
. appendChild ( document
. createElement ( 'div' ));
680 oEl
. className
= 'sm2-object-box' ;
681 oEl
. innerHTML
= movieHTML
;
683 _s
. _appendSuccess
= true ;
685 throw new Error ( appXHTML
);
688 // it's already in the document.
689 _s
. oMC
. appendChild ( oMovie
);
691 oEl
= _s
. oMC
. appendChild ( document
. createElement ( 'div' ));
692 oEl
. className
= 'sm2-object-box' ;
693 oEl
. innerHTML
= movieHTML
;
695 _s
. _appendSuccess
= true ;
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' );
704 oTarget
. appendChild ( oD
);
706 throw new Error ( appXHTML
);
709 oTarget
. appendChild ( oDebug
);
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 );
722 // aliased to this._wD()
723 this . _writeDebug = function ( sText
, sType
, bTimestamp
) {
727 if ( typeof bTimestamp
!= 'undefined' && bTimestamp
) {
728 sText
= sText
+ ' | ' + new Date (). getTime ();
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
737 if ( _s
. useConsoleOnly
) {
741 var sDID
= 'soundmanager-debug' ;
743 var o
= document
. getElementById ( sDID
);
747 var oItem
= document
. createElement ( 'div' );
748 // sText = sText.replace(/\n/g,'<br />');
749 if ( typeof sType
== 'undefined' ) {
752 sType
= parseInt ( sType
, 10 );
754 oItem
. appendChild ( document
. createTextNode ( sText
));
757 oItem
. style
. fontWeight
= 'bold' ;
760 oItem
. style
. color
= '#ff3333' ;
763 // o.appendChild(oItem); // top-to-bottom
764 o
. insertBefore ( oItem
, o
. firstChild
); // bottom-to-top
770 this . _writeDebug
. _protected
= true ;
771 this . _wD
= this . _writeDebug
;
773 this . _wDAlert = function ( sText
) { alert ( sText
); };
775 if ( window
. location
. href
. indexOf ( 'debug=alert' )+ 1 && _s
. debugMode
) {
776 _s
. _wD
= _s
. _wDAlert
;
779 this . _toggleDebug = function () {
780 var o
= document
. getElementById ( _s
. debugID
);
781 var oT
= document
. getElementById ( _s
. debugID
+ '-toggle' );
788 o
. style
. display
= 'none' ;
791 o
. style
. display
= 'block' ;
793 _s
. _debugOpen
= ! _s
. _debugOpen
;
796 this . _toggleDebug
. _protected
= true ;
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 ();
805 this . _debugTS = function ( sEventType
, bSuccess
, sMessage
) {
806 // troubleshooter debug hooks
807 if ( typeof sm2Debugger
!= 'undefined' ) {
809 sm2Debugger
. handleEvent ( sEventType
, bSuccess
, sMessage
);
816 this . _debugTS
. _protected
= true ;
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
)) {
826 var o2
= ( typeof oAdd
== 'undefined' ? _s
. defaultOptions : oAdd
);
828 if ( o2
. hasOwnProperty ( o
) && typeof o1
[ o
] == 'undefined' ) {
835 this . createMovie = function ( sURL
) {
842 this . go
= this . createMovie
; // nice alias
844 this . _initMovie = function () {
845 // attempt to get, or create, movie
847 return false ; // pre-init may have fired this function before window.onload(), may already exist
849 _s
. o
= _s
. getMovie ( _s
. id
); // try to get flash movie (inline markup)
852 _s
. _createMovie ( _s
. id
, _s
. url
);
853 _s
. o
= _s
. getMovie ( _s
. id
);
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..' );
861 this . waitForExternalInterface = function () {
862 if ( _s
. _waitingForEI
) {
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..' );
871 _s
. _wD ( 'soundManager: Getting impatient, still waiting for Flash.. ;)' );
873 setTimeout ( function () {
875 _s
. _wD ( 'soundManager: No Flash response within reasonable time after document load. \n Possible causes: Flash version under 8, no support, or Flash security denying JS-Flash communication.' , 2 );
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 );
879 _s
. _debugTS ( 'flashtojs' , false , ': Timed out' +( _s
. _overHTTP
)? ' (Check flash security)' : ' (No plugin/missing SWF?)' );
881 // if still not initialized and no other options, give up
882 if (! _s
. _didInit
&& _s
. _okToDisable
) {
888 this . handleFocus = function () {
889 if ( _s
. _isFocused
|| ! _s
. _tryInitOnFocus
) {
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 );
899 // allow init to restart
900 _s
. _waitingForEI
= false ;
901 setTimeout ( _s
. waitForExternalInterface
, 500 );
903 if ( window
. removeEventListener
) {
904 window
. removeEventListener ( 'focus' , _s
. handleFocus
, false );
905 } else if ( window
. detachEvent
) {
906 window
. detachEvent ( 'onfocus' , _s
. handleFocus
);
910 this . initComplete = function () {
915 _s
. _wD ( '-- SoundManager 2 ' +( _s
. _disabled
? 'failed to load' : 'loaded' )+ ' (' +( _s
. _disabled
? 'security/load error' : 'OK' )+ ') --' , 1 );
917 _s
. _wD ( 'soundManager.initComplete(): calling soundManager.onerror()' , 1 );
918 _s
. _debugTS ( 'onload' , false );
919 _s
. onerror
. apply ( window
);
922 _s
. _debugTS ( 'onload' , true );
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
);
933 if ( _s
. waitForWindowLoad
&& _s
. _windowLoaded
) {
934 _s
. _wD ( 'soundManager: Document already loaded' );
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 );
947 this . init = function () {
948 _s
. _wD ( '-- soundManager.init() --' );
949 // called after onload()
952 _s
. _wD ( 'soundManager.init(): Already called?' );
956 if ( window
. removeEventListener
) {
957 window
. removeEventListener ( 'load' , _s
. beginDelayedInit
, false );
958 } else if ( window
. detachEvent
) {
959 window
. detachEvent ( 'onload' , _s
. beginDelayedInit
);
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 );
970 _s
. o
. _disableDebug ();
973 _s
. _debugTS ( 'jstoflash' , true );
975 _s
. _debugTS ( 'jstoflash' , false );
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 );
990 this . beginInit = function () {
991 if ( _s
. _initPending
) {
994 _s
. createMovie (); // ensure creation if not already done
996 _s
. _initPending
= true ;
1000 this . domContentLoaded = function () {
1001 _s
. _wD ( 'soundManager.domContentLoaded()' );
1002 if ( document
. removeEventListener
) {
1003 document
. removeEventListener ( 'DOMContentLoaded' , _s
. domContentLoaded
, false );
1008 this . _externalInterfaceOK = function () {
1009 // callback from flash for confirming that movie loaded, EI is working etc.
1013 _s
. _wD ( 'soundManager._externalInterfaceOK()' );
1014 _s
. _debugTS ( 'swf' , true );
1015 _s
. _debugTS ( 'flashtojs' , true );
1016 _s
. swfLoaded
= true ;
1017 _s
. _tryInitOnFocus
= false ;
1019 // IE needs a timeout OR delay until window.onload - may need TODO: investigating
1020 setTimeout ( _s
. init
, 100 );
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' ) {
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 ;
1038 } else if ( sb
. type
== 'localTrusted' ) {
1039 sb
. noRemote
= false ;
1044 this . destruct = function () {
1045 _s
. _wD ( 'soundManager.destruct()' );
1049 // SMSound (sound object)
1051 SMSound = function ( oOptions
) {
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
1059 // assign property defaults (volume, pan etc.)
1060 this . pan
= this . options
. pan
;
1061 this . volume
= this . options
. volume
;
1063 this . _debug = function () {
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 , '' )+ '... }' ;
1079 msg
[ msg
. length
] = ' ' + stuff
+ ': ' + _t
. options
[ stuff
];
1083 _s
. _wD ( 'SMSound() merged options: { \n ' + msg
. join ( ', \n ' )+ ' \n }' );
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'])
1097 this . resetProperties = function ( bLoaded
) {
1098 _t
. bytesLoaded
= null ;
1099 _t
. bytesTotal
= null ;
1102 _t
. durationEstimate
= null ;
1106 _t
. readyState
= 0 ; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success
1108 _t
. didBeforeFinish
= false ;
1109 _t
. didJustBeforeFinish
= false ;
1110 _t
. instanceOptions
= {};
1111 _t
. instanceCount
= 0 ;
1116 _t
. waveformData
= [];
1120 _t
. resetProperties ();
1122 // --- public methods ---
1124 this . load = function ( oOptions
) {
1125 if ( typeof oOptions
!= 'undefined' ) {
1126 _t
. _iO
= _s
. _mergeObjects ( oOptions
);
1127 _t
. instanceOptions
= _t
. _iO
;
1129 oOptions
= _t
. options
;
1131 _t
. instanceOptions
= _t
. _iO
;
1133 if ( typeof _t
. _iO
. url
== 'undefined' ) {
1134 _t
. _iO
. url
= _t
. url
;
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 );
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?)
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 ));
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.
1155 _s
. _wD ( 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.' , 2 );
1156 _s
. _debugTS ( 'onload' , false );
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
1171 _s
. o
. _unload ( _t
. sID
, _s
. nullURL
);
1172 // reset load/status flags
1173 _t
. resetProperties ();
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 ); // ensure deletion from controller
1184 this . play = function ( oOptions
) {
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
;
1194 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" already playing (one-shot)' , 1 );
1197 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" already playing (multi-shot)' , 1 );
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 );
1213 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" is loading - attempting to play..' , 1 );
1216 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '"' );
1222 if (! _t
. instanceCount
|| _s
. flashVersion
== 9 ) {
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
);
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 ));
1235 this . start
= this . play
; // just for convenience
1237 this . stop = function ( bAll
) {
1238 if ( _t
. playState
== 1 ) {
1241 // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);
1242 if ( _t
. _iO
. onstop
) {
1243 _t
. _iO
. onstop
. apply ( _t
);
1245 _s
. o
. _stop ( _t
. sID
, bAll
);
1246 _t
. instanceCount
= 0 ;
1248 // _t.instanceOptions = _t._iO;
1252 this . setPosition = function ( nMsecOffset
, bNoDebug
) {
1253 if ( typeof nMsecOffset
== 'undefined' ) {
1256 var offset
= Math
. min ( _t
. duration
, Math
. max ( nMsecOffset
, 0 )); // position >= 0 and <= current available (loaded) duration
1257 _t
. _iO
. position
= offset
;
1259 _s
. _wD ( 'SMSound.setPosition(' + nMsecOffset
+ ')' +( nMsecOffset
!= offset
? ', corrected value: ' + offset : '' ));
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
)
1264 this . pause = function () {
1265 if ( _t
. paused
|| _t
. playState
=== 0 ) {
1268 _s
. _wD ( 'SMSound.pause()' );
1270 _s
. o
. _pause ( _t
. sID
);
1271 if ( _t
. _iO
. onpause
) {
1272 _t
. _iO
. onpause
. apply ( _t
);
1276 this . resume = function () {
1277 if (! _t
. paused
|| _t
. playState
=== 0 ) {
1280 _s
. _wD ( 'SMSound.resume()' );
1282 _s
. o
. _pause ( _t
. sID
); // flash method is toggle-based (pause/resume)
1283 if ( _t
. _iO
. onresume
) {
1284 _t
. _iO
. onresume
. apply ( _t
);
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 )});
1301 this . setPan = function ( nPan
, bInstanceOnly
) {
1302 if ( typeof nPan
== 'undefined' ) {
1305 if ( typeof bInstanceOnly
== 'undefined' ) {
1306 bInstanceOnly
= false ;
1308 _s
. o
. _setPan ( _t
. sID
, nPan
);
1310 if (! bInstanceOnly
) {
1315 this . setVolume = function ( nVol
, bInstanceOnly
) {
1316 if ( typeof nVol
== 'undefined' ) {
1319 if ( typeof bInstanceOnly
== 'undefined' ) {
1320 bInstanceOnly
= false ;
1322 _s
. o
. _setVolume ( _t
. sID
,( _s
. muted
&&! _t
. muted
)|| _t
. muted
? 0 : nVol
);
1323 _t
. _iO
. volume
= nVol
;
1324 if (! bInstanceOnly
) {
1329 this . mute = function () {
1331 _s
. o
. _setVolume ( _t
. sID
, 0 );
1334 this . unmute = function () {
1336 var hasIO
= typeof _t
. _iO
. volume
!= 'undefined' ;
1337 _s
. o
. _setVolume ( _t
. sID
, hasIO
? _t
. _iO
. volume : _t
. options
. volume
, hasIO
? false : true );
1340 // --- "private" methods called by Flash ---
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
);
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
);
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.' );
1367 for ( var i
= 0 , j
= oID3PropNames
. length
; i
< j
; i
++) {
1368 oData
[ oID3PropNames
[ i
]] = oID3Data
[ i
];
1369 // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);
1371 _t
. id3
= _s
. _mergeObjects ( _t
. id3
, oData
);
1373 _t
. _iO
. onid3
. apply ( _t
);
1377 this . _whileplaying = function ( nPosition
, oPeakData
, oWaveformData
, oEQData
) {
1378 if ( isNaN ( nPosition
) || nPosition
=== null ) {
1379 return false ; // Flash may return NaN at times
1381 _t
. position
= nPosition
;
1382 if ( _t
. _iO
. usePeakData
&& typeof oPeakData
!= 'undefined' && oPeakData
) {
1384 left : oPeakData
. leftPeak
,
1385 right : oPeakData
. rightPeak
1388 if ( _t
. _iO
. useWaveformData
&& typeof oWaveformData
!= 'undefined' && oWaveformData
) {
1389 _t
. waveformData
= oWaveformData
;
1392 left: oSpectrumData.left.split(','),
1393 right: oSpectrumData.right.split(',')
1397 if ( _t
. _iO
. useEQData
&& typeof oEQData
!= 'undefined' && oEQData
) {
1398 _t
. eqData
= oEQData
;
1400 if ( _t
. playState
== 1 ) {
1401 if ( _t
. _iO
. whileplaying
) {
1402 _t
. _iO
. whileplaying
. apply ( _t
); // flash may call after actual finish
1404 if ( _t
. loaded
&& _t
. _iO
. onbeforefinish
&& _t
. _iO
. onbeforefinishtime
&& ! _t
. didBeforeFinish
&& _t
. duration
- _t
. position
<= _t
. _iO
. onbeforefinishtime
) {
1405 _s
. _wD ( 'duration-position <= onbeforefinishtime: ' + _t
. duration
+ ' - ' + _t
. position
+ ' <= ' + _t
. _iO
. onbeforefinishtime
+ ' (' +( _t
. duration
- _t
. position
)+ ')' );
1406 _t
. _onbeforefinish ();
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
));
1415 if ( _s
. sandbox
. noRemote
=== true ) {
1416 _s
. _wD ( 'SMSound._onload(): Reminder: Flash security is denying network/internet access' , 1 );
1418 if ( _s
. sandbox
. noLocal
=== true ) {
1419 _s
. _wD ( 'SMSound._onload(): Reminder: Flash security is denying local access' , 1 );
1422 _t
. loaded
= bSuccess
;
1423 _t
. readyState
= bSuccess
? 3 : 2 ;
1424 if ( _t
. _iO
. onload
) {
1425 _t
. _iO
. onload
. apply ( _t
);
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
);
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
);
1450 this . _onfinish = function () {
1451 // sound has finished playing
1453 // TODO: calling user-defined onfinish() should happen after setPosition(0)
1454 // OR: onfinish() and then setPosition(0) is bad.
1456 if ( _t
. _iO
. onbeforefinishcomplete
) {
1457 _t
. _iO
. onbeforefinishcomplete
. apply ( _t
);
1459 // reset some state items
1460 _t
. didBeforeFinish
= false ;
1461 _t
. didJustBeforeFinish
= false ;
1462 if ( _t
. instanceCount
) {
1464 if (! _t
. instanceCount
) {
1465 // reset instance options
1466 // _t.setPosition(0);
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
);
1477 // _t.setPosition(0);
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 ;
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
);
1498 _s
. _wD ( 'SMSound.onmetadata() complete' );
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
1511 } else if ( window
. attachEvent
) {
1512 window
. attachEvent ( 'onfocus' , _s
. handleFocus
);
1513 window
. attachEvent ( 'onload' , _s
. beginDelayedInit
);
1514 window
. attachEvent ( 'unload' , _s
. destruct
);
1516 // no add/attachevent support - safe to assume no JS -> Flash either.
1517 _s
. _debugTS ( 'onload' , false );
1518 soundManager
. onerror ();
1519 soundManager
. disable ();
1522 if ( document
. addEventListener
) {
1523 document
. addEventListener ( 'DOMContentLoaded' , _s
. domContentLoaded
, false );
1528 soundManager
= new SoundManager ();