]>
jfr.im git - irc/quakenet/qwebirc.git/blob - static/js/soundmanager2.js
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, '#000000' useful if showing on-screen/full-screen video etc.
26 this . useHighPerformance
= false ; // position:fixed flash movie gives increased js/flash speed
27 this . flashLoadTimeout
= 750 ; // ms to wait for flash movie to load before failing (0 = infinity)
28 this . wmode
= null ; // mode to render the flash movie in - null, transparent, opaque (last two allow layering of HTML on top)
29 this . allowFullScreen
= true ; // enter full-screen (via double-click on movie) for flash 9+ video
31 this . defaultOptions
= {
32 '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)
33 'stream' : true , // allows playing before entire file has loaded (recommended)
34 'autoPlay' : false , // enable playing of file as soon as possible (much faster if "stream" is true)
35 'onid3' : null , // callback function for "ID3 data is added/available"
36 'onload' : null , // callback function for "load finished"
37 'whileloading' : null , // callback function for "download progress update" (X of Y bytes received)
38 'onplay' : null , // callback for "play" start
39 'onpause' : null , // callback for "pause"
40 'onresume' : null , // callback for "resume" (pause toggle)
41 'whileplaying' : null , // callback during play (position update)
42 'onstop' : null , // callback for "user stop"
43 'onfinish' : null , // callback function for "sound finished playing"
44 'onbeforefinish' : null , // callback for "before sound finished playing (at [time])"
45 'onbeforefinishtime' : 5000 , // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)
46 'onbeforefinishcomplete' : null , // function to call when said sound finishes playing
47 'onjustbeforefinish' : null , // callback for [n] msec before end of current sound
48 'onjustbeforefinishtime' : 200 , // [n] - if not using, set to 0 (or null handler) and event will not fire.
49 'multiShot' : true , // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
50 'position' : null , // offset (milliseconds) to seek to within loaded sound data.
51 'pan' : 0 , // "pan" settings, left-to-right, -100 to 100
52 'volume' : 100 // self-explanatory. 0-100, the latter being the max.
55 this . flash9Options
= { // flash 9-only options, merged into defaultOptions if flash 9 is being used
56 'isMovieStar' : null , // "MovieStar" MPEG4 audio/video mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
57 'usePeakData' : false , // enable left/right channel peak (level) data
58 'useWaveformData' : false , // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.
59 'useEQData' : false , // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.
60 'onbufferchange' : null , // callback for "isBuffering" property change
61 'ondataerror' : null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
64 this . movieStarOptions
= { // flash 9.0r115+ MPEG4 audio/video options, merged into defaultOptions if flash 9 + movieStar mode is enabled
65 'onmetadata' : null , // callback for when video width/height etc. are received
66 'useVideo' : false , // if loading movieStar content, whether to show video
67 'bufferTime' : null // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try up to 3 seconds)
70 // jslint global declarations
71 /*global SM2_DEFER, sm2Debugger, alert, console, document, navigator, setTimeout, window */
73 var SMSound
= null ; // defined later
77 this . versionNumber
= 'V2.95a.20090501' ;
81 this . swfLoaded
= false ;
84 this . id
= ( smID
|| 'sm2movie' );
89 this . isFullScreen
= false ; // set later by flash 9+
90 this . isIE
= ( navigator
. userAgent
. match ( /MSIE/i ));
91 this . isSafari
= ( navigator
. userAgent
. match ( /safari/i ));
92 this . isGecko
= ( navigator
. userAgent
. match ( /gecko/i ));
93 this . debugID
= 'soundmanager-debug' ;
94 this . specialWmodeCase
= false ;
95 this . _debugOpen
= true ;
96 this . _didAppend
= false ;
97 this . _appendSuccess
= false ;
98 this . _didInit
= false ;
99 this . _disabled
= false ;
100 this . _windowLoaded
= false ;
101 this . _hasConsole
= ( typeof console
!= 'undefined' && typeof console
. log
!= 'undefined' );
102 this . _debugLevels
= [ 'log' , 'info' , 'warn' , 'error' ];
103 this . _defaultFlashVersion
= 8 ;
104 this . _oRemoved
= null ;
105 this . _oRemovedHTML
= null ;
107 var _
$ = function ( sID
) {
108 return document
. getElementById ( sID
);
111 this . filePatterns
= {
112 flash8 : /\.mp3(\?.*)?$/i ,
113 flash9 : /\.mp3(\?.*)?$/i
116 this . netStreamTypes
= [ 'aac' , 'flv' , 'mov' , 'mp4' , 'm4v' , 'f4v' , 'm4a' , 'mp4v' , '3gp' , '3g2' ]; // Flash v9.0r115+ "moviestar" formats
117 this . netStreamPattern
= new RegExp ( ' \\ .(' + this . netStreamTypes
. join ( '|' )+ ')( \\ ?.*)?$' , 'i' );
119 this . filePattern
= null ;
131 'remote' : 'remote (domain-based) rules' ,
132 'localWithFile' : 'local with file access (no internet access)' ,
133 'localWithNetwork' : 'local with network (internet access only, no local access)' ,
134 'localTrusted' : 'local, trusted (local + internet access)'
141 this . _setVersionInfo = function () {
142 if ( _s
. flashVersion
!= 8 && _s
. flashVersion
!= 9 ) {
143 alert ( 'soundManager.flashVersion must be 8 or 9. "' + _s
. flashVersion
+ '" is invalid. Reverting to ' + _s
. _defaultFlashVersion
+ '.' );
144 _s
. flashVersion
= _s
. _defaultFlashVersion
;
146 _s
. version
= _s
. versionNumber
+( _s
. flashVersion
== 9 ? ' (AS3/Flash 9)' : ' (AS2/Flash 8)' );
147 // set up default options
148 if ( _s
. flashVersion
> 8 ) {
149 _s
. defaultOptions
= _s
. _mergeObjects ( _s
. defaultOptions
, _s
. flash9Options
);
150 _s
. features
. buffering
= true ;
152 if ( _s
. flashVersion
> 8 && _s
. useMovieStar
) {
153 // flash 9+ support for movieStar formats as well as MP3
154 _s
. defaultOptions
= _s
. _mergeObjects ( _s
. defaultOptions
, _s
. movieStarOptions
);
155 _s
. filePatterns
. flash9
= new RegExp ( ' \\ .(mp3|' + _s
. netStreamTypes
. join ( '|' )+ ')( \\ ?.*)?$' , 'i' );
156 _s
. features
. movieStar
= true ;
158 _s
. useMovieStar
= false ;
159 _s
. features
. movieStar
= false ;
161 _s
. filePattern
= _s
. filePatterns
[( _s
. flashVersion
!= 8 ? 'flash9' : 'flash8' )];
162 _s
. movieURL
= ( _s
. flashVersion
== 8 ? 'soundmanager2.swf' : 'soundmanager2_flash9.swf' );
163 _s
. features
. peakData
= _s
. features
. waveformData
= _s
. features
. eqData
= ( _s
. flashVersion
> 8 );
166 this . _overHTTP
= ( document
. location
? document
. location
. protocol
. match ( /http/i ): null );
167 this . _waitingforEI
= false ;
168 this . _initPending
= false ;
169 this . _tryInitOnFocus
= ( this . isSafari
&& typeof document
. hasFocus
== 'undefined' );
170 this . _isFocused
= ( typeof document
. hasFocus
!= 'undefined' ? document
. hasFocus (): null );
171 this . _okToDisable
= ! this . _tryInitOnFocus
;
173 this . useAltURL
= ! this . _overHTTP
; // use altURL if not "online"
175 var flashCPLink
= 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html' ;
178 notReady : 'Not loaded yet - wait for soundManager.onload() before calling sound-related methods' ,
179 appXHTML : 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.'
182 // --- public methods ---
184 this . supported = function () {
185 return ( _s
. _didInit
&& ! _s
. _disabled
);
188 this . getMovie = function ( smID
) {
189 return _s
. isIE
? window
[ smID
]:( _s
. isSafari
? _
$( smID
)|| document
[ smID
]: _
$( smID
));
192 this . loadFromXML = function ( sXmlUrl
) {
194 _s
. o
. _loadFromXML ( sXmlUrl
);
201 this . createSound = function ( oOptions
) {
203 throw _s
. _complain ( 'soundManager.createSound(): ' + _s
. strings
. notReady
, arguments
. callee
. caller
);
205 if ( arguments
. length
== 2 ) {
206 // function overloading in JS! :) ..assume simple createSound(id,url) use case
207 oOptions
= { 'id' : arguments
[ 0 ], 'url' : arguments
[ 1 ]};
209 var thisOptions
= _s
. _mergeObjects ( oOptions
); // inherit SM2 defaults
210 var _tO
= thisOptions
; // alias
211 _s
. _wD ( 'soundManager.createSound(): ' + _tO
. id
+ ' (' + _tO
. url
+ ')' , 1 );
212 if ( _s
. _idCheck ( _tO
. id
, true )) {
213 _s
. _wD ( 'soundManager.createSound(): ' + _tO
. id
+ ' exists' , 1 );
214 return _s
. sounds
[ _tO
. id
];
216 if ( _s
. flashVersion
> 8 && _s
. useMovieStar
) {
217 if ( _tO
. isMovieStar
=== null ) {
218 _tO
. isMovieStar
= ( _tO
. url
. match ( _s
. netStreamPattern
)? true : false );
220 if ( _tO
. isMovieStar
) {
221 _s
. _wD ( 'soundManager.createSound(): using MovieStar handling' );
223 if ( _tO
. isMovieStar
&& ( _tO
. usePeakData
|| _tO
. useWaveformData
|| _tO
. useEQData
)) {
224 _s
. _wD ( 'Warning: peak/waveform/eqData features unsupported for non-MP3 formats' );
225 _tO
. usePeakData
= false ;
226 _tO
. useWaveformData
= false ;
227 _tO
. useEQData
= false ;
230 _s
. sounds
[ _tO
. id
] = new SMSound ( _tO
);
231 _s
. soundIDs
[ _s
. soundIDs
. length
] = _tO
. id
;
233 if ( _s
. flashVersion
== 8 ) {
234 _s
. o
. _createSound ( _tO
. id
, _tO
. onjustbeforefinishtime
);
236 _s
. o
. _createSound ( _tO
. id
, _tO
. url
, _tO
. onjustbeforefinishtime
, _tO
. usePeakData
, _tO
. useWaveformData
, _tO
. useEQData
, _tO
. isMovieStar
,( _tO
. isMovieStar
? _tO
. useVideo : false ),( _tO
. isMovieStar
? _tO
. bufferTime : false ));
238 if ( _tO
. autoLoad
|| _tO
. autoPlay
) {
239 // TODO: does removing timeout here cause problems?
240 if ( _s
. sounds
[ _tO
. id
]) {
241 _s
. sounds
[ _tO
. id
]. load ( _tO
);
245 _s
. sounds
[ _tO
. id
]. play ();
247 return _s
. sounds
[ _tO
. id
];
250 this . createVideo = function ( oOptions
) {
251 if ( arguments
. length
== 2 ) {
252 oOptions
= { 'id' : arguments
[ 0 ], 'url' : arguments
[ 1 ]};
254 if ( _s
. flashVersion
>= 9 ) {
255 oOptions
. isMovieStar
= true ;
256 oOptions
. useVideo
= true ;
258 _s
. _wD ( 'soundManager.createVideo(): flash 9 required for video. Exiting.' , 2 );
261 if (! _s
. useMovieStar
) {
262 _s
. _wD ( 'soundManager.createVideo(): MovieStar mode not enabled. Exiting.' , 2 );
264 return _s
. createSound ( oOptions
);
267 this . destroySound = function ( sID
, bFromSound
) {
268 // explicitly destroy a sound before normal page unload, etc.
269 if (! _s
. _idCheck ( sID
)) {
272 for ( var i
= 0 ; i
< _s
. soundIDs
. length
; i
++) {
273 if ( _s
. soundIDs
[ i
] == sID
) {
274 _s
. soundIDs
. splice ( i
, 1 );
278 // conservative option: avoid crash with ze flash 8
279 // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP + flash 8??
280 // if (_s.flashVersion != 8) {
281 _s
. sounds
[ sID
]. unload ();
284 // ignore if being called from SMSound instance
285 _s
. sounds
[ sID
]. destruct ();
287 delete _s
. sounds
[ sID
];
290 this . destroyVideo
= this . destroySound
;
292 this . load = function ( sID
, oOptions
) {
293 if (! _s
. _idCheck ( sID
)) {
296 _s
. sounds
[ sID
]. load ( oOptions
);
299 this . unload = function ( sID
) {
300 if (! _s
. _idCheck ( sID
)) {
303 _s
. sounds
[ sID
]. unload ();
306 this . play = function ( sID
, oOptions
) {
308 throw _s
. _complain ( 'soundManager.play(): ' + _s
. strings
. notReady
, arguments
. callee
. caller
);
310 if (! _s
. _idCheck ( sID
)) {
311 if ( typeof oOptions
!= 'Object' ) {
312 oOptions
= { url : oOptions
}; // overloading use case: play('mySound','/path/to/some.mp3');
314 if ( oOptions
&& oOptions
. url
) {
315 // overloading use case, creation + playing of sound: .play('someID',{url:'/path/to.mp3'});
316 _s
. _wD ( 'soundController.play(): attempting to create "' + sID
+ '"' , 1 );
318 _s
. createSound ( oOptions
);
323 _s
. sounds
[ sID
]. play ( oOptions
);
326 this . start
= this . play
; // just for convenience
328 this . setPosition = function ( sID
, nMsecOffset
) {
329 if (! _s
. _idCheck ( sID
)) {
332 _s
. sounds
[ sID
]. setPosition ( nMsecOffset
);
335 this . stop = function ( sID
) {
336 if (! _s
. _idCheck ( sID
)) {
339 _s
. _wD ( 'soundManager.stop(' + sID
+ ')' , 1 );
340 _s
. sounds
[ sID
]. stop ();
343 this . stopAll = function () {
344 _s
. _wD ( 'soundManager.stopAll()' , 1 );
345 for ( var oSound
in _s
. sounds
) {
346 if ( _s
. sounds
[ oSound
] instanceof SMSound
) {
347 _s
. sounds
[ oSound
]. stop (); // apply only to sound objects
352 this . pause = function ( sID
) {
353 if (! _s
. _idCheck ( sID
)) {
356 _s
. sounds
[ sID
]. pause ();
359 this . pauseAll = function () {
360 for ( var i
= _s
. soundIDs
. length
; i
--;) {
361 _s
. sounds
[ _s
. soundIDs
[ i
]]. pause ();
365 this . resume = function ( sID
) {
366 if (! _s
. _idCheck ( sID
)) {
369 _s
. sounds
[ sID
]. resume ();
372 this . resumeAll = function () {
373 for ( var i
= _s
. soundIDs
. length
; i
--;) {
374 _s
. sounds
[ _s
. soundIDs
[ i
]]. resume ();
378 this . togglePause = function ( sID
) {
379 if (! _s
. _idCheck ( sID
)) {
382 _s
. sounds
[ sID
]. togglePause ();
385 this . setPan = function ( sID
, nPan
) {
386 if (! _s
. _idCheck ( sID
)) {
389 _s
. sounds
[ sID
]. setPan ( nPan
);
392 this . setVolume = function ( sID
, nVol
) {
393 if (! _s
. _idCheck ( sID
)) {
396 _s
. sounds
[ sID
]. setVolume ( nVol
);
399 this . mute = function ( sID
) {
400 if ( typeof sID
!= 'string' ) {
404 _s
. _wD ( 'soundManager.mute(): Muting all sounds' );
405 for ( var i
= _s
. soundIDs
. length
; i
--;) {
406 _s
. sounds
[ _s
. soundIDs
[ i
]]. mute ();
410 if (! _s
. _idCheck ( sID
)) {
413 _s
. _wD ( 'soundManager.mute(): Muting "' + sID
+ '"' );
414 _s
. sounds
[ sID
]. mute ();
418 this . muteAll = function () {
422 this . unmute = function ( sID
) {
423 if ( typeof sID
!= 'string' ) {
427 _s
. _wD ( 'soundManager.unmute(): Unmuting all sounds' );
428 for ( var i
= _s
. soundIDs
. length
; i
--;) {
429 _s
. sounds
[ _s
. soundIDs
[ i
]]. unmute ();
433 if (! _s
. _idCheck ( sID
)) {
436 _s
. _wD ( 'soundManager.unmute(): Unmuting "' + sID
+ '"' );
437 _s
. sounds
[ sID
]. unmute ();
441 this . unmuteAll = function () {
445 this . getMemoryUse = function () {
446 if ( _s
. flashVersion
== 8 ) {
447 // not supported in Flash 8
451 return parseInt ( _s
. o
. _getMemoryUse (), 10 );
455 this . setPolling = function ( bPolling
) {
456 if (! _s
. o
|| ! _s
. allowPolling
) {
459 _s
. o
. _setPolling ( bPolling
);
462 this . disable = function ( bNoDisable
) {
463 // destroy all functions
464 if ( typeof bNoDisable
== 'undefined' ) {
471 _s
. _wD ( 'soundManager.disable(): Shutting down' , 1 );
472 for ( var i
= _s
. soundIDs
. length
; i
--;) {
473 _s
. _disableObject ( _s
. sounds
[ _s
. soundIDs
[ i
]]);
475 _s
. initComplete ( bNoDisable
); // fire "complete", despite fail
476 // _s._disableObject(_s); // taken out to allow reboot()
479 this . canPlayURL = function ( sURL
) {
480 return ( sURL
?( sURL
. match ( _s
. filePattern
)? true : false ): null );
483 this . getSoundById = function ( sID
, suppressDebug
) {
485 throw new Error ( 'SoundManager.getSoundById(): sID is null/undefined' );
487 var result
= _s
. sounds
[ sID
];
488 if (! result
&& ! suppressDebug
) {
489 _s
. _wD ( '"' + sID
+ '" is an invalid sound ID.' , 2 );
490 // soundManager._wD('trace: '+arguments.callee.caller);
495 this . onload = function () {
496 // window.onload() equivalent for SM2, ready to create sounds etc.
497 // this is a stub - you can override this in your own external script, eg. soundManager.onload = function() {}
498 soundManager
. _wD ( 'Warning: soundManager.onload() is undefined.' , 2 );
501 this . onerror = function () {
502 // stub for user handler, called when SM2 fails to load/init
505 // --- "private" methods ---
507 this . _idCheck
= this . getSoundById
;
509 this . _complain = function ( sMsg
, oCaller
) {
510 // Try to create meaningful custom errors, w/stack trace to the "offending" line
511 var sPre
= 'Error: ' ;
513 return new Error ( sPre
+ sMsg
);
515 var e
= new Error ( '' ); // make a mistake.
518 // potentially dangerous: Try to return a meaningful stacktrace where provided (Mozilla)
521 var stackTmp
= e
. stack
. split ( splitChar
);
522 stackMsg
= stackTmp
[ 4 ]; // try to return only the relevant bit, skipping internal SM2 shiz
528 if ( typeof console
!= 'undefined' && typeof console
. trace
!= 'undefined' ) {
531 var errorDesc
= sPre
+ sMsg
+ '. \n Caller: ' + oCaller
. toString ()+( e
. stack
? ' \n Top of stacktrace: ' + stackMsg :( e
. message
? ' \n Message: ' + e
. message : '' ));
532 // See JS error/debug/console output for real error source, stack trace / message detail where possible.
533 return new Error ( errorDesc
);
536 var _doNothing = function () {
540 _doNothing
. _protected
= true ;
542 this . _disableObject = function ( o
) {
543 for ( var oProp
in o
) {
544 if ( typeof o
[ oProp
] == 'function' && typeof o
[ oProp
]. _protected
== 'undefined' ) {
545 o
[ oProp
] = _doNothing
;
551 this . _failSafely = function ( bNoDisable
) {
552 // general failure exception handler
553 if ( typeof bNoDisable
== 'undefined' ) {
556 if (! _s
. _disabled
|| bNoDisable
) {
557 _s
. _wD ( 'soundManager: Failed to initialise.' , 2 );
558 _s
. disable ( bNoDisable
);
562 this . _normalizeMovieURL = function ( smURL
) {
563 var urlParams
= null ;
565 if ( smURL
. match ( /\.swf(\?.*)?$/i )) {
566 urlParams
= smURL
. substr ( smURL
. toLowerCase (). lastIndexOf ( '.swf?' )+ 4 );
568 return smURL
; // assume user knows what they're doing
570 } else if ( smURL
. lastIndexOf ( '/' ) != smURL
. length
- 1 ) {
574 return ( smURL
&& smURL
. lastIndexOf ( '/' )!=- 1 ? smURL
. substr ( 0 , smURL
. lastIndexOf ( '/' )+ 1 ): './' )+ _s
. movieURL
;
577 this . _getDocument = function () {
578 return ( document
. body
? document
. body :( document
. documentElement
? document
. documentElement : document
. getElementsByTagName ( 'div' )[ 0 ]));
581 this . _getDocument
. _protected
= true ;
583 this . _createMovie = function ( smID
, smURL
) {
584 if ( _s
. _didAppend
&& _s
. _appendSuccess
) {
585 return false ; // ignore if already succeeded
587 if ( window
. location
. href
. indexOf ( 'debug=1' )+ 1 ) {
588 _s
. debugMode
= true ; // allow force of debug mode via URL
590 _s
. _didAppend
= true ;
592 // safety check for legacy (change to Flash 9 URL)
593 _s
. _setVersionInfo ();
594 var remoteURL
= ( smURL
? smURL : _s
. url
);
595 var localURL
= ( _s
. altURL
? _s
. altURL : remoteURL
);
596 _s
. url
= _s
. _normalizeMovieURL ( _s
. _overHTTP
? remoteURL : localURL
);
599 var specialCase
= null ;
601 if ( _s
. useHighPerformance
&& _s
. useMovieStar
&& _s
. defaultOptions
. useVideo
=== true ) {
602 specialCase
= 'soundManager note: disabling highPerformance, not applicable with movieStar mode + useVideo' ;
603 _s
. useHighPerformance
= false ;
606 _s
. wmode
= (! _s
. wmode
&& _s
. useHighPerformance
&& ! _s
. useMovieStar
? 'transparent' : _s
. wmode
);
608 if ( _s
. wmode
!== null && _s
. flashLoadTimeout
!== 0 && ! _s
. useHighPerformance
&& ! _s
. isIE
&& navigator
. platform
. match ( /win32/i )) {
609 _s
. specialWmodeCase
= true ;
610 // extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here
611 // does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout
612 _s
. _wD ( 'soundManager note: Removing wmode, preventing off-screen SWF loading issue' );
616 if ( _s
. flashVersion
== 8 ) {
617 _s
. allowFullScreen
= false ;
627 allowScriptAccess : 'always' ,
629 pluginspage : 'http://www.macromedia.com/go/getflashplayer' ,
630 type : 'application/x-shockwave-flash' ,
632 allowfullscreen : ( _s
. allowFullScreen
? 'true' : 'false' )
636 delete oEmbed
. wmode
; // don't write empty attribute
642 type : 'application/x-shockwave-flash' ,
653 oMovie
= document
. createElement ( 'div' );
654 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
. wmode
? '<param name="wmode" value="' + _s
. wmode
+ '" /> ' : '' )+ '<param name="bgcolor" value="' + _s
. bgColor
+ '" /><param name="allowFullScreen" value="' +( _s
. allowFullScreen
? 'true' : 'false' )+ '" /><!-- --></object>' ;
656 oMovie
= document
. createElement ( 'embed' );
657 for ( tmp
in oEmbed
) {
658 if ( oEmbed
. hasOwnProperty ( tmp
)) {
659 oMovie
. setAttribute ( tmp
, oEmbed
[ tmp
]);
664 var oD
= document
. createElement ( 'div' );
665 oD
. id
= _s
. debugID
+ '-toggle' ;
675 border : '1px solid #999' ,
682 oD
. appendChild ( document
. createTextNode ( '-' ));
683 oD
. onclick
= _s
. _toggleDebug
;
684 oD
. title
= 'Toggle SM2 debug console' ;
686 if ( navigator
. userAgent
. match (/ msie
6 / i
)) {
687 oD
. style
. position
= 'absolute' ;
688 oD
. style
. cursor
= 'hand' ;
691 for ( tmp
in oToggle
) {
692 if ( oToggle
. hasOwnProperty ( tmp
)) {
693 oD
. style
[ tmp
] = oToggle
[ tmp
];
697 var oTarget
= _s
. _getDocument ();
701 _s
. oMC
= _
$( 'sm2-container' )? _
$( 'sm2-container' ): document
. createElement ( 'div' );
704 _s
. oMC
. id
= 'sm2-container' ;
705 _s
. oMC
. className
= 'movieContainer' ;
706 // "hide" flash movie
709 if ( _s
. useHighPerformance
) {
713 height : '8px' , // must be at least 6px for flash to run fast. odd? yes.
716 // zIndex:-1 // sit behind everything else - potentially dangerous/buggy?
720 position : 'absolute' ,
729 if ( s
. hasOwnProperty ( x
)) {
730 _s
. oMC
. style
[ x
] = s
[ x
];
735 _s
. oMC
. appendChild ( oMovie
);
737 oTarget
. appendChild ( _s
. oMC
);
739 oEl
= _s
. oMC
. appendChild ( document
. createElement ( 'div' ));
740 oEl
. className
= 'sm2-object-box' ;
741 oEl
. innerHTML
= movieHTML
;
743 _s
. _appendSuccess
= true ;
745 throw new Error ( _s
. strings
. appXHTML
);
748 // it's already in the document.
749 _s
. oMC
. appendChild ( oMovie
);
751 oEl
= _s
. oMC
. appendChild ( document
. createElement ( 'div' ));
752 oEl
. className
= 'sm2-object-box' ;
753 oEl
. innerHTML
= movieHTML
;
755 _s
. _appendSuccess
= true ;
758 if (! _
$( _s
. debugID
) && ((! _s
. _hasConsole
||! _s
. useConsole
)||( _s
. useConsole
&& _s
. _hasConsole
&& ! _s
. consoleOnly
))) {
759 var oDebug
= document
. createElement ( 'div' );
760 oDebug
. id
= _s
. debugID
;
761 oDebug
. style
. display
= ( _s
. debugMode
? 'block' : 'none' );
762 if ( _s
. debugMode
&& ! _
$( oD
. id
)) {
764 oTarget
. appendChild ( oD
);
766 throw new Error ( _s
. strings
. appXHTML
);
768 oTarget
. appendChild ( oDebug
);
778 _s
. _wD ( '-- SoundManager 2 ' + _s
. version
+( _s
. useMovieStar
? ', MovieStar mode' : '' )+( _s
. useHighPerformance
? ', high performance mode' : '' )+( _s
. wmode
? ', wmode: ' + _s
. wmode : '' )+ ' --' , 1 );
779 _s
. _wD ( 'soundManager._createMovie(): Trying to load ' + smURL
+(! _s
. _overHTTP
&& _s
. altURL
? ' (alternate URL)' : '' ), 1 );
782 // aliased to this._wD()
783 this . _writeDebug = function ( sText
, sType
, bTimestamp
) {
787 if ( typeof bTimestamp
!= 'undefined' && bTimestamp
) {
788 sText
= sText
+ ' | ' + new Date (). getTime ();
790 if ( _s
. _hasConsole
&& _s
. useConsole
) {
791 var sMethod
= _s
. _debugLevels
[ sType
];
792 if ( typeof console
[ sMethod
] != 'undefined' ) {
793 console
[ sMethod
]( sText
);
797 if ( _s
. useConsoleOnly
) {
801 var sDID
= 'soundmanager-debug' ;
807 var oItem
= document
. createElement ( 'div' );
808 if (++ _s
. _wdCount
% 2 === 0 ) {
809 oItem
. className
= 'sm2-alt' ;
811 // sText = sText.replace(/\n/g,'<br />');
812 if ( typeof sType
== 'undefined' ) {
815 sType
= parseInt ( sType
, 10 );
817 oItem
. appendChild ( document
. createTextNode ( sText
));
820 oItem
. style
. fontWeight
= 'bold' ;
823 oItem
. style
. color
= '#ff3333' ;
826 // o.appendChild(oItem); // top-to-bottom
827 o
. insertBefore ( oItem
, o
. firstChild
); // bottom-to-top
833 this . _writeDebug
. _protected
= true ;
835 this . _wdCount
. _protected
= true ;
836 this . _wD
= this . _writeDebug
;
838 this . _wDAlert = function ( sText
) { alert ( sText
); };
840 if ( window
. location
. href
. indexOf ( 'debug=alert' )+ 1 && _s
. debugMode
) {
841 _s
. _wD
= _s
. _wDAlert
;
844 this . _toggleDebug = function () {
845 var o
= _
$( _s
. debugID
);
846 var oT
= _
$( _s
. debugID
+ '-toggle' );
853 o
. style
. display
= 'none' ;
856 o
. style
. display
= 'block' ;
858 _s
. _debugOpen
= ! _s
. _debugOpen
;
861 this . _toggleDebug
. _protected
= true ;
863 this . _debug = function () {
864 _s
. _wD ( '--- soundManager._debug(): Current sound objects ---' , 1 );
865 for ( var i
= 0 , j
= _s
. soundIDs
. length
; i
< j
; i
++) {
866 _s
. sounds
[ _s
. soundIDs
[ i
]]. _debug ();
870 this . _debugTS = function ( sEventType
, bSuccess
, sMessage
) {
871 // troubleshooter debug hooks
872 if ( typeof sm2Debugger
!= 'undefined' ) {
874 sm2Debugger
. handleEvent ( sEventType
, bSuccess
, sMessage
);
881 this . _debugTS
. _protected
= true ;
883 this . _mergeObjects = function ( oMain
, oAdd
) {
884 // non-destructive merge
885 var o1
= {}; // clone o1
886 for ( var i
in oMain
) {
887 if ( oMain
. hasOwnProperty ( i
)) {
891 var o2
= ( typeof oAdd
== 'undefined' ? _s
. defaultOptions : oAdd
);
893 if ( o2
. hasOwnProperty ( o
) && typeof o1
[ o
] == 'undefined' ) {
900 this . createMovie = function ( sURL
) {
907 this . go
= this . createMovie
; // nice alias
909 this . _initMovie = function () {
910 // attempt to get, or create, movie
912 return false ; // may already exist
914 _s
. o
= _s
. getMovie ( _s
. id
); // (inline markup)
918 _s
. _createMovie ( _s
. id
, _s
. url
);
920 // try to re-append removed movie after reboot()
922 _s
. oMC
. appendChild ( _s
. oRemoved
);
924 _s
. oMC
. innerHTML
= _s
. oRemovedHTML
;
927 _s
. _didAppend
= true ;
929 _s
. o
= _s
. getMovie ( _s
. id
);
932 _s
. _wD ( 'soundManager._initMovie(): Got ' + _s
. o
. nodeName
+ ' element (' +( _s
. _didAppend
? 'created via JS' : 'static HTML' )+ ')' , 1 );
933 if ( _s
. flashLoadTimeout
> 0 ) {
934 _s
. _wD ( 'soundManager._initMovie(): Waiting for ExternalInterface call from Flash..' );
939 this . waitForExternalInterface = function () {
940 if ( _s
. _waitingForEI
) {
943 _s
. _waitingForEI
= true ;
944 if ( _s
. _tryInitOnFocus
&& ! _s
. _isFocused
) {
945 _s
. _wD ( 'soundManager: Special case: Waiting for focus-related event..' );
948 if ( _s
. flashLoadTimeout
> 0 ) {
950 _s
. _wD ( 'soundManager: Getting impatient, still waiting for Flash.. ;)' );
952 setTimeout ( function () {
954 _s
. _wD ( 'soundManager: No Flash response within reasonable time after document load. \n Possible causes: Loading ' + _s
. movieURL
+ ' failed, Flash version under ' + _s
. flashVersion
+ ', no support, flash blocked or JS-Flash security error.' , 2 );
956 _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 );
958 _s
. _debugTS ( 'flashtojs' , false , ': Timed out' +( _s
. _overHTTP
)? ' (Check flash security)' : ' (No plugin/missing SWF?)' );
960 // if still not initialized and no other options, give up
961 if (! _s
. _didInit
&& _s
. _okToDisable
) {
962 _s
. _failSafely ( true ); // don't disable, for reboot()
964 }, _s
. flashLoadTimeout
);
965 } else if (! _s
. didInit
) {
966 _s
. _wD ( 'soundManager: Waiting indefinitely for Flash...' );
970 this . handleFocus = function () {
971 if ( _s
. _isFocused
|| ! _s
. _tryInitOnFocus
) {
974 _s
. _okToDisable
= true ;
975 _s
. _isFocused
= true ;
976 _s
. _wD ( 'soundManager.handleFocus()' );
977 if ( _s
. _tryInitOnFocus
) {
978 // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented.
979 window
. removeEventListener ( 'mousemove' , _s
. handleFocus
, false );
981 // allow init to restart
982 _s
. _waitingForEI
= false ;
983 setTimeout ( _s
. waitForExternalInterface
, 500 );
985 if ( window
. removeEventListener
) {
986 window
. removeEventListener ( 'focus' , _s
. handleFocus
, false );
987 } else if ( window
. detachEvent
) {
988 window
. detachEvent ( 'onfocus' , _s
. handleFocus
);
992 this . initComplete = function ( bNoDisable
) {
997 _s
. _wD ( '-- SoundManager 2 ' +( _s
. _disabled
? 'failed to load' : 'loaded' )+ ' (' +( _s
. _disabled
? 'security/load error' : 'OK' )+ ') --' , 1 );
998 if ( _s
. _disabled
|| bNoDisable
) {
999 _s
. _wD ( 'soundManager.initComplete(): calling soundManager.onerror()' , 1 );
1000 _s
. _debugTS ( 'onload' , false );
1001 _s
. onerror
. apply ( window
);
1004 _s
. _debugTS ( 'onload' , true );
1006 if ( _s
. waitForWindowLoad
&& ! _s
. _windowLoaded
) {
1007 _s
. _wD ( 'soundManager: Waiting for window.onload()' );
1008 if ( window
. addEventListener
) {
1009 window
. addEventListener ( 'load' , _s
. initUserOnload
, false );
1010 } else if ( window
. attachEvent
) {
1011 window
. attachEvent ( 'onload' , _s
. initUserOnload
);
1015 if ( _s
. waitForWindowLoad
&& _s
. _windowLoaded
) {
1016 _s
. _wD ( 'soundManager: Document already loaded' );
1018 _s
. initUserOnload ();
1022 this . initUserOnload = function () {
1023 _s
. _wD ( 'soundManager.initComplete(): calling soundManager.onload()' , 1 );
1024 // call user-defined "onload", scoped to window
1025 _s
. onload
. apply ( window
);
1026 _s
. _wD ( 'soundManager.onload() complete' , 1 );
1029 this . init = function () {
1030 _s
. _wD ( '-- soundManager.init() --' );
1031 // called after onload()
1034 _s
. _wD ( 'soundManager.init(): Already called?' );
1038 if ( window
. removeEventListener
) {
1039 window
. removeEventListener ( 'load' , _s
. beginDelayedInit
, false );
1040 } else if ( window
. detachEvent
) {
1041 window
. detachEvent ( 'onload' , _s
. beginDelayedInit
);
1044 _s
. _wD ( 'Attempting to call Flash from JS..' );
1045 _s
. o
. _externalInterfaceTest ( false ); // attempt to talk to Flash
1046 // _s._wD('Flash ExternalInterface call (JS-Flash) OK',1);
1047 if (! _s
. allowPolling
) {
1048 _s
. _wD ( 'Polling (whileloading/whileplaying support) is disabled.' , 1 );
1050 _s
. setPolling ( true );
1051 if (! _s
. debugMode
) {
1052 _s
. o
. _disableDebug ();
1055 _s
. _debugTS ( 'jstoflash' , true );
1057 _s
. _debugTS ( 'jstoflash' , false );
1058 _s
. _failSafely ( true ); // don't disable, for reboot()
1065 this . beginDelayedInit = function () {
1066 _s
. _wD ( 'soundManager.beginDelayedInit()' );
1067 _s
. _windowLoaded
= true ;
1068 setTimeout ( _s
. waitForExternalInterface
, 500 );
1069 setTimeout ( _s
. beginInit
, 20 );
1072 this . beginInit = function () {
1073 if ( _s
. _initPending
) {
1076 _s
. createMovie (); // ensure creation if not already done
1078 _s
. _initPending
= true ;
1082 this . domContentLoaded = function () {
1083 _s
. _wD ( 'soundManager.domContentLoaded()' );
1084 if ( document
. removeEventListener
) {
1085 document
. removeEventListener ( 'DOMContentLoaded' , _s
. domContentLoaded
, false );
1090 this . _externalInterfaceOK = function () {
1091 // callback from flash for confirming that movie loaded, EI is working etc.
1095 _s
. _wD ( 'soundManager._externalInterfaceOK()' );
1096 _s
. _debugTS ( 'swf' , true );
1097 _s
. _debugTS ( 'flashtojs' , true );
1098 _s
. swfLoaded
= true ;
1099 _s
. _tryInitOnFocus
= false ;
1102 // IE needs a timeout OR delay until window.onload - may need TODO: investigating
1103 setTimeout ( _s
. init
, 100 );
1110 this . _setSandboxType = function ( sandboxType
) {
1111 var sb
= _s
. sandbox
;
1112 sb
. type
= sandboxType
;
1113 sb
. description
= sb
. types
[( typeof sb
. types
[ sandboxType
] != 'undefined' ? sandboxType : 'unknown' )];
1114 _s
. _wD ( 'Flash security sandbox type: ' + sb
. type
);
1115 if ( sb
. type
== 'localWithFile' ) {
1118 _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 );
1119 } else if ( sb
. type
== 'localWithNetwork' ) {
1120 sb
. noRemote
= false ;
1122 } else if ( sb
. type
== 'localTrusted' ) {
1123 sb
. noRemote
= false ;
1128 this . reboot = function () {
1129 // attempt to reset and init SM2
1130 _s
. _wD ( 'soundManager.reboot()' );
1131 if ( _s
. soundIDs
. length
) {
1132 _s
. _wD ( 'Destroying ' + _s
. soundIDs
. length
+ ' SMSound objects...' );
1134 for ( var i
= _s
. soundIDs
. length
; i
--;) {
1135 _s
. sounds
[ _s
. soundIDs
[ i
]]. destruct ();
1140 _s
. oRemovedHTML
= _s
. o
. innerHTML
;
1142 _s
. oRemoved
= _s
. o
. parentNode
. removeChild ( _s
. o
);
1143 _s
. _wD ( 'Flash movie removed.' );
1146 _s
. _wD ( 'Warning: Failed to remove flash movie.' , 2 );
1149 _s
. _didInit
= false ;
1150 _s
. _waitingForEI
= false ;
1151 _s
. _initPending
= false ;
1152 _s
. _didInit
= false ;
1153 _s
. _didAppend
= false ;
1154 _s
. _appendSuccess
= false ;
1155 _s
. _didInit
= false ;
1156 _s
. _disabled
= false ;
1157 _s
. _waitingforEI
= true ;
1158 _s
. swfLoaded
= false ;
1162 _s
. _wD ( 'soundManager: Rebooting...' );
1163 window
. setTimeout ( function () {
1164 soundManager
. beginDelayedInit ();
1168 this . destruct = function () {
1169 _s
. _wD ( 'soundManager.destruct()' );
1173 // SMSound (sound object)
1175 SMSound = function ( oOptions
) {
1177 this . sID
= oOptions
. id
;
1178 this . url
= oOptions
. url
;
1179 this . options
= _s
. _mergeObjects ( oOptions
);
1180 this . instanceOptions
= this . options
; // per-play-instance-specific options
1181 this . _iO
= this . instanceOptions
; // short alias
1183 // assign property defaults (volume, pan etc.)
1184 this . pan
= this . options
. pan
;
1185 this . volume
= this . options
. volume
;
1187 this . _lastURL
= null ;
1189 this . _debug = function () {
1194 var sfBracket
= null ;
1195 var maxLength
= 64 ; // # of characters of function code to show before truncating
1196 for ( stuff
in _t
. options
) {
1197 if ( _t
. options
[ stuff
] !== null ) {
1198 if ( _t
. options
[ stuff
] instanceof Function
) {
1199 // handle functions specially
1200 sF
= _t
. options
[ stuff
]. toString ();
1201 sF
= sF
. replace ( /\s\s+/g , ' ' ); // normalize spaces
1202 sfBracket
= sF
. indexOf ( '{' );
1203 msg
[ msg
. length
] = ' ' + stuff
+ ': {' + sF
. substr ( sfBracket
+ 1 ,( Math
. min ( Math
. max ( sF
. indexOf ( ' \n ' )- 1 , maxLength
), maxLength
))). replace ( /\n/g , '' )+ '... }' ;
1205 msg
[ msg
. length
] = ' ' + stuff
+ ': ' + _t
. options
[ stuff
];
1209 _s
. _wD ( 'SMSound() merged options: { \n ' + msg
. join ( ', \n ' )+ ' \n }' );
1217 Name/value pairs set via Flash when available - see reference for names:
1218 http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html
1219 (eg., this.id3.songname or this.id3['songname'])
1223 this . resetProperties = function ( bLoaded
) {
1224 _t
. bytesLoaded
= null ;
1225 _t
. bytesTotal
= null ;
1228 _t
. durationEstimate
= null ;
1232 _t
. readyState
= 0 ; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success
1234 _t
. didBeforeFinish
= false ;
1235 _t
. didJustBeforeFinish
= false ;
1236 _t
. isBuffering
= false ;
1237 _t
. instanceOptions
= {};
1238 _t
. instanceCount
= 0 ;
1250 _t
. resetProperties ();
1252 // --- public methods ---
1254 this . load = function ( oOptions
) {
1255 if ( typeof oOptions
!= 'undefined' ) {
1256 _t
. _iO
= _s
. _mergeObjects ( oOptions
);
1257 _t
. instanceOptions
= _t
. _iO
;
1259 oOptions
= _t
. options
;
1261 _t
. instanceOptions
= _t
. _iO
;
1263 // console.log('typeof oOptions: '+(typeof oOptions)+', lastURL: '+_t._lastURL+', _t.url: '+_t.url);
1265 if ( _t
. _lastURL
&& _t
. _lastURL
!= _t
. url
) {
1266 _s
. _wD ( 'SMSound.load(): Using manually-assigned URL' );
1267 _t
. _iO
. url
= _t
. url
;
1272 if ( typeof _t
. _iO
. url
== 'undefined' ) {
1273 _t
. _iO
. url
= _t
. url
;
1276 _s
. _wD ( 'soundManager.load(): ' + _t
. _iO
. url
, 1 );
1277 if ( _t
. _iO
. url
== _t
. url
&& _t
. readyState
!== 0 && _t
. readyState
!= 2 ) {
1278 _s
. _wD ( 'soundManager.load(): current URL already assigned.' , 1 );
1281 _t
. url
= _t
. _iO
. url
;
1282 _t
. _lastURL
= _t
. _iO
. url
;
1285 _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?)
1287 if ( _s
. flashVersion
== 8 ) {
1288 _s
. o
. _load ( _t
. sID
, _t
. _iO
. url
, _t
. _iO
. stream
, _t
. _iO
. autoPlay
,( _t
. _iO
. whileloading
? 1 : 0 ));
1290 _s
. o
. _load ( _t
. sID
, _t
. _iO
. url
, _t
. _iO
. stream
? true : false , _t
. _iO
. autoPlay
? true : false ); // ,(_tO.whileloading?true:false)
1291 if ( _t
. _iO
. isMovieStar
&& _t
. _iO
. autoLoad
&& ! _t
. _iO
. autoPlay
) {
1292 // special case: MPEG4 content must start playing to load, then pause to prevent playing.
1297 _s
. _wD ( 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.' , 2 );
1298 _s
. _debugTS ( 'onload' , false );
1305 this . unload = function () {
1306 // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3
1307 // Flash 9/AS3: Close stream, preventing further load
1308 if ( _t
. readyState
!== 0 ) {
1309 _s
. _wD ( 'SMSound.unload(): "' + _t
. sID
+ '"' );
1310 if ( _t
. readyState
!= 2 ) { // reset if not error
1311 _t
. setPosition ( 0 , true ); // reset current sound positioning
1313 _s
. o
. _unload ( _t
. sID
, _s
. nullURL
);
1314 // reset load/status flags
1315 _t
. resetProperties ();
1319 this . destruct = function () {
1320 // kill sound within Flash
1321 _s
. _wD ( 'SMSound.destruct(): "' + _t
. sID
+ '"' );
1322 _s
. o
. _destroySound ( _t
. sID
);
1323 _s
. destroySound ( _t
. sID
, true ); // ensure deletion from controller
1326 this . play = function ( oOptions
) {
1330 _t
. _iO
= _s
. _mergeObjects ( oOptions
, _t
. _iO
);
1331 _t
. _iO
= _s
. _mergeObjects ( _t
. _iO
, _t
. options
);
1332 _t
. instanceOptions
= _t
. _iO
;
1333 if ( _t
. playState
== 1 ) {
1334 var allowMulti
= _t
. _iO
. multiShot
;
1336 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" already playing (one-shot)' , 1 );
1339 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" already playing (multi-shot)' , 1 );
1343 if ( _t
. readyState
=== 0 ) {
1344 _s
. _wD ( 'SMSound.play(): Attempting to load "' + _t
. sID
+ '"' , 1 );
1345 // try to get this sound playing ASAP
1346 _t
. _iO
. stream
= true ;
1347 _t
. _iO
. autoPlay
= true ;
1348 // TODO: need to investigate when false, double-playing
1349 // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here
1350 _t
. load ( _t
. _iO
); // try to get this sound playing ASAP
1351 } else if ( _t
. readyState
== 2 ) {
1352 _s
. _wD ( 'SMSound.play(): Could not load "' + _t
. sID
+ '" - exiting' , 2 );
1355 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '" is loading - attempting to play..' , 1 );
1358 _s
. _wD ( 'SMSound.play(): "' + _t
. sID
+ '"' );
1364 if (! _t
. instanceCount
|| _s
. flashVersion
> 8 ) {
1367 _t
. position
= ( typeof _t
. _iO
. position
!= 'undefined' && ! isNaN ( _t
. _iO
. position
)? _t
. _iO
. position : 0 );
1368 if ( _t
. _iO
. onplay
) {
1369 _t
. _iO
. onplay
. apply ( _t
);
1371 _t
. setVolume ( _t
. _iO
. volume
, true ); // restrict volume to instance options only
1372 _t
. setPan ( _t
. _iO
. pan
, true );
1373 _s
. o
. _start ( _t
. sID
, _t
. _iO
. loop
|| 1 ,( _s
. flashVersion
== 9 ? _t
. position : _t
. position
/ 1000 ));
1377 this . start
= this . play
; // just for convenience
1379 this . stop = function ( bAll
) {
1380 if ( _t
. playState
== 1 ) {
1383 // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);
1384 if ( _t
. _iO
. onstop
) {
1385 _t
. _iO
. onstop
. apply ( _t
);
1387 _s
. o
. _stop ( _t
. sID
, bAll
);
1388 _t
. instanceCount
= 0 ;
1390 // _t.instanceOptions = _t._iO;
1394 this . setPosition = function ( nMsecOffset
, bNoDebug
) {
1395 if ( typeof nMsecOffset
== 'undefined' ) {
1398 var offset
= Math
. min ( _t
. duration
, Math
. max ( nMsecOffset
, 0 )); // position >= 0 and <= current available (loaded) duration
1399 _t
. _iO
. position
= offset
;
1401 // _s._wD('SMSound.setPosition('+nMsecOffset+')'+(nMsecOffset != offset?', corrected value: '+offset:''));
1403 _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
)
1406 this . pause = function () {
1407 if ( _t
. paused
|| _t
. playState
=== 0 ) {
1410 _s
. _wD ( 'SMSound.pause()' );
1412 _s
. o
. _pause ( _t
. sID
);
1413 if ( _t
. _iO
. onpause
) {
1414 _t
. _iO
. onpause
. apply ( _t
);
1418 this . resume = function () {
1419 if (! _t
. paused
|| _t
. playState
=== 0 ) {
1422 _s
. _wD ( 'SMSound.resume()' );
1424 _s
. o
. _pause ( _t
. sID
); // flash method is toggle-based (pause/resume)
1425 if ( _t
. _iO
. onresume
) {
1426 _t
. _iO
. onresume
. apply ( _t
);
1430 this . togglePause = function () {
1431 _s
. _wD ( 'SMSound.togglePause()' );
1432 if ( _t
. playState
=== 0 ) {
1433 _t
. play ({ position :( _s
. flashVersion
== 9 ? _t
. position : _t
. position
/ 1000 )});
1443 this . setPan = function ( nPan
, bInstanceOnly
) {
1444 if ( typeof nPan
== 'undefined' ) {
1447 if ( typeof bInstanceOnly
== 'undefined' ) {
1448 bInstanceOnly
= false ;
1450 _s
. o
. _setPan ( _t
. sID
, nPan
);
1452 if (! bInstanceOnly
) {
1457 this . setVolume = function ( nVol
, bInstanceOnly
) {
1458 if ( typeof nVol
== 'undefined' ) {
1461 if ( typeof bInstanceOnly
== 'undefined' ) {
1462 bInstanceOnly
= false ;
1464 _s
. o
. _setVolume ( _t
. sID
,( _s
. muted
&&! _t
. muted
)|| _t
. muted
? 0 : nVol
);
1465 _t
. _iO
. volume
= nVol
;
1466 if (! bInstanceOnly
) {
1471 this . mute = function () {
1473 _s
. o
. _setVolume ( _t
. sID
, 0 );
1476 this . unmute = function () {
1478 var hasIO
= typeof _t
. _iO
. volume
!= 'undefined' ;
1479 _s
. o
. _setVolume ( _t
. sID
, hasIO
? _t
. _iO
. volume : _t
. options
. volume
);
1482 // --- "private" methods called by Flash ---
1484 this . _whileloading = function ( nBytesLoaded
, nBytesTotal
, nDuration
) {
1485 if (! _t
. _iO
. isMovieStar
) {
1486 _t
. bytesLoaded
= nBytesLoaded
;
1487 _t
. bytesTotal
= nBytesTotal
;
1488 _t
. duration
= Math
. floor ( nDuration
);
1489 _t
. durationEstimate
= parseInt (( _t
. bytesTotal
/ _t
. bytesLoaded
)* _t
. duration
, 10 );
1490 if ( _t
. readyState
!= 3 && _t
. _iO
. whileloading
) {
1491 _t
. _iO
. whileloading
. apply ( _t
);
1494 _t
. bytesLoaded
= nBytesLoaded
;
1495 _t
. bytesTotal
= nBytesTotal
;
1496 _t
. duration
= Math
. floor ( nDuration
);
1497 _t
. durationEstimate
= _t
. duration
;
1498 if ( _t
. readyState
!= 3 && _t
. _iO
. whileloading
) {
1499 _t
. _iO
. whileloading
. apply ( _t
);
1504 this . _onid3 = function ( oID3PropNames
, oID3Data
) {
1505 // oID3PropNames: string array (names)
1506 // ID3Data: string array (data)
1507 _s
. _wD ( 'SMSound._onid3(): "' + this . sID
+ '" ID3 data received.' );
1509 for ( var i
= 0 , j
= oID3PropNames
. length
; i
< j
; i
++) {
1510 oData
[ oID3PropNames
[ i
]] = oID3Data
[ i
];
1511 // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);
1513 _t
. id3
= _s
. _mergeObjects ( _t
. id3
, oData
);
1515 _t
. _iO
. onid3
. apply ( _t
);
1519 this . _whileplaying = function ( nPosition
, oPeakData
, oWaveformDataLeft
, oWaveformDataRight
, oEQData
) {
1521 if ( isNaN ( nPosition
) || nPosition
=== null ) {
1522 return false ; // Flash may return NaN at times
1524 if ( _t
. playState
=== 0 && nPosition
> 0 ) {
1525 // can happen at the end of a video where nPosition == 33 for some reason, after finishing.???
1526 // can also happen with a normal stop operation. This resets the position to 0.
1527 // _s._writeDebug('Note: Not playing, but position = '+nPosition);
1530 _t
. position
= nPosition
;
1531 if ( _t
. _iO
. usePeakData
&& typeof oPeakData
!= 'undefined' && oPeakData
) {
1533 left : oPeakData
. leftPeak
,
1534 right : oPeakData
. rightPeak
1537 if ( _t
. _iO
. useWaveformData
&& typeof oWaveformDataLeft
!= 'undefined' && oWaveformDataLeft
) {
1539 left : oWaveformDataLeft
. split ( ',' ),
1540 right : oWaveformDataRight
. split ( ',' )
1543 if ( _t
. _iO
. useEQData
&& typeof oEQData
!= 'undefined' && oEQData
) {
1544 _t
. eqData
= oEQData
;
1546 if ( _t
. playState
== 1 ) {
1547 // special case/hack: ensure buffering is false (instant load from cache, thus buffering stuck at 1?)
1548 if ( _t
. isBuffering
) {
1549 _t
. _onbufferchange ( 0 );
1551 if ( _t
. _iO
. whileplaying
) {
1552 _t
. _iO
. whileplaying
. apply ( _t
); // flash may call after actual finish
1554 if ( _t
. loaded
&& _t
. _iO
. onbeforefinish
&& _t
. _iO
. onbeforefinishtime
&& ! _t
. didBeforeFinish
&& _t
. duration
- _t
. position
<= _t
. _iO
. onbeforefinishtime
) {
1555 _s
. _wD ( 'duration-position <= onbeforefinishtime: ' + _t
. duration
+ ' - ' + _t
. position
+ ' <= ' + _t
. _iO
. onbeforefinishtime
+ ' (' +( _t
. duration
- _t
. position
)+ ')' );
1556 _t
. _onbeforefinish ();
1561 this . _onload = function ( bSuccess
) {
1562 bSuccess
= ( bSuccess
== 1 ? true : false );
1563 _s
. _wD ( 'SMSound._onload(): "' + _t
. sID
+ '"' +( bSuccess
? ' loaded.' : ' failed to load? - ' + _t
. url
),( bSuccess
? 1 : 2 ));
1565 if ( _s
. sandbox
. noRemote
=== true ) {
1566 _s
. _wD ( 'SMSound._onload(): Reminder: Flash security is denying network/internet access' , 1 );
1568 if ( _s
. sandbox
. noLocal
=== true ) {
1569 _s
. _wD ( 'SMSound._onload(): Reminder: Flash security is denying local access' , 1 );
1572 _t
. loaded
= bSuccess
;
1573 _t
. readyState
= bSuccess
? 3 : 2 ;
1574 if ( _t
. _iO
. onload
) {
1575 _t
. _iO
. onload
. apply ( _t
);
1579 this . _onbeforefinish = function () {
1580 if (! _t
. didBeforeFinish
) {
1581 _t
. didBeforeFinish
= true ;
1582 if ( _t
. _iO
. onbeforefinish
) {
1583 _s
. _wD ( 'SMSound._onbeforefinish(): "' + _t
. sID
+ '"' );
1584 _t
. _iO
. onbeforefinish
. apply ( _t
);
1589 this . _onjustbeforefinish = function ( msOffset
) {
1590 // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187)
1591 if (! _t
. didJustBeforeFinish
) {
1592 _t
. didJustBeforeFinish
= true ;
1593 if ( _t
. _iO
. onjustbeforefinish
) {
1594 _s
. _wD ( 'SMSound._onjustbeforefinish(): "' + _t
. sID
+ '"' );
1595 _t
. _iO
. onjustbeforefinish
. apply ( _t
);
1600 this . _onfinish = function () {
1601 // sound has finished playing
1603 // TODO: calling user-defined onfinish() should happen after setPosition(0)
1604 // OR: onfinish() and then setPosition(0) is bad.
1605 if ( _t
. _iO
. onbeforefinishcomplete
) {
1606 _t
. _iO
. onbeforefinishcomplete
. apply ( _t
);
1608 // reset some state items
1609 _t
. didBeforeFinish
= false ;
1610 _t
. didJustBeforeFinish
= false ;
1611 if ( _t
. instanceCount
) {
1613 if (! _t
. instanceCount
) {
1614 // reset instance options
1615 // _t.setPosition(0);
1618 _t
. instanceCount
= 0 ;
1619 _t
. instanceOptions
= {};
1620 if ( _t
. _iO
. onfinish
) {
1621 _s
. _wD ( 'SMSound._onfinish(): "' + _t
. sID
+ '"' );
1622 _t
. _iO
. onfinish
. apply ( _t
);
1627 // video has finished
1628 // may need to reset position for next play call, "rewind"
1629 // _t.setPosition(0);
1631 // _t.setPosition(0);
1636 this . _onmetadata = function ( oMetaData
) {
1637 // movieStar mode only
1638 _s
. _wD ( 'SMSound.onmetadata()' );
1639 // Contains a subset of metadata. Note that files may have their own unique metadata.
1640 // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html
1641 if (! oMetaData
. width
&& ! oMetaData
. height
) {
1642 _s
. _wD ( 'No width/height given, assuming defaults' );
1643 oMetaData
. width
= 320 ;
1644 oMetaData
. height
= 240 ;
1646 _t
. metadata
= oMetaData
; // potentially-large object from flash
1647 _t
. width
= oMetaData
. width
;
1648 _t
. height
= oMetaData
. height
;
1649 if ( _t
. _iO
. onmetadata
) {
1650 _s
. _wD ( 'SMSound._onmetadata(): "' + _t
. sID
+ '"' );
1651 _t
. _iO
. onmetadata
. apply ( _t
);
1653 _s
. _wD ( 'SMSound.onmetadata() complete' );
1656 this . _onbufferchange = function ( bIsBuffering
) {
1657 if ( _t
. playState
=== 0 ) {
1658 // ignore if not playing
1661 if ( bIsBuffering
== _t
. isBuffering
) {
1662 // ignore initial "false" default, if matching
1663 _s
. _wD ( '_onbufferchange: ignoring false default / loaded sound' );
1666 _t
. isBuffering
= ( bIsBuffering
== 1 ? true : false );
1667 if ( _t
. _iO
. onbufferchange
) {
1668 _s
. _wD ( 'SMSound._onbufferchange(): ' + bIsBuffering
);
1669 _t
. _iO
. onbufferchange
. apply ( _t
);
1673 this . _ondataerror = function ( sError
) {
1674 // flash 9 wave/eq data handler
1675 if ( _t
. playState
> 0 ) { // hack: called at start, and end from flash at/after onfinish().
1676 _s
. _wD ( 'SMSound._ondataerror(): ' + sError
);
1677 if ( _t
. _iO
. ondataerror
) {
1678 _t
. _iO
. ondataerror
. apply ( _t
);
1681 // _s._wD('SMSound._ondataerror(): ignoring');
1687 this . _onfullscreenchange = function ( bFullScreen
) {
1688 _s
. _wD ( 'onfullscreenchange(): ' + bFullScreen
);
1689 _s
. isFullScreen
= ( bFullScreen
== 1 ? true : false );
1690 if (! _s
. isFullScreen
) {
1691 // attempt to restore window focus after leaving full-screen
1694 _s
. _wD ( 'window.focus()' );
1701 // register a few event handlers
1702 if ( window
. addEventListener
) {
1703 window
. addEventListener ( 'focus' , _s
. handleFocus
, false );
1704 window
. addEventListener ( 'load' , _s
. beginDelayedInit
, false );
1705 window
. addEventListener ( 'unload' , _s
. destruct
, false );
1706 if ( _s
. _tryInitOnFocus
) {
1707 window
. addEventListener ( 'mousemove' , _s
. handleFocus
, false ); // massive Safari focus hack
1709 } else if ( window
. attachEvent
) {
1710 window
. attachEvent ( 'onfocus' , _s
. handleFocus
);
1711 window
. attachEvent ( 'onload' , _s
. beginDelayedInit
);
1712 window
. attachEvent ( 'unload' , _s
. destruct
);
1714 // no add/attachevent support - safe to assume no JS -> Flash either.
1715 _s
. _debugTS ( 'onload' , false );
1716 soundManager
. onerror ();
1717 soundManager
. disable ();
1720 if ( document
. addEventListener
) {
1721 document
. addEventListener ( 'DOMContentLoaded' , _s
. domContentLoaded
, false );
1726 // set var SM2_DEFER = true; in your own script to prevent auto start-up
1727 if ( typeof SM2_DEFER
== 'undefined' || ! SM2_DEFER
) {
1728 soundManager
= new SoundManager ();